Grouping sets of tags with XSLT

M

masonmarc

I have a document like:

<all>
<phone>
<number>12345</number>
<r comp="1"/>
<r comp="2"/>
<r comp="3"/>
<r comp="1">
<r address="a"/>
</r>
<r comp="2">
<r address="b"/>
</r>
<r comp="3">
<r address="c"/>
</r>
<r comp="1">
<r country="a1"/>
</r>
<r comp="2">
<r country="b1"/>
</r>
<r comp="3">
<r country="c1"/>
</r>
</phone>
<phone>
<number>67890</phone>
<r comp="1"/>
<r comp="1">
<r address="a"/>
</r>
<r comp="1">
<r country="a1"/>
</r>
</phone>
</all>

That I would like to use XSLT to transform to:

<all>
<phone>
<number>12345</number>
<r comp="1">
<r address="a"/>
<r country="a1"/>
</r>
<r comp="2">
<r address="b"/>
<r country="b1"/>
</r>
<r comp="3">
<r address="c"/>
<r country="c1"/>
</r>
</phone>
<phone>
<number>67890</phone>
<r comp="1">
<r address="a"/>
<r country="a1"/>
</r>
</phone>
</all>

So I need to do grouping. I've used the key and generate-id trick to
do:

<xsl:key name="rs" match="r" use="@comp">

then:

<xsl:for-each select="r[generate-id(.)=generate-id(key('rs',
@comp)[1])]">

to select the r elements and then process them to get the correct
output. Using this method I can get the first phone element to output
correctly, but when it gets to the second one (or any other one that
has an r element with a comp attribute that has already been processed,
the select in the for-each statement doesn't select anything (comp="1"
was already processed in the previous phone element), so I get no
output. Does anyone have any ideas on how to get this to work or
another way to do it?

Thanks.
 
S

SL

(e-mail address removed) a écrit :
So I need to do grouping. I've used the key and generate-id trick to
do:

<xsl:key name="rs" match="r" use="@comp">

then:

<xsl:for-each select="r[generate-id(.)=generate-id(key('rs',
@comp)[1])]">

to select the r elements and then process them to get the correct
output. Using this method I can get the first phone element to output
correctly, but when it gets to the second one (or any other one that
has an r element with a comp attribute that has already been processed,
the select in the for-each statement doesn't select anything (comp="1"
was already processed in the previous phone element), so I get no
output. Does anyone have any ideas on how to get this to work or
another way to do it?

I think you could avoid using xsl:key with something like:

<xsl:template match="phone">
<phone>
<xsl:copy-of select="number" />
<xsl:for-each select="r[not(*)]">
<xsl:variable name="nbr" select="@comp" />
<r comp="{$nbr}">
<r address="{ ../r[@comp="$nbr"]/r/@address }" />
<r country="{ ../r[@comp="$nbr"]/r/@country }" />
</r>
</xsl:for-each>
</phone>
</xsl:template

not tested at all !

HTH,
SL
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,740
Latest member
AdolphBig6

Latest Threads

Top