This solution is totally free of loops or keys. I've loaded only one document using document()
, while I use the other one as source. Briefly, an element missing in the source document, it is taken on the loaded one. More elements you have less usable is this solution. See bottom for a more general one.
XSLT 1.0 tested on Saxon-HE 9.2.1.1J
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="catalog2" select="document('source_test2.xml')/catalog"/>
<xsl:template match="catalog">
<catalog>
<xsl:apply-templates select="data"/>
</catalog>
</xsl:template>
<xsl:template match="data">
<xsl:variable name="data2" select="$catalog2/data[myid=current()/myid]/."/>
<data>
<xsl:choose>
<xsl:when test="title">
<xsl:copy-of select="title"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="$data2/title"/>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="description">
<xsl:copy-of select="description"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="$data2/description"/>
</xsl:otherwise>
</xsl:choose>
<xsl:copy-of select="myid"/>
<xsl:choose>
<xsl:when test="author">
<xsl:copy-of select="author"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="$data2/author"/>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="date">
<xsl:copy-of select="date"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="$data2/date"/>
</xsl:otherwise>
</xsl:choose>
</data>
</xsl:template>
</xsl:stylesheet>
Here follows a more general solution. The approach is the same. For each data
, an element present in myFile2
and missing in myFile1
is added to the result tree, and vice-versa.
XSLT 1.0 tested on Saxon-B 9.0.0.4J
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="catalog2" select="document('myFile2.xml')/catalog"/>
<xsl:template match="catalog">
<catalog>
<xsl:apply-templates select="data"/>
</catalog>
</xsl:template>
<xsl:template match="data">
<xsl:variable name="data1" select="."/>
<xsl:variable name="data2" select="$catalog2/data[myid=current()/myid]/."/>
<data>
<xsl:copy-of select="$data1/*"/>
<xsl:for-each select="$data2/*">
<xsl:variable name="element2" select="name(.)"/>
<xsl:if test="count($data1/*[name()=$element2])=0">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</data>
</xsl:template>
</xsl:stylesheet>
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…