Tony
Tony

Reputation: 1626

Concatenate the values of two attributes into one attribute for all nodes that contain both

I have XML like this:

   <Parent>
       <Elem1 Attr1="1" Attr2="2">
           <Elem2>
               <Elem3 Attr1="4" Attr2="5"></Elem3>
           </Elem2>
       </Elem1>
   </Parent>

and it should be turned into this:

  <Parent>
     <Elem1 Attr1="1+2">
        <Elem2>
           <Elem3 Attr1="4+5"></Elem3>
        </Elem2>
     </Elem1>
  </Parent>

The problem is that I don't know the names of the elements, that is, Elem1 or Elem3 in this case. I know is that elements must contain both the attribute Attr1 and the attribute Attr2 but not all such element names ahead of time.

I also know that parent element must have the name Parent, but children containing the attributes may be at any level, either immediate descendants or deeper in the parent tree.

The closest to the possible solution that I could find is this StackOverflow post but my XSLT knowledge is not good enough to try to adapt it to this case.

Upvotes: 0

Views: 1305

Answers (2)

michael.hor257k
michael.hor257k

Reputation: 116993

I think you want to do something like:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="@Attr1[../@Attr2]">
    <xsl:attribute name="Attr1">
        <xsl:value-of select="."/>
        <xsl:text>+</xsl:text>
        <xsl:value-of select="../@Attr2"/>
    </xsl:attribute>
</xsl:template>

<xsl:template match="@Attr2[../@Attr1]"/>

</xsl:stylesheet>

Upvotes: 1

Martin Honnen
Martin Honnen

Reputation: 167561

One way to solve that is

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">


    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Parent//*[@Attr1 and @Attr2]/@Attr1">
        <xsl:attribute name="Attr1" select="concat(., '+', ../@Attr2)"/>
    </xsl:template>

    <xsl:template match="Parent//*[@Attr1 and @Attr2]/@Attr2"/>

</xsl:transform>

http://xsltransform.net/ejivdHM

Upvotes: 1

Related Questions