Loren Shaw
Loren Shaw

Reputation: 466

Count results from foreach from keyed results in XSLT

I have the below code:

<xsl:key name="propRecType" match="RecordType" use="."/>

<xsl:template name="DisplayCodeCount">
    <xsl:variable name="TypeRecords" >
        <xsl:for-each select="Records/Record/ReportRecords/ReportRecord/RecordType[generate-id() = generate-id(key('propRecType', .))]">
            <xsl:copy-of select="."/>
        </xsl:for-each>
    </xsl:variable>

    <div>
        Test<br/>
        <xsl:value-of select="$TypeRecords"/>
        <xsl:value-of select="count($TypeRecords)"/>
    </div>
</xsl:template>

The issue is the count function throws the following exception:

System.Xml.Xsl.XslTransformException: To use a result tree fragment in a path expression, first convert it to a node-set using the msxsl:node-set() function.

I have a condition where I need this count value do determine other data that may or may not need to be displayed. The only other option I have is to check for specific values, which will cause issues in the future if other codes are supplied.

The key does give me the distinct values I'm looking for, so that is working as expected.

Upvotes: 0

Views: 269

Answers (1)

Tim C
Tim C

Reputation: 70648

The issue is that because you are creating copies of nodes, the TypeRecords is holding a "result tree fragment", and you can't apply XPath navigation to a such variables.

Now, you could use an extension function to turn the Result Tree Fragment into the node set. This involves declaring the relevant namespace

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common">

And then, you can use the node-set function when you want to access the variable

    <xsl:value-of select="exsl:node-set($TypeRecords)"/>
    <xsl:value-of select="count(exsl:node-set($TypeRecords)/RecordType)"/>

See http://www.xml.com/pub/a/2003/07/16/nodeset.html for information.

But... There is no need to use the node-set function in this case. Simply change your variable declaration to this:

<xsl:variable name="TypeRecords"  
     select="Records/Record/ReportRecords/ReportRecord/RecordType[generate-id() = generate-id(key('propRecType', .))]" />

The variable is now referencing nodes in the source XML directly, and not creating copies. Because there are the source nodes, you can use xpath functions as normal, without the need for the node-set function.

Upvotes: 1

Related Questions