Subject: Re: [xsl] Finding triples with same/distinct attribute value From: Michael Kay <mike@xxxxxxxxxxxx> Date: Wed, 29 Feb 2012 21:27:11 +0000 |
Dear gurus,I think you need to state the requirement more clearly. Reverse-engineering it from your code isn't that easy. Is your definition of a "triple" this: "a sequence of three distinct <pot> elements, not necessarily adjacent, but in document order"?
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 Kay Saxonica
- 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>
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] Finding triples with same/dis, Michael Müller-Hille | Thread | |
Re: [xsl] faster complicated counti, Liam R E Quin | Date | Re: [xsl] faster complicated counti, Wendell Piez |
Month |