I have a large XML file and I need to change certain values in it where the ID number (OWNINST) matches one in another XML file.
My large XML file 'file1.xml' is in the following format:
<institution>
<ukprn>1234</ukprn>
<course>
<courseID>1</courseID>
<courseaim>X99</courseaim>
</course>
<student>
<birthdate>30/10/1985</birthdate>
<instance>
<OWNINST>123456|5</OWNINST>
<FC>1</FC>
<STULOAD>100</STULOAD>
<elq>4</elq>
<MODE>31</MODE>
</instance>
</student>
<student>
<birthdate>01/02/1999</birthdate>
<instance>
<OWNINST>654321|1</OWNINST>
<FC>2</FC>
<elq>2</elq>
</instance>
<instance>
<OWNINST>654321|2</OWNINST>
<FC>6</FC>
<elq>1</elq>
</instance>
</student>
</institution>
There are multiple students each of which can have multiple instances.
I have another xml file 'File2.xml' which is structured like this:
<studentstoamend>
<OWNINST>123456|5</OWNINST><MODE>01</MODE><STULOAD>100</STULOAD>
<OWNINST>111112|1</OWNINST><MODE>31</MODE><STULOAD>75</STULOAD>
</studentstoamend>
For each of the students in File2.xml, I would like to change the value of the fields in File1.xml to those listed in File2.xml. Any students not listed in File2.xml should not be changed.
Please could someone help with this as I don't seem to be able to do it.
This is how far I got:
<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="no"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Student/Instance[OWNINST = document('File2.xml')/studentstoamend/OWNINST]/MODE">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
Alternatively, I can run multiple stylesheets to put the data in one node at a time, i.e. update MODE in one stylesheet and MCDATE in another etc
Many thanks
Edit: 22/9/2015
Thanks for your help Abel. It seems to just copy the original file though without making amendments.
Would it help if I could structure file2.xml as follows?
<?xml version="1.0" encoding="UTF-8"?>
<studentstoamend>
<student><OWNINST>328352|2</OWNINST><MODE>31</MODE><STULOAD>50</STULOAD><MCDATE>12/01/2015</MCDATE></student>
<student><OWNINST>652508|3</OWNINST><MODE>01</MODE><STULOAD>100</STULOAD><MCDATE>15/11/2014</MCDATE></student>
</studentstoamend>
This is the code I now have
<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:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:variable name="students2" select="document('File2.xml')/studentstoamend" />
<xsl:template match="student/instance[OWNINST = document('File2.xml')/studentstoamend/OWNINST]/MODE">
<xsl:variable name="owninst" select="OWNINST" />
<xsl:apply-templates select="$students2[OWNINST = $owninst]/*" mode="file2" />
</xsl:template>
<!-- adjust this, or add more templates in this mode if changes in element names/values are needed -->
<xsl:template match="node() | @*" mode="file2">
<xsl:copy>
<xsl:apply-templates select="node() | @*" mode="file2" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
What part of the last bit of code would I change to target specific nodes, e.g. mode?
Thanks
Edit 1:45pm 22/09/15
The output I would like to see is:
<institution>
<ukprn>1234</ukprn>
<course>
<courseID>1</courseID>
<courseaim>X99</courseaim>
</course>
<student>
<birthdate>30/10/1985</birthdate>
<instance>
<OWNINST>123456|5</OWNINST>
<FC>1</FC>
<STULOAD>100</STULOAD> <!--Updated to 100 (although in this case it already was 100 so no change) -->
<elq>4</elq>
<MODE>01</MODE> <!--Updated to 01 -->
</instance>
</student>
<student>
<birthdate>01/02/1999</birthdate>
<instance>
<OWNINST>654321|1</OWNINST>
<FC>2</FC>
<elq>2</elq>
</instance>
<instance>
<OWNINST>654321|2</OWNINST>
<FC>6</FC>
<elq>1</elq>
</instance>
</student>
</institution>
Many thanks
This won't match anything, your input file has
student
andinstance
as element names and XML is case-sensitive.Inside this template, you apply templates on the original document (File1.xml). To adopt the changes from File2.xml, you will have to apply templates to the second document, something along those lines:
Update: changed the focus of the main template from
MODE
toOWNINST
.Yes, that would make it much more convenient. Try it this way:
XSLT 1.0