SeB
SeB

Reputation: 33

XSL : how to select a unique nodes in a nodeset

I have been reading on the different question talking about selecting unique nodes in a document (using the Muenchian method) but in my case I cannot use keys (or I do not know how) because I am working on a node set and not on the document.

And keys cannot be set on a node-set. Basically I have a variable:

<xsl:variable name="limitedSet" select="
  $deviceInstanceNodeSet[position() &lt;= $tableMaxCol]" 
/>

which contains <deviceInstance> nodes which themselves containing <structure> elements the node set may be represented this way:

<deviceInstance name="Demux TSchannel" deviceIndex="0">
  <structure name="DemuxTschannelCaps">
  </structure>
</deviceInstance>
<deviceInstance name="Demux TSchannel" deviceIndex="1">
  <structure name="DemuxTschannelCaps">
  </structure>
</deviceInstance>
<deviceInstance name="Demux TSchannel" deviceIndex="3">
  <structure name="otherCaps">
  </structure>
</deviceInstance>

And I do not know a to select <structure> elements that only have different name. The select would in this example return two <structure> elements, being:

<structure name="DemuxTschannelCaps"></structure>
<structure name="otherCaps"></structure>

I have tried

select="$limitedSet//structure[not(@name=preceding::structure/@name)]"  

but the preceding axis goes all along the document and not the $limitedSet?

I am stuck, can someone help me. Thank you.

Upvotes: 3

Views: 2444

Answers (2)

Pavel Minaev
Pavel Minaev

Reputation: 101595

select="$limitedSet//structure[not(@name=preceding::structure[count($limitedSet) = count($limitedSet | ..)]/@name)]"

Upvotes: 1

Tomalak
Tomalak

Reputation: 338248

<xsl:variable name="structure" select="$limitedSet//structure" />

<xsl:for-each select="$structure">
  <xsl:variable name="name" select="@name" />
  <xsl:if test="generate-id() = generate-id($structure[@name = $name][1])">
    <xsl:copy-of select="." />
  </xsl:if>
</xsl:for-each>

This could be aided by a key:

<xsl:key name="kStructureByName" match="structure" use="@name" />
<!-- ... -->
<xsl:if test="generate-id() = generate-id(key('kStructureByName', $name)[1])">

Depending on your input, the key would have to capture some additional contextual information:

<xsl:key name="kStructureByName" match="structure" use="
  concat(ancestor::device[1]/@id, ',', @name)
" />
<!-- ... -->
<xsl:variable name="name" select="concat(ancestor::device[1]/@id, ',', @name)" />
<xsl:if test="generate-id() = generate-id(key('kStructureByName', $name)[1])">

Upvotes: 3

Related Questions