Reputation: 487
My goal is to get in output XML file surname and amount of the clients. I want to match id from <ClientList>
and id from <AmountList>
and if there are the same show the amount. My XSL file doesn't work correctly.
I have such an XML file:
<?xml version="1.0" encoding="utf-8"?>
<myData>
<ClientList>
<Client>
<surname>Kowalski</surname>
<id>12</id>
</Client>
<Client>
<surname>Nowak</surname>
<id>13</id>
</Client>
</ClientList>
<AmountList>
<Client>
<id>12<id>
<amount>500</amount>
</Client>
<Client>
<id>13<id>
<amount>300</amount>
</Client>
</AmountList>
<myData>
This one XML I would like to get:
<ClientList>
<Client>
<surname>Kowalski</surname>
<amount>500</amount>
</Client>
<Client>
<surname>Nowak</surname>
<amount>300</amount>
</Client>
</ClientList>
My XSL file doesn't work properly:
<xsl:template match="/">
<ClientList>
<xsl:for-each select="ClientList/Client">
<Client>
<surname>
<xsl:value-of select="surname" />
</surname>
<amount>
<xsl:variable name="Var1" select="substring(id, 1, 2)" />
<xsl:variable name="Var2" select="substring(id, 1, 2)" />
<xsl:if test="Var1 = Var2">AmountList/Client/amount</xsl:if>
</amount>
</Client>
</xsl:for-each>
</ClientList>
Upvotes: 1
Views: 333
Reputation: 461
<xsl:template match="myData">
<xsl:for-each select="ClientList/Client">
<xsl:if test="id=../following-sibling::AmountList/Client/id">
<xsl:element name="ClientList">
<xsl:element name="Client">
<xsl:element name="surname">
<xsl:value-of select="surname"/>
</xsl:element>
<amount>
<xsl:value-of select="../following-sibling::AmountList/Client[id=current()/id]/amount"/>
</amount>
</xsl:element>
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:template>
Upvotes: 0
Reputation: 91
Firstly, there are a couple of small problems with your input XML: the <id>
nodes in the <AmountList>
s aren't properly closed, and you're missing the closing tag for the root node <myData>
.
Having fixed that, here is my suggestion:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/myData">
<ClientList>
<xsl:for-each select="ClientList/Client">
<Client>
<surname>
<xsl:value-of select="surname" />
</surname>
<amount>
<xsl:value-of select="/myData/AmountList/Client[id=current()/id]/amount" />
</amount>
</Client>
</xsl:for-each>
</ClientList>
</xsl:template>
</xsl:stylesheet>
The xPath expression /myData/AmountList/Client[id=current()/id]/amount
means this:
Starting at the root, find the
/myData/AmoutList/Client
node whoseid
child node is equal to theid
child node of the current context node, and then select this node'samount
child node.
The current()
function is key to be able to do lookups like this, where you're looking elsewhere in the input tree for some node based on a value relative to the node you're currently on.
In this case the current context node returned by current()
is the Client
node because that's what is selected by the for-each
. I find that it is good practice to always be aware of which is your current context node is at any point in an XSL transform.
Upvotes: 1