xsl-list
[Top] [All Lists]

[xsl] Finding triples with same/distinct attribute value

2012-02-29 14:27:03
Dear gurus,

I have a solution but I am eager to learn whether there is a better method to 
solve the problem. 

There is a number of elements with an attribute. The task is to find every 
triple of elements with the same attribute value or with distinct attribute 
values. I solved it using xsl:for-each loops but feel like having missed some 
XPath 2 features. I am looking forward to your comments.
 
- Michael

PS: I get a result of 60 triples with the sample file.

Input:

<pots>
 <pot a="3" />
 <pot a="3" />
 <pot a="3" />
 <pot a="1" />
 <pot a="1" />
 <pot a="1" />
 <pot a="1" />
 <pot a="1" />
 <pot a="1" />
 <pot a="3" />
 <pot a="2" />
 <pot a="3" />
</pots>

XSL:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="2.0"
 xmlns:xs="http://www.w3.org/2001/XMLSchema";
 xmlns:my="http://my";
 exclude-result-prefixes="xs my"

 <xsl:output indent="yes"/>
 
 <xsl:template match="pots">
  <result>
   <xsl:sequence select="my:triples(*)" />
  </result>
 </xsl:template>
 
 <xsl:function name="my:triples" as="node()*">
  <xsl:param name="nodes" as="node()+"/>
  
  <!-- common values -->
  <xsl:for-each select="$nodes">
   <xsl:variable name="t1" select="."/>
   <xsl:for-each select="$t1/following-sibling::*[@a eq $t1/@a]">
    <xsl:variable name="t2" select="."/>
    <xsl:for-each select="$t2/following-sibling::*[@a eq $t1/@a]">
     <triple>
      <xsl:value-of select="string-join((my:pos($nodes, $t1), my:pos($nodes, 
$t2), my:pos($nodes, .)), ' ')" />
     </triple>
    </xsl:for-each>
   </xsl:for-each>
  </xsl:for-each>
  
  <!-- distinct values -->
  <xsl:for-each select="$nodes">
   <xsl:variable name="t1" select="."/>
   <xsl:for-each select="$t1/following-sibling::*[@a ne $t1/@a]">
    <xsl:variable name="t2" select="."/>
    <xsl:for-each select="$t2/following-sibling::*[@a ne $t1/@a and @a ne 
$t2/@a]">
     <triple>
      <xsl:value-of select="string-join((my:pos($nodes, $t1), my:pos($nodes, 
$t2), my:pos($nodes, .)), ' ')" />
     </triple>
    </xsl:for-each>
   </xsl:for-each>
  </xsl:for-each>
  
 </xsl:function>
 
 <xsl:function name="my:pos" as="xs:string">
  <xsl:param name="nodes" as="node()+"/>
  <xsl:param name="node" as="node()"/>
  <xsl:value-of select="count($nodes[$node >> .]) + 1" />
 </xsl:function>
 
</xsl:transform>



--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--


<Prev in Thread] Current Thread [Next in Thread>