Reputation: 375
I want to process two separate nodes in for each in xsl. This is the question How do I access elements from the outer loop from within nested loops? which looked similar. I tried but didnt worked even after using variable. Don't know what I'm doing wrong.
Here's the xml:
<root>
<demomain>
<demo>
<name>A</name>
<price>10</price>
</demo>
<demo>
<name>B</name>
<price>15</price>
</demo>
<demomain>
<demomainOrig>
<demoOrig>
<name>A</name>
<price>20</price>
</demoOrig>
<demoOrig>
<name></name>
<price>25</price>
</demoOrig>
</demomainOrig>
</root>
And the xsl I have made so far is
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<demos>
<xsl:for-each select="root/demomain/demo">
<xsl:variable name="newNode" select="."/>
<Demo>
<productID id="{$newNode/name}"/>
<xsl:for-each select="root/demomainOrig/demoOrig">
<price newVal="{$newNode/price}" origVal="{price}" />
</xsl:for-each>
</Demo>
</xsl:for-each>
</demos>
</xsl:template>
</xsl:stylesheet>
Following is the output that I want:
<?xml version="1.0" encoding="UTF-8"?>
<demos>
<Demo>
<productID id="A"/>
<price newVal="10" origVal="20"/>
</Demo>
<Demo>
<productID id="B"/>
<price newVal="15" origVal="25"/>
</Demo>
</demos>
The problem is in the inner for each. If I remove the inner for each i get the price tag in output else it is not even displayed. And so I'm not able to get the original price for the particular item. Please Help.
Thanks in Advance
Upvotes: 1
Views: 1408
Reputation: 534
You can fetch the corresponding demoOrig nodes by using the same position of the current node (assuming that the order is the same, and 'name' is not an identifier).
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<demos>
<xsl:for-each select="root/demomain/demo">
<xsl:variable name="position" select="position()" />
<xsl:variable name="demoOrig" select="/root/demomainOrig/demoOrig[position() = $position]" />
<Demo>
<productID id="{name}"/>
<price newVal="{price}" origVal="{$demoOrig/price}" />
</Demo>
</xsl:for-each>
</demos>
</xsl:template>
</xsl:stylesheet>
This outputs:
<?xml version="1.0" encoding="UTF-8"?>
<demos>
<Demo>
<productID id="A" />
<price origVal="20" newVal="10" />
</Demo>
<Demo>
<productID id="B" />
<price origVal="25" newVal="15" />
</Demo>
</demos>
Upvotes: 1
Reputation: 70618
The problem is with this line...
<xsl:for-each select="root/demomainOrig/demoOrig">
You are positioned on a demo
element at this point, so this will be looking for a child element called root
. But your root
is the root element of the whole document. It should like this...
<xsl:for-each select="/root/demomainOrig/demoOrig">
However, this still won't be quite what you need, as this will select all demoOrig
elements. You only want to select the one with the same name:
<xsl:for-each select="/root/demomainOrig/demoOrig[name = $newNode/name]">
Try this XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<demos>
<xsl:for-each select="root/demomain/demo">
<xsl:variable name="newNode" select="."/>
<Demo>
<productID id="{$newNode/name}"/>
<xsl:for-each select="/root/demomainOrig/demoOrig[name=$newNode/name]">
<price newVal="{$newNode/price}" origVal="{price}" />
</xsl:for-each>
</Demo>
</xsl:for-each>
</demos>
</xsl:template>
</xsl:stylesheet>
I am assuming your actual XML has the name
specified for all demoOrig
elements.
In fact, you could possibly replace the xsl:for-each
with just a single statement
<price newVal="{$newNode/price}" origVal="{/root/demomainOrig/demoOrig[name=$newNode/name]/price}" />
Alternatively, you could benefit from using an xsl:key
to look up the records. Try this XSLT too
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="orig" match="demoOrig" use="name" />
<xsl:template match="/">
<demos>
<xsl:for-each select="root/demomain/demo">
<xsl:variable name="newNode" select="."/>
<Demo>
<productID id="{name}"/>
<price newVal="{price}" origVal="{key('orig', name)/price}" />
</Demo>
</xsl:for-each>
</demos>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1