Re: [xsl] constructing arrays in XSLT with templates

Subject: Re: [xsl] constructing arrays in XSLT with templates
From: "Martin Honnen martin.honnen@xxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 19 Jun 2021 09:25:39 -0000
Am 19.06.2021 um 10:54 schrieb Alan Painter alan.painter@xxxxxxxxx:
But I'm wondering what the equivalent would be for conditional map
entries.


Supposing that there is an additional optional attribute on the 'book' element of the original xml, 'out-of-print="true"'. Furthermore, let's say that the JSON maps in the 'books' array contain an additional field when a book is out of print.

In XSLT map entries, you can write:

<xsl:map>
B B B <xsl:map-entry key="'title'"B B select="title!string()"B B B B
B
B  B  />
B  B  B  <xsl:map-entry key="'authors'" select="array { ./author!string()
}" />

B  B  B  <xsl:if test="@out-of-print andB @out-of-print eq 'true'" >
B  B  B  B  B B <xsl:map-entry key="'out-of-print'" select="true()" />
B  B  B  </xsl:if>
</xsl:map>

But I'm thinking that there is not a way to express this with the 'map
{ ... }' form in xpath.

map {
B  B  'title'B  B  B  B  : title!string(),
B  B  'authors'B  B  B  : array { author/string() },
B  ( 'out-of-print' : true() )[@out-of-print and @out-of-print eq 'true']
}

Is there any way of doing something like this using in-line xpath?


My first instinct would be that the data is more consistent if you just do


B <xsl:template match="/"> B B B <xsl:sequence B B B B B select="map { B B B B B B B B B B B B B B 'books' : array { B B B B B B B B B B B B B B B B B books/book ! map { B B B B B B B B B B B B B B B B B B B 'title' : title!string(), B B B B B B B B B B B B B B B B B B B 'authors' : array { author/string() }, B B B B B B B B B B B B B B B B B B B 'out-of-print' : @out-of-print = 'true' B B B B B B B B B B B B B B B B B } B B B B B B B B B B B B B B B } B B B B B B B B B B B B B }"/> B </xsl:template>


i.e. give any map representing a book a property of the name out-of-print with the right value.


Otherwise I think you can use map:merge



B <xsl:template match="/"> B B B <xsl:sequence B B B B B select="map { B B B B B B B B B B B B B B 'books' : array { B B B B B B B B B B B B B B B B B books/book ! B B B B B B B B B B B B B B B B B B B map:merge(( B B B B B B B B B B B B B B B B B B B B B map { B B B B B B B B B B B B B B B B B B B B B B B 'title' : title!string(), B B B B B B B B B B B B B B B B B B B B B B B 'authors' : array { author/string() } B B B B B B B B B B B B B B B B B B B B B }, B B B B B B B B B B B B B B B B B B B B B @out-of-print ! map:entry(local-name(), boolean(.))) B B B B B B B B B B B B B B B B B B B ) B B B B B B B B B B B B B B B B B } B B B B B B B B B B B B B }"/> B </xsl:template>


with xmlns:map="http://www.w3.org/2005/xpath-functions/map";


Current Thread