Home > Back-end >  Combine the value of attribute and element
Combine the value of attribute and element

Time:07-29

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

  • Related