First xml file to be updated:
<Conf key="11" title="tit">
<Item key="1" >
<Lock con="E0" />
<Vol title="te" description="de">
<All con="1" title="uu" />
<Widget title="11" description="11" />
</Vol>
<Am title="re" description="de">
<Hold con="50" />
<Widget title="22" description="22" />
</Am>
</Item>
<Item key="2" title="tit">
<Lock const="E0" />
<Vol title="ty">
<All con="1" title="fg" />
<Widget title="33" description="33" />
</Vol>
<Am title="gh" description="gh">
<Hold const="50" />
<Widget title="44" description="44" />
</Am>
</Item>
</Conf>
The second xml file "updates.xml" from which data is taken to update the first file:
<Profile title="u">
<Item key="1">
<Vol>
<Widget title="AA"/>
</Vol>
<Am>
<Widget title="BB" description="BB" />
</Am>
</Item>
<Item key="2">
<Vol>
<Widget title="CC" description="CC" />
</Vol>
<Am>
<Widget title="Dd" description="DD" />
</Am>
</Item>
</Profile>
The update.xml file differs from the input file in that it contains only those tags that are ancestors of the Widget tag and lacks some attributes. After the XSLT1.0 transformation, the input tree is transferred to the output tree with the replacement of the Widget tags from the "updates.xml" file. If there is a Widget tag in the input file, but not in the "updates.xml" file, then the widget tag from the input file is transferred to the output tree. Now the transformation file:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exslt="http://exslt.org/common"
exclude-result-prefixes="exslt"
version="1.0">
<xsl:output method="xml"/>
<xsl:param name="updates" select="document('updates.xml')"/>
<xsl:key name="replacement" match="Widget" use="local-name(parent::*)"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Widget">
<xsl:variable name="parentName" select="local-name(parent::*)"/>
<xsl:variable name="replacement">
<xsl:for-each select="$updates">
<xsl:copy-of select="key('replacement', $parentName)"/>
</xsl:for-each>
</xsl:variable>
<xsl:choose>
<xsl:when test="exslt:node-set($replacement)/*">
<xsl:copy-of select="$replacement"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
After transforming the file:
<?xml version="1.0" encoding="utf-8"?>
<Conf key="11" title="tit">
<Item key="1">
<Lock con="E0" />
<Vol title="te" description="de">
<All con="1" title="uu" />
<Widget title="AA" />
<Widget title="CC" description="CC" />
</Vol>
<Am title="re" description="de">
<Hold con="50" />
<Widget title="BB" description="BB" />
<Widget title="Dd" description="DD" />
</Am>
</Item>
<Item key="2" title="tit">
<Lock const="E0" />
<Vol title="ty">
<All con="1" title="fg" />
<Widget title="AA" />
<Widget title="CC" description="CC" />
</Vol>
<Am title="gh" description="gh">
<Hold const="50" />
<Widget title="BB" description="BB" />
<Widget title="Dd" description="DD" />
</Am>
</Item>
</Conf>
How to ensure that after the XSLT1.0 transformation, the output file does not have extra Widget tags and the output file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<Conf key="11" title="tit">
<Item key="1">
<Lock con="E0" />
<Vol title="te" description="de">
<All con="1" title="uu" />
<Widget title="AA" />
</Vol>
<Am title="re" description="de">
<Hold con="50" />
<Widget title="BB" description="BB" />
</Am>
</Item>
<Item key="2" title="tit">
<Lock const="E0" />
<Vol title="ty">
<All con="1" title="fg" />
<Widget title="CC" description="CC" />
</Vol>
<Am title="gh" description="gh">
<Hold const="50" />
<Widget title="Dd" description="DD" />
</Am>
</Item>
</Conf>
ancestor::Item/@key
in thekey
value? – michael.hor257k