Is it possible to combine the value of attribute to the value of element?
INPUT XML
<Files>
<File>
<Data1>
<item attrib="Ol4d">value1</item>
</Data1>
<Data2 attrib="Old"/>
<Data3>
<item attrib="New">value2</item>
</Data3>
</File>
<File attrib="New">
<Data1>
<item2>
<item3 attrib="Old">value3</item3>
</item2>
</Data1>
</File>
<File attrib="New">
<Data1>
<item attrib="Old">value1</item>
</Data1>
</File>
</Files>
Say if it matches an element with specific attribute such as "Old", result will be like below.
DESIRED OUTPUT XML
<Files>
<File>
<Data1>
<item attrib="Old">Old-value1</item>
</Data1>
<Data2 attrib="Old"/>
<Data3>
<item attrib="New">value2</item>
</Data3>
</File>
<File attrib="New">
<Data1>
<item2>
<item3 attrib="Old">Old-value3</item3>
</item2>
</Data1>
</File>
<File attrib="New">
<Data1>
<item attrib="Old">Old-value1</item>
</Data1>
</File>
</Files>
CURRENT XSLT
I originally got this
<xsl:template match="*[@attrib='Old' and normalize-space(.)]">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:text>replace value</xsl:text>
</xsl:copy>
</xsl:template>
Then replaced xsl:text with <xsl:value-of select="@attrib" separator="-"/> but it is not combining with the value of the element, just replacing it with the attribute value.
OUTPUT produced by XSLT:
<Files>
<File>
<Data1>
<item attrib="Old">Old</item>
</Data1>
<Data2 attrib="Old"></Data2>
<Data3>
<item attrib="New">value2</item>
</Data3>
</File>
<File attrib="New">
<Data1>
<item2>
<item3 attrib="Old">Old</item3>
</item2>
</Data1>
</File>
<File attrib="New">
<Data1>
<item attrib="Old">Old</item>
</Data1>
</File>
</Files>
CodePudding user response:
Since you haven't posted what you've tried, here's what I would do and hopefully this will get you started.
What I would do is match text nodes whose parent has an attrib
attribute value of "Old". Maybe a match like this:
text()[normalize-space()][../@attrib='Old']
Then I'd concatenate the value of the attrib
attribute along with the value of the text() node. Something like (assuming XSLT 1.0 otherwise I'd probably use a separator
attribute, ||
, or a text value template):
concat(../@attrib,'-',.)
Note: Even though we already know the value of the attrib attribute is going to be "Old", I didn't hardcode "Old-" in the concat. This is so that if "Old" needs to change it only needs to change in the match.
Edit
Here's what I would do...
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()[normalize-space()][../@attrib='Old']">
<xsl:value-of select="concat(../@attrib,'-',.)"/>
</xsl:template>
</xsl:stylesheet>
Working example: http://xsltfiddle.liberty-development.net/jyfAiD3