user1186390
user1186390

Reputation: 85

xsl to remove specific attribute and add it as a child node instead

I have the following xml:

<Envelope> 
  <ABC>
   <Hierarchy>
      <Family> 
       <History> ... </History>
      <Plan>  
       <Mom Name="Parent1">
         <Child Name = "Child11">
          <GrandChild Name="GC111" Label="" Sequence = "1">
            <Attributes>... </Attributes>
           </GrandChild>
          </Child>
         </Mom>
        <Child Name = "ChildIndependent1">
          <GrandChild Name="GCIndep12"   Label="&lt;Requested&gt;&lt;Item1&gt;68&lt;/Item1&gt;&lt;Item2&gt;69&lt;/Item2&g    t;&lt;/Requested&gt;" Sequence = "2" >
            <Attributes>... </Attributes>
        </GrandChild>       </Child>
  </Plan>      </Family>
   </Hierarchy>      </ABC>
</Envelope>

Here is my current xsl i have on the xml to create dummy mom tags around independent child tags. It also converts the & lt; and & gt; to < and >

         <xsl:stylesheet version="2.0" >
         <xsl:output method="xml" indent="yes" use-character-maps="angle-brackets"/>
           <xsl:character-map name="angle-brackets">
           <xsl:output-character character="&lt;" string="&lt;"/>
           <xsl:output-character character="&gt;" string="&gt;"/>
         </xsl:character-map>
        <xsl:template match="node()|@*">
       <xsl:copy><xsl:apply-templates select="node()|@*"/></xsl:copy>
     </xsl:template>
      <xsl:template match="//ABC/Hierarchy/Family">
        <xsl:element name="Plan">
           <xsl:for-each select="//ABC/Hierarchy/Family/Plan/*">
              <xsl:if test="self::Mom">
                   <xsl:copy-of select="."/>
              </xsl:if>
               <xsl:if test="self::Child">
                    <xsl:element name="Mom">
                       <xsl:attribute name="Name">dummy</xsl:attribute>
                         <xsl:copy-of select="."/>
                    </xsl:element>
               </xsl:if>
           </xsl:for-each>
       </xsl:element>
      </xsl:element>
       </xsl:template>
       </xsl:stylesheet>

I need to modify the above xsl to create the LabelRequested tag with the content of the label attribute as a child to the GrandChild and remove the Label attribute itself as below above xsl already converts the & lt; and & gt; to < and >.

        <Child Name = "ChildIndependent1">
          <GrandChild Name="GCIndep12"    Sequence = "2" >
             <LabelRequested>
                        <Requested><Item1>68</Item1><Item2>69</Item2>   </Requested>
             </LabelRequested>
            <Attributes>... </Attributes>
        </GrandChild>     

Any idea how I could change the above xsl to do this?

Upvotes: 0

Views: 234

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 116982

To minimize the example to the problem at hand, consider the following stylesheet:

XSLT 2.0

<xsl:stylesheet version="2.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="GrandChild">
    <xsl:copy>
        <xsl:apply-templates select="@* except @Label"/>
        <LabelRequested>
            <xsl:value-of select="@Label" disable-output-escaping="yes"/>
        </LabelRequested>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Applied to your input example, the result will be:

<?xml version="1.0" encoding="UTF-8"?>
<Envelope>
   <ABC>
      <Hierarchy>
         <Family>
            <History> ... </History>
            <Plan>
               <Mom Name="Parent1">
                  <Child Name="Child11">
                     <GrandChild Name="GC111" Sequence="1">
                        <LabelRequested/>
                        <Attributes>... </Attributes>
                     </GrandChild>
                  </Child>
               </Mom>
               <Child Name="ChildIndependent1">
                  <GrandChild Name="GCIndep12" Sequence="2">
                     <LabelRequested><Requested><Item1>68</Item1><Item2>69</Item2></Requested></LabelRequested>
                     <Attributes>... </Attributes>
                  </GrandChild>
               </Child>
            </Plan>
         </Family>
      </Hierarchy>
   </ABC>
</Envelope>

Note that this assumes your processor supports disable-output-escaping and that the processing chain allows it to execute it. Otherwise you would have to use either XSLT 3.0 or an extension function to parse the markup contained in the Label attribute.

Upvotes: 1

Related Questions