Re: [xsl] Techniques for Sorting and Reducing Maps in XSLT 3/XPath 3?

Subject: Re: [xsl] Techniques for Sorting and Reducing Maps in XSLT 3/XPath 3?
From: "Michael Kay mike@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Thu, 19 Jul 2018 13:19:33 -0000
Looks good.

Don't forget that

map:get(., 'version')

can be written

?version

and

>  $courses-for-locale !
>               (if (map:get(., 'version') eq $highest-version)
>                then .
>                else ()

can be written

$courses-for-locale[?version eq $highest-version]

Michael Kay
Saxonica


> On 19 Jul 2018, at 13:16, Eliot Kimber ekimber@xxxxxxxxxxxx
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
>
> Here is my current solution, which is definitely an improvement over my
earlier solution. I hadnbt realized (or it didnbt occur to me) that I
could use for-each-group on maps. Using for-each-group and grouping by a
specific field is certainly easy and straightforward:
>
> For this data, the paths provide the course details, in particular, course
ID and locale. I also have to eliminate config.xml files that are not the ones
Ibm looking for, which I do just by counting the number of tokens in the
path.
>
>     <xsl:variable name="candidate-configs" as="map(*)*"
>       select="collection($courses-dir ||
'?recurse=yes;metadata=yes;match=config.xml')"
>     />
>
>     <!-- Select configurations that are in the appropriate locale and that
>          are course configurations and not course content configurations
(config.xml
>          is used both for course description and within the course content
directory).
>
>          Result is a sequence of maps, one for each selected candidate
course.
>       -->
>     <xsl:variable name="configs-to-use" as="map(*)*">
>       <xsl:for-each select="$candidate-configs">
>         <xsl:variable name="cand" as="map(*)" select="."/>
>         <xsl:variable name="path-base" as="xs:string" select="$cand?name"/>
>         <xsl:variable name="path" as="xs:string"
select="substring-after($path-base, $courses-dir || '/')"/>
>         <xsl:variable name="tokens" as="xs:string*" select="tokenize($path,
'/')"/>
>         <xsl:variable name="course-group" as="xs:string"
select="$tokens[1]"/>
>         <xsl:variable name="course-id" as="xs:string" select="$tokens[2]"/>
>         <xsl:variable name="locale" as="xs:string" select="$tokens[3]"/>
>         <xsl:variable name="version" as="xs:string" select="$tokens[4]"/>
>         <xsl:variable name="new-map" as="map(*)"
>           select="
>           map{
>           'course-group' : $course-group,
>           'course-id' : $course-id,
>           'locale' : $locale,
>           'version' : $version,
>           'course-key' : ($course-group, $course-id) => string-join('^'),
>           'course-key-locale' : ($course-group, $course-id, $locale) =>
string-join('^')
>           }"
>         />
>         <xsl:if test="(empty($locales) or (exists($locales) and $locale =
$locales)) and count($tokens) eq 6">
>           <xsl:sequence select="map:merge((., $new-map))"/>
>         </xsl:if>
>       </xsl:for-each>
>     </xsl:variable>
>
>     <!-- Now group by course ID and locale in order to select the highest
version of each course. -->
>     <xsl:variable name="course-configs-by-course-key-locale"
as="map(xs:string, map(*))">
>       <xsl:map>
>         <xsl:for-each-group select="$configs-to-use"
group-by=".?course-key-locale">
>           <xsl:variable name="courses-for-locale" as="map(*)*"
select="current-group()"/>
>           <xsl:variable name="highest-version" as="xs:string"
>             select="$courses-for-locale ! map:get(., 'version') !
xs:double(.) => max() => format-number('#.0')"
>           />
>           <xsl:variable name="course-map" as="map(*)*"
>             select="
>               $courses-for-locale !
>               (if (map:get(., 'version') eq $highest-version)
>                then .
>                else ()
>               )"
>           />
>           <xsl:sequence select="map:entry(current-grouping-key(),
$course-map)"/>
>         </xsl:for-each-group>
>       </xsl:map>
>     </xsl:variable>
>
> Cheers,
>
> E.
> --
> Eliot Kimber
> http://contrext.com <http://contrext.com/>
>
>
>
> From: "Mukul Gandhi gandhi.mukul@xxxxxxxxx <mailto:gandhi.mukul@xxxxxxxxx>"
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx
<mailto:xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>>
> Reply-To: <xsl-list@xxxxxxxxxxxxxxxxxxxxxx
<mailto:xsl-list@xxxxxxxxxxxxxxxxxxxxxx>>
> Date: Saturday, July 7, 2018 at 2:01 AM
> To: <xsl-list@xxxxxxxxxxxxxxxxxxxxxx
<mailto:xsl-list@xxxxxxxxxxxxxxxxxxxxxx>>
> Subject: Re: [xsl] Techniques for Sorting and Reducing Maps in XSLT 3/XPath
3?
>
> On Fri, Jul 6, 2018 at 9:58 PM, Liam R. E. Quin liam@xxxxxx
<mailto:liam@xxxxxx> <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx
<mailto:xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>> wrote:
>> On your xsl:iterate question, i'd generally try for-each and/or for-
>> each-group before xsl:iterate. The reason is largely that i think it
>> encourage thinking in terms of a functional mapping rather than an
>> imperative loop, and that can help clarity of thought.
>
>  I'm still not up to speed with using XSLT 3.0 (but I'm trying to). But I
agree with your point Liam.
>
>
>
>
> --
> Regards,
> Mukul Gandhi
> XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>
> EasyUnsubscribe <x-msg://101/-list/1278982> (by email
<applewebdata://09520B08-E59F-4D3A-AE57-ACF7B6C75260>)
> XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>
> EasyUnsubscribe <-list/293509> (by email <>)

Current Thread