xsl-list
[Top] [All Lists]

Re: [xsl] constructing arrays in XSLT with templates

2021-06-18 16:46:34
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(_dot_)painter(_at_)gmail(_dot_)com 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> 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 <>)
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--
<Prev in Thread] Current Thread [Next in Thread>