[xsl] constructing arrays in XSLT with templates

Subject: [xsl] constructing arrays in XSLT with templates
From: "Alan Painter alan.painter@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 18 Jun 2021 18:40:09 -0000
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";
  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

Current Thread