Question
I have an xml
<Root>
<Parent>
<Child1>A</Child1>
<Child2>B</Child2>
<Child1>X</Child1>
<Child2>Y</Child2>
</Parent>
</Root>
Child2 always will be with child1. I need to know how I can loop through using xsl:foreach
and create an XML output example.
<TransformedXML>
<Child attribute1="A" attribute2="B"/>
<Child attribute1="X" attribute2="Y"/>
</TransformedXML>
My question is how do I loop in XSLT considering Child2 node will follow a Child1 always?
Solution
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kFollowingChild1" match="*[not(self::Child1)]"
use="generate-id(preceding-sibling::Child1[1])"/>
<xsl:template match="Parent">
<TransformedXML>
<xsl:apply-templates/>
</TransformedXML>
</xsl:template>
<xsl:template match="Child1">
<Child>
<xsl:for-each select=".|key('kFollowingChild1', generate-id())">
<xsl:attribute name="attribute{position()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:for-each>
</Child>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
when applied on the provided (corrected many times to become well-formed!) XML document:
<Root>
<Parent>
<Child1>A</Child1>
<Child2>B</Child2>
<Child1>X</Child1>
<Child2>Y</Child2>
</Parent>
</Root>
produces the wanted, correct result:
<TransformedXML>
<Child attribute1="A" attribute2="B"/>
<Child attribute1="X" attribute2="Y"/>
</TransformedXML>
OTHER TIPS
Is there a specific reason why you wan't to use xsl:for-each
? I'd suggest to just use matching templates:
<xsl:template match="Child1">
<Child attribute1="{.}" attribute2="{following-sibling::*[1]}"/>
</xsl:template>
<xsl:template match="Child2"/>
This will work just fine as long as the prerequisite that Child1
always will be the first following sibling of Child2
.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow