Reputation: 3
I need to merge two XML files via XSLT Version 1.0 . My Problem here is, that I need to add the Attributes of the 2nd XML-file to the Attributes of the first file. Let me give you an example to clarify my Problem.
XML1:
<sample>
<tag a="1" b="2" c="3" d="4" />
<tag a="2" b="3" c="4" d="5" />
</sample>
XML2:
<sample>
<tag e="5" f="6" g="7" />
<tag e="10" f="12" g="11" />
</sample>
Output:
<sample>
<tag a="1" b="2" c="3" d="4" e="5" f="6" g="7" />
<tag a="2" b="3" c="4" d="5" e="10" f="12" g="11" />
</sample>
I tried following XSLT for this:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ws="http://www.w3schools.com">
<xsl:template match="/">
<xsl:for-each select="sample/tag">
<tag>
<xsl:attribute name="a"><xsl:value-of select="@a"/></xsl:attribute>
<xsl:attribute name="b"><xsl:value-of select="@b"/></xsl:attribute>
<xsl:attribute name="c"><xsl:value-of select="@c"/></xsl:attribute>
<xsl:attribute name="d"><xsl:value-of select="@d"/></xsl:attribute>
<xsl:attribute name="e"><xsl:value-of select="document('xml2.xml')//@e"/></xsl:attribute>
<xsl:attribute name="f"><xsl:value-of select="document('xml2.xml')//@f"/></xsl:attribute>
<xsl:attribute name="g"><xsl:value-of select="document('xml2.xml')//@g"/></xsl:attribute>
<tag>
</xsl:for-each>
</xbrl>
</xsl:template>
</xsl:stylesheet>
But I got only the first line of the 2nd XML-File. EG my Output was:
<sample>
<tag a="1" b="2" c="3" d="4" e="5" f="6" g="7" />
<tag a="2" b="3" c="4" d="5" e="5" f="6" g="7" />
</sample>
Hopefully anyone can help me with this. I am completly new to XSLT.
Upvotes: 0
Views: 80
Reputation: 29032
A short and easy way is using the following template applying a one-to-one position mapping:
<xsl:template match="/sample">
<sample>
<xsl:apply-templates select="tag" />
</sample>
</xsl:template>
<xsl:template match="tag">
<xsl:variable name="pos" select="position()" />
<tag>
<xsl:copy-of select="@*" />
<xsl:copy-of select="document('a2.xml')/sample/tag[$pos]/@*" />
</tag>
</xsl:template>
Output is:
<?xml version="1.0"?>
<sample>
<tag a="1" b="2" c="3" d="4" e="5" f="6" g="7"/>
<tag a="2" b="3" c="4" d="5" e="10" f="12" g="11"/>
</sample>
Upvotes: 1
Reputation: 70618
Firstly, you can simplify things by starting off with the XSLT identity template to copy the existing nodes and attributes in your first XML
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
Then, to add the extra attributes to the tag
element, you have a template matching tag
<xsl:template match="tag">
In this, you then need to get the position of the current element, so you can find the relevant tag
element in the same position in the second document
<xsl:variable name="position">
<xsl:number />
</xsl:variable>
Then, you can select the attributes from the second document like so:
<xsl:apply-templates select="document('xml2.xml')/sample/tag[position() = $position]/@*"/>
Try this XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="tag">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:variable name="position">
<xsl:number />
</xsl:variable>
<xsl:apply-templates select="document('xml2.xml')/sample/tag[position() = $position]/@*"/>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Upvotes: 0