Re: [xsl] Making a lookup structure from multiple documents

Subject: Re: [xsl] Making a lookup structure from multiple documents
From: "Martin Honnen martin.honnen@xxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 12 Jun 2023 14:17:30 -0000
On 6/12/2023 2:17 PM, rick@xxxxxxxxxxxxxx wrote:
>
> I have a ditamap that has references to child topics, and each child
> topic may references to other topics. I need to collect the contents
> of three particular elements, then then use them in a summary in one
> of the documents. Here is my basic shell, where I am navigating
> through all of the referenced documents. I also have a template for
> the items I am trying to collect (I can combine them into a single
> template). I am looking for the best approach for making a lookup of
> items that can be used later in the processing. Thank you.
>

It gather you want to collect/store the data from the elements tools,
spares, supplies. It is not quite clear on what kind of key(s) you later
want to look up the collected values.


Anyway, Chris already suggested maps as a facility in XSLT 3 to store
stuff for lookup.

In the context of your code I am wondering whether it makes sense to set
up an accumulator that does all the heavy lifting/recollection of the
data from the referenced docs; see below inline for some ideas:

>
> <?xml version="1.0" encoding="UTF-8"?>
>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>
> xmlns:xs="http://www.w3.org/2001/XMLSchema";
>
> xmlns:math="http://www.w3.org/2005/xpath-functions/math";
>
> B B B  exclude-result-prefixes="xs math"
>
> B B B  version="3.0" expand-text="yes">
>
> B B B B <xsl:output indent="yes"/>
>
> B B B B <xsl:template match="/">
>
> B B B B B B B  <xsl:apply-templates/>
>
> B B B  </xsl:template>
>
> B B B B <xsl:template
> match="@href[matches(.,'(dita(map)?|xml)$','i')=true()]">
>
> B B B B B B B  <xsl:if test="doc-available(.)">
>
> <xsl:message>{.}</xsl:message>
>
> B B B B B B B B B B B  <xsl:variable name="refdoc" select="doc(.)"/>
>
> B B B B B B B B B B B  <xsl:apply-templates select="$refdoc/*"/>
>
> B B B B B B B  </xsl:if>
>
> B B B  </xsl:template>
>

I think accumulators need to be attached to element nodes not attributes
so I would think that e.g.

 B  <xsl:accumulator name="lookup" as="map(*)" initial-value="map{}">

 B B  <xsl:accumulator-rule
match="*[@href[matches(.,'(dita(map)?|xml)$','i')=true()][doc-available(.)]]"
>

 B B B  <xsl:variable name="collected" as="map(*)*">

 B B B B B  <xsl:apply-templates select="doc(@href)/*"/>

 B B B  </xsl:variable>

 B B B  <xsl:sequence select="map:merge(($value, $collected))"/>

 B B  </xsl:accumulator-rule>

</xsl:accumulator>


Make sure the the main mode uses the accumulator e.g. <xsl:mode
use-accumulators="lookup"/>


> B B B B <xsl:template match="tools">
>
> B B B B B B B  <xsl:message>{local-name() || ' ' || base-uri(.) || ' ' ||
> .}</xsl:message>
>
> B B B  </xsl:template>
>

Now here construct the map/lookup entry you need, I don't have a clear
idea what would be your key perhaps e.g.

 B  <xsl:template match="tools">

 B B B  <xsl:map-entry key="base-uri() || ':' || local-name()"
select="string()"/>

 B  </xsl:template>


For sanity I would consider doing the processing of the referenced
documents for the map/lookup data in a different mode.


> B B B  <xsl:template match="spares">
>
> B B B B B B B  <xsl:message>{local-name() || ' ' || base-uri(.) || ' ' ||
> .}</xsl:message>
>
> B B B  </xsl:template>
>
> B B B B <xsl:template match="supplies">
>
> B B B B B B B  <xsl:message>{local-name() || ' ' || base-uri(.) || ' ' ||
> .}</xsl:message>
>
> B B B  </xsl:template>
>
> B B B B <xsl:mode on-no-match="shallow-skip"/>
>
> </xsl:stylesheet>

Current Thread