tags:

views:

462

answers:

2

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.

+1  A: 
<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])">
Tomalak
This is a great answer that saves my day, thanks a lot for that quick reply. This site is great and I will register to give a rank to this answer.Tahnk you so much.SeB.
SeB
I gave a thought to your key suggestion but this shall not work because I need a single struct among multiple devices and your suggestion only works for a single device.
SeB
@SeB: Not sure what you mean - my suggestion (the second version of the key, at least) would work for multiple devices. Of course you'd have to adapt the "use" expression to your actual XML, but it should not be impossible.
Tomalak
basically, you do not use the limitedSet in the second approach. And the test is only true for the first structure in the given device but not among the limitedSet of multiple deviceS. You first solution looks for the first structure in all the limitedSet.
SeB
He wants to limit the "uniqueness" lookup only to nodes from $limitedSet; not to all nodes in the document.
Pavel Minaev
+1  A: 
select="$limitedSet//structure[not(@name=preceding::structure[count($limitedSet) = count($limitedSet | ..)]/@name)]"
Pavel Minaev
I think not, as I said, axi applis on all the document and not the nodeset. Moreover to my understanding preceding sibling does not goes to another deviceInstance of the one the structure is in.But thanks anyway for the try.
SeB
`preceding` and `following` axes apply across all document, but `preceding-sibling` and `following-sibling` only apply to nodes with the same parent. You're right about it not accounting for nodes in other `deviceInstance` elements, though.
Pavel Minaev
Try the updated version. I had to come up with a hack to test for presence of nodes in `$limitedSet`.
Pavel Minaev
houaou that is a nasty hack and a brilliant one. great input but I prefer Tomalak solution caus I have a very big file (30400 lines) and it looks more efficient as it is limited to the limitedSet whereas your solution would have to look for all the preceding nodes in the document. This is actually on problem I have somewhere else in my xsl, preceding axis is to costly.
SeB