Reputation: 3
My XML looks like
<Subjects>
<subject>
<id>Maths</id>
<sid>12</sid>
</subject>
<subject>
<id>science</id>
<sid>13</sid>
</subject>
<subject>
<id>social</id>
<sid>14</sid>
</subject>
</Subjects>
<xsl:variable name="Msubject" select="../../id[text()='Maths']"/>
<xsl:value-of select="$Msubject/sid/text()" />
<xsl:template match="//subject[id='Maths']/sid">
<xsl:copy>
22
</xsl:copy>
</xsl:template>
I need the to get the subject where id = Maths and change its sid to 22(or requried value). Similary i need to get the subject where id is science and change its sid to 23 etc tried above whhich is not working**
Upvotes: 0
Views: 1178
Reputation: 3247
Based on the additional inputs provided in the question, the solution has been modified and it can now be used for replacing the value in <sid>
with the value available in a different file.
File1.xml
<Subjects>
<subject>
<id>Maths</id>
<sid>12</sid>
</subject>
<subject>
<id>science</id>
<sid>13</sid>
</subject>
<subject>
<id>social</id>
<sid>14</sid>
</subject>
</Subjects>
File2.xml
<inputfile>
<mathsid>22</mathsid>
<scienceid>23</scienceid>
<socialid>24</socialid>
</inputfile>
The XSLT uses logic to read the value of <id>
from File1.xml
and create a node out of it viz. <Mathsid>
,<scienceid>
and <socialid>
. Using this fabricated node it looks up in File2.xml
for nodes that contain similar name. The matching is done from the 2nd character so that uppercase M in <Mathsid>
does not create issues with <mathsid>
. It can also be achieved by converting the camel case node name to lower case but XSLT 1.0 requires additional work to handle it.
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" />
<xsl:strip-space elements="*" />
<xsl:param name="file" select="document('File2.xml')/inputfile" />
<!-- identity transform -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<!-- for all 'subject' nodes -->
<xsl:template match="subject">
<!-- create variable to fabricate a node name i.e. Mathsid, scienceid,
socialid using the value in <id> and string 'id' -->
<xsl:variable name="subjNameNode" select="concat(id, 'id')" />
<xsl:copy>
<!-- copy the value of node id as is -->
<xsl:apply-templates select="id" />
<!-- replace existing value of 'sid' by value from the different file by checking
whether the node name contains the explicitly created above. The check is done
from the 2nd character so that <mathsid> contains text 'athsid' -->
<sid>
<xsl:value-of select="$file/*[contains(local-name(), substring($subjNameNode,2))]" />
</sid>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
The XSLT when used with File1.xml
transforms it and produces the desired output.
Output
<Subjects>
<subject>
<id>Maths</id>
<sid>22</sid>
</subject>
<subject>
<id>science</id>
<sid>23</sid>
</subject>
<subject>
<id>social</id>
<sid>24</sid>
</subject>
</Subjects>
Upvotes: 1