I have some code that compares two XML documents for attribute differences (updates only, not new attribute nodes) and generates a set of XPath pointers to the attributes and the new values for the attribute.
The Setup
For example, given an old XML and new xml:
Old XML
<EntityA>
<EntityB id="foo1" value="bar1" ignoredbutsave="bazz1"/>
</EntityA>
New XML
<EntityA>
<EntityB id="foo2" value="bar2"/>
</EntityA>
My code would return
/EntityA/EntityB/@id, foo2
/EntityA/EntityB/@value, bar2
I would like to generate an XSLT that merges the old XML into the new XML, to create the following XML:
<EntityA>
<EntityB id="foo2" value="bar2" ignoredbutsave="bazz1"/>
</EntityA>
All answers I've found on SO assume some prior knowledge about the attribute name. In this case, I'm given only the XPath reference the attribute, not the name itself. I know I could parse the XPath string to derive the attribute name, but would prefer to keep that complexity out of the code.
What I've tried
I can't use an attribute value template because I need to copy the ignoredbutsave
attribute from the old XML. I've tried to use an xsl:param to select the attribute name from the XPath and use it within an xsl:attribute, like this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/EntityA/EntityB/@id">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
<xsl:param name="newValue" select="name(/EntityA/EntityB/@id)"/>
<xsl:attribute name="$newValue">newAttributeId</xsl:attribute>
</xsl:copy>
</xsl:template>
<xsl:template match="/EntityA/EntityB/@value">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
<xsl:param name="myattrname" select="name(/EntityA/EntityB/@value)"/>
<xsl:attribute name="$myattrname">newAttributeValue</xsl:attribute>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
However, this causes the error The value '$myattrname' of the attribute 'name' is not a valid QName.
So, the question is given an XPath for an attribute and a new value for that attribute, how do I generate an an XSLT that updates that value without explicitly referencing the attribute name?
$myattrname
in curly brackets? – Marcus Rickert<xsl:attribute name="{$myattrname}">
does work. – lreeder