Re: [xsl] Find several different attribute values on many elements

Subject: Re: [xsl] Find several different attribute values on many elements
From: "dvint@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Thu, 8 Feb 2024 23:32:09 -0000
Here is where I'm at now

<xsl:variable name="ditacollectionString"
	select="concat($srcPath, '?select=(*.dita|*.xml)')"/>

<xsl:template match="/">

<xsl:variable name="CONDITIONS" >
	<xsl:for-each
		select="collection($ditacollectionString)/*" >
		<xsl:apply-templates mode="conditions"/>
	</xsl:for-each>
</xsl:variable>

<xsl:for-each select="distinct-values(tokenize($CONDITIONS, ' '))">
	<xsl:sort/>
	<xsl:if test="not(. ='')">
		<xsl:value-of select="$spaceTAB"/>
		<xsl:value-of select="$spaceTAB"/>
		<xsl:value-of select="."/><xsl:text>:     true</xsl:text>
		<xsl:value-of select="$RETURN"/>
	</xsl:if>
</xsl:for-each>
</xsl:template>

<xsl:template match="text()" mode="conditions"/>

	<xsl:template match="p" mode="conditions">
		<xsl:if test="@product">
			<xsl:value-of select="concat(@product, ' ')"/>
		</xsl:if>
		<xsl:if test="@audience">
			<xsl:value-of select="concat(@audience, ' ')"/>
		</xsl:if>
		<xsl:if test="@platform">
			<xsl:value-of select="concat(@platform, ' ')"/>
		</xsl:if>
		<xsl:if test="@props">
			<xsl:value-of select="concat(@props, ' ')"/>
		</xsl:if>
		<xsl:if test="@otherprops">
			<xsl:value-of select="concat(@otherprops, ' ')"/>
		</xsl:if>
		<xsl:if test="@rev">
			<xsl:value-of select="concat(@rev, ' ')"/>
		</xsl:if>

</xsl:template>

This is working fine when I have the template match on "p". My problem is these attributes can appear on all of the elements in the content and more than one can appear on a given element.

So I tried substitution p with element() and with * and those fail to produce anything.

Various forms of this didn't work either

	<xsl:template match="p/@product | p/@audience" mode="conditions">
		<xsl:value-of select="concat(., ' ')"/>
	</xsl:template>

Thoughts?

..dan
On 2024-02-08 14:28, Piez, Wendell A. (Fed) wendell.piez@xxxxxxxx wrote:
Hi Dan,

There are a bunch of things I might change about this approach, but
the error you are getting could be addressed (simply enough, I think)
by changing your template matching "@product | @audience" to match
strings instead -- or even untyped atomic values, if that's what
distinct-values() is returning. (I haven't looked it up but I think
it's strings.)

Try match=".[. instance of xs:string]" or just plain match="." on that
template in mode 'conditions' and see what happens.

There are other reasons it could be slow or things I might do
differently, but I'll leave those comments aside for now or for
others.

Cheers, Wendell



-----Original Message-----
From: dvint@xxxxxxxxx <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Sent: Thursday, February 8, 2024 5:12 PM
To: xsl <xsl-list@xxxxxxxxxxxxxxxxxxxxxx>
Subject: [xsl] Find several different attribute values on many elements

I'm trying to process a collection of documents and extract the
distinct-values for several attributes. My first attempt was this
which is very slow

        <xsl:variable name="ditacollectionString"
                select="concat($srcPath, '?select=*.dita')"/>

        <xsl:variable name="xmlcollectionString"
                select="concat($srcPath, '?select=*.xml')"/>

<xsl:for-each

select="distinct-values(collection($ditacollectionString)//*/@audience)"
 >
                        <xsl:value-of select="concat(., ' ')"/>
                </xsl:for-each>
                <xsl:for-each

select="distinct-values(collection($ditacollectionString)//*/@platform)"
 >
                        <xsl:value-of select="concat(., ' ')"/>
                </xsl:for-each>
                <xsl:for-each

select="distinct-values(collection($ditacollectionString)//*/@props)"
 >
                        <xsl:value-of select="concat(., ' ')"/>
                </xsl:for-each>

I'm looking for a way to just make a single for-each loop and tried this

<xsl:for-each

select="distinct-values(collection($ditacollectionString)//element())"
>
<xsl:apply-templates mode="conditions"/>


</xsl:for-each>

        <xsl:template match="@product | @audience " mode="conditions">
                <xsl:value-of select="concat(., ' ')"/>
        </xsl:template>

But I get an error on the <xsl:apply-templates mode="conditions"/>
indicating The required item type of the context item is node(), but
the supplied expression {.} has item type xs:anyAtomicType.

I also need to do this with both .dita and .xml files and I'm planning
on making 2 collections, is there a way to do one collection()?

Current Thread