I have the following input XMLs:
car.xml:
<car ref-id="parts.xml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<color>red</color>
<tire>michelin</tire>
<engines override="false">
<engine>
<model>Z</model>
</engine>
</engines>
<hifi>pioneer</hifi>
</car>
parts.xml:
<?xml version="1.0" encoding="UTF-8"?>
<parts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<engines>
<engine>
<model>X</model>
</engine>
<engine>
<model>Y</model>
</engine>
</engines>
<tire>goodyear</tire>
<color>black</color>
<airbag>true</airbag>
</parts>
I'd like to merge parts.xml with car.xml, but want to copy only those nodes from parts.xml (regardless of their value) which:
- A, doesn't exist in car.xml
- B, exists in car xml, but the element's "override" attribute is set to false.
Michael-hor257k provided a solution to A, but I'm stuck implementing B.
Then XSLT looks like this:
<xsl:variable name="loc">
<xsl:value-of select="car/@ref-id" />
</xsl:variable>
<xsl:template match="/car">
<xsl:variable name="local-names">
<xsl:for-each select="*">
<name>
<xsl:value-of select="name()" />
</name>
<attr>
<xsl:value-of select="@override" />
</attr>
</xsl:for-each>
</xsl:variable>
<xsl:copy>
<xsl:copy-of select="*" />
<xsl:copy-of
select="document($loc)/parts/*[not(name()=exsl:node-set($local-names)/name)] or
exsl:node-set($local-names)/attr='false'"/>
</xsl:copy>
</xsl:template>
I tried to add
<attr>
<xsl:value-of select="@override" />
</attr>
and
or exsl:node-set($local-names)/attr='false'
to the XSLT but no success.
You could change line #10 from:
to:
You didn't post the expected result, so I am not sure it will be to your liking. This could prove much more complicated than it seems, if you need to merge nodes at different levels.