This task can be made somewhat easier by using the index-of() function
-- it produces the positions for you.
Cheers,
Dimitre
On Wed, Feb 29, 2012 at 12:26 PM, Michael Müller-Hillebrand
<mmh(_at_)cap-studio(_dot_)de> wrote:
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>
--~--
--
Cheers,
Dimitre Novatchev
---------------------------------------
Truly great madness cannot be achieved without significant intelligence.
---------------------------------------
To invent, you need a good imagination and a pile of junk
-------------------------------------
Never fight an inanimate object
-------------------------------------
To avoid situations in which you might make mistakes may be the
biggest mistake of all
------------------------------------
Quality means doing it right when no one is looking.
-------------------------------------
You've achieved success in your field when you don't know whether what
you're doing is work or play
-------------------------------------
Facts do not cease to exist because they are ignored.
-------------------------------------
I finally figured out the only reason to be alive is to enjoy it.
--~------------------------------------------------------------------
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>
--~--