Re: [xsl] constructing arrays in XSLT with templates

Subject: Re: [xsl] constructing arrays in XSLT with templates
From: "Michael Kay mike@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 18 Jun 2021 21:46:29 -0000
Unfortunately this is a significant gap in XSLT 3.0 functionality.

The explanation for the gap is that the WG was reluctant to make XSLT 3.0
dependent on XPath 3.1 as distinct from XPath 3.0, and arrays only came with
3.1.

There are workarounds, of course, but they aren't particularly nice.

Michael Kay
Saxonica

> On 18 Jun 2021, at 19:40, Alan Painter alan.painter@xxxxxxxxx
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
>
> Hi fellow XSLT enthusiasts,
>
> I've been constructing json in XSLT using xsl:map and xsl:map-entry and the
resulting code looks really nice.  But I'm a bit stuck with arrays and was
hoping for some enlightenment.
>
> Taking as input example:
>
> <books>
>   <book>
>     <title>The C Programming Language</title>
>     <author>Brian Kernighan</author>
>     <author>Dennis Ritchie</author>
>   </book>
>   <book>
>     <title>Principles of Compiler Design</title>
>     <author>Alfred V. Aho</author>
>     <author>Jeffrey D. Ullman</author>
>     <author>J. E. Hopcrof</author>
>   </book>
> </books>
>
> And using this stylesheet to construct a JSON representation:
>
> <?xml version="1.0" encoding="utf-8"?>
> <xsl:stylesheet
>   xmlns:xsl="http://www.w3.org/1999/XSL/Transform
<http://www.w3.org/1999/XSL/Transform>"
>   version="3.0">
>
>   <xsl:mode on-no-match="fail"/>
>
>   <xsl:output method="json" indent="yes" />
>
>   <xsl:template match="/" >
>     <xsl:map>
>       <xsl:apply-templates select="books" />
>     </xsl:map>
>   </xsl:template>
>
>   <xsl:template match="/books">
>     <xsl:variable name="books" as="map(*)*">
>       <xsl:apply-templates select="book" />
>     </xsl:variable>
>     <xsl:map-entry key="'books'" select="array { $books } "/>
>   </xsl:template>
>
>   <xsl:template match="book" as="map(*)">
>     <xsl:map>
>       <xsl:map-entry key="'title'" select="title!string()" />
>       <xsl:map-entry key="'authors'" select="array { ./author!string() } "/>
>     </xsl:map>
>   </xsl:template>
>
> </xsl:stylesheet>
>
> Within the template for "/books" I find that I have to declare a variable in
order to represent the sequence of maps that come from the nested
apply-templates.
>
> I'd like to be able to do away with the intermediate $books variable which
is used for the purpose of constructing the array using the xpath "array { ...
}" expression.
>
> Is there a more elegant way of doing this?
>
> thanks for any pointers and best regards
>
> -alan
>
> XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>
> EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/293509> (by
email <>)

Current Thread