Consider the following XML:
<root>
<a>
<pos>
<c val="abc"></c>
<c val="def"></c>
<c val="ghi"></c>
<c val="jkl"></c>
<c val="mno"></c>
</pos>
<b>
<c></c>
</b>
<b>
<c></c>
<d>here</d>
</b>
<b>
<e>and</e>
<c></c>
<d>for</d>
</b>
<b>
<c></c>
<c></c>
<d>also</d>
</b>
</a>
<a>
<pos>
<c val="pqr"></c>
<c val="stu"></c>
<c val="vwx"></c>
<c val="yz"></c>
</pos>
<b>
<c></c>
<d>what</d>
</b>
<b>
<c></c>
</b>
<b>
<d>how</d>
</b>
<b>
<c></c>
<d>where</d>
<c></c>
</b>
</a>
</root>
Now in my output, when ever I encounter a <c></c>
inside a b
, I need to put the corresponding value of the val
attribute of a <c></c>
from the <pos></pos>
node. By corresponding value I mean the index of node c
inside pos
should be the same as the index of c
in all the b
nodes combined.
The desired output is:
<start>
<level>
abc
</level>
<level>
def
here
</level>
<level>
and
ghi
for
</level>
<level>
jkl
mno
also
</level>
<start>
<start>
<level>
pqr
what
</level>
<level>
stu
</level>
<level>
how
</level>
<level>
vwx
where
yz
</level>
</start>
I attempted it with the following XSL:
<xsl:template match="root">
<star>
<xsl:apply-templates select="a"/>
</start>
</xsl:template>
<xsl:template match="a">
<xsl:apply-templates select="b"/>
</xsl:template>
<xsl:template match="b">
<level>
<xsl:for-each select="*">
<xsl:choose>
<xsl:when test="name() = 'd'">
<xsl:value-of select="."/>
</xsl:when>
<xsl:when test="name() = 'e'">
<xsl:value-of select="."/>
</xsl:when>
<xsl:when test="name() = 'c'">
<xsl:variable name="posCount">
<!-- I don't know what to do here -->
</xsl:valiable>
<xsl:for-each select="ancestor::a[1]/pos">
<xsl:for-each select="c[position() = $posCount]">
<xsl:value-of select="@val"/>
</xsl:for-each>
</xsl:for-each>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</level>
</xsl:template>
What I need to do is somehow get the position count of each c
inside all the b
s combined and then use the value of val
attribute of correspondingly positioned c
from inside pos
.
How can I proceed to do it?
Note: I am using XSLT 1.0
Thnx in advance!!
The index number you are looking for can be obtained quite easily by using the xsl:number
element. For example:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="root">
<root>
<xsl:apply-templates select="a"/>
</root>
</xsl:template>
<xsl:template match="a">
<start>
<xsl:apply-templates select="b"/>
</start>
</xsl:template>
<xsl:template match="b">
<level>
<xsl:text> </xsl:text>
<xsl:apply-templates select="*"/>
</level>
</xsl:template>
<xsl:template match="d|e">
<xsl:value-of select="."/>
<xsl:text> </xsl:text>
</xsl:template>
<xsl:template match="b/c">
<xsl:variable name="i">
<xsl:number count="b/c" from="a" level="any" />
</xsl:variable>
<xsl:value-of select="ancestor::a/pos/c[number($i)]/@val"/>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
Notes:
1. I have added a root
element to the output to make it a valid XML;
2. It would be best to use a key to get the corresponding value from pos/c
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With