Adding namespace to a xml having namespaces in its child and also adding new elements through xslt on top of it

StackOverflow https://stackoverflow.com/questions/23479917

  •  16-07-2023
  •  | 
  •  

Question

My input xml looks like this as given below

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<L1>
    <L2>
        <l3>
            <item>
                <State>1</state>
                <currency>
                    <value1 xmlns:xs="www.anotherexample.com">5</value1>
                    <value2 xmlns:xs="www.anotherexample.com">dd</value2>
                </currency>
            </item>
            <item2>
                <a>1</a>
                <b>2</b>
                <c>3</c>
             </item2>
             <item3>
                 <e>2</e>
                 <l>3</l>
                 <m>3</m>
            </item3>
            <item4>
                 <n>r</n>
                 <p>5</p>
            </item4>
        </l3>
     </L2>
</L1>

i have two requirements

1) the xml has to be added with an envelope ie another xml will sit on top of this whole xml and resultant should look like

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>

    <start>
       <a></a>
        .....
        ..... 
       <Body>
       <Envelope>
           <L1>
               <L2>
                   <l3>
                       <item>
                           <State>1</state>
                           <currency>
                               <value1 xmlns:xs="www.anotherexample.com">5</value1>
                               <value2 xmlns:xs="www.anotherexample.com">ca</value2>
                            </currency>
                        </item>
                        <item2>
                              <a>1</a>
                              <b>2</b>
                              <c>3</c>
                         </item2>
                         <item3>
                              <e>2</e>
                              <l>3</l>
                               <m>3</m>
                          </item3>
                          <item4>
                               <n>r</n>
                               <p>5</p>
                          </item4>
                    </l3>
                </L2>
             </L1>
      </Envelope>   
      </Body>
       .....
       ..... 
    </start> 

2 the second requirment is that the root tag of the original xml ie the L1 tag should have a namespace added to it so the root tag becomes

    <start>
       <a></a>
        .....
        ..... 
       <Body>
           <Envelope>    
              <L1 xmlns="www.example.com">
                  <L2>
                     <l3>
                        <item>
                           <State>1</state>
                           <currency>
                                 <value1  xmlns:xs="www.anotherexample.com">5</value1>
                                 <value2   xmlns:xs="www.anotherexample.com">ca</value2>
                            </currency>
                </item>
                        <item2>
                             <a>1</a>
                             <c>3</c>
                        </item2>
                        <item3>
                             <e>2</e>
                        </item3>
                        <item4>
                            <n>r</n>
                        </item4>
                   </l3>
                </L2>
             </L1>
        </Envelope>
      </Body>
    </start>

how do we design an xslt to do this combination of transformation. i have searched and found solutions for adding namespace to the root tag, but how can i achieve both the results simulataneously

note: There are many elements inside the input xml that will be ignored or processed by using call template, so directly copying the xml and adding namespace fails in this case

example: i may be wanting only 1 tag from the input in the output xml. Edited the original post to show that the original input xml is not intended to be copied as it is to the output , as shown in the new output, the output xml will be in variation with the input XML with several tags missing and the order of the tags have to be constant Sorry for the incomplete description previously

Was it helpful?

Solution

the second requirment is that the root tag of the original xml ie the L1 tag should have a namespace added to it

That's not an accurate description of what you show as your output: all the elements that are descendants of the root inherit the root's namespace - therefore you need to add the new namespace to each and every one of them:

XSLT 1.0

<?xml version="1.0" encoding="UTF-8"?>
<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="*"/>

<xsl:template match="/">
    <start>
        <a></a>
        <!-- ... -->
        <Body>
            <Envelope> 
                <xsl:apply-templates select="*" />
            </Envelope>
        </Body>
    </start>
</xsl:template>

<xsl:template match="*">
    <xsl:element name="{local-name()}" namespace="www.example.com">
        <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
</xsl:template>

<xsl:template match="@*">
    <xsl:copy/>
</xsl:template>

</xsl:stylesheet>

when the above stylesheet is applied to the corrected input of:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
<L1>
  <L2>
    <l3>
      <item>
        <state>1</state>
        <currency>LEVEL</currency> 
            <value1 xmlns:xsi="http://www.w3.org/2001/XMLSchema" xsi:type="xs:int">5</value1>
            <value2 xmlns:xsi="http://www.w3.org/2001/XMLSchema" xsi:type="xs:int">ca</value2>
      </item>
    </l3>
  </L2>
</L1>

the result is:

<?xml version="1.0" encoding="UTF-8"?>
<start>
   <a/>
   <Body>
      <Envelope>
         <L1 xmlns="www.example.com">
            <L2>
               <l3>
                  <item>
                     <state>1</state>
                     <currency>LEVEL</currency>
                     <value1 xmlns:xsi="http://www.w3.org/2001/XMLSchema" xsi:type="xs:int">5</value1>
                     <value2 xmlns:xsi="http://www.w3.org/2001/XMLSchema" xsi:type="xs:int">ca</value2>
                  </item>
               </l3>
            </L2>
         </L1>
      </Envelope>
   </Body>
</start>

Edit

If you want to remove some nodes from the output, create a specific template for them and leave it empty. For example, using the following input:

<L1>
    <L2>
        <l3>
            <item>
                <state>1</state>
                <currency>
                    <value1 xmlns:xsi="http://www.w3.org/2001/XMLSchema" xsi:type="xs:int">5</value1>
                    <value2 xmlns:xsi="http://www.w3.org/2001/XMLSchema" xsi:type="xs:int">ca</value2>
                </currency>
            </item>
            <item2>
                <a>1</a>
                <b>2</b>
                <c>3</c>
             </item2>
             <item3>
                 <e>2</e>
                 <l>3</l>
                 <m>3</m>
            </item3>
            <item4>
                 <n>r</n>
                 <p>5</p>
            </item4>
        </l3>
     </L2>
</L1>

we will add an empty template for elements <b, <l>, <m> and <p> to our previous stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<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="*"/>

<xsl:template match="/">
    <start>
        <a></a>
        <!-- ... -->
        <Body>
            <Envelope> 
                <xsl:apply-templates select="*" />
            </Envelope>
        </Body>
    </start>
</xsl:template>

<xsl:template match="*">
    <xsl:element name="{local-name()}" namespace="www.example.com">
        <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
</xsl:template>

<xsl:template match="@*">
    <xsl:copy/>
</xsl:template>

<xsl:template match="b|l|m|p"/>

</xsl:stylesheet>

and obtain the following result:

<?xml version="1.0" encoding="UTF-8"?>
<start>
   <a/>
   <Body>
      <Envelope>
         <L1 xmlns="www.example.com">
            <L2>
               <l3>
                  <item>
                     <state>1</state>
                     <currency>
                        <value1 xmlns:xsi="http://www.w3.org/2001/XMLSchema" xsi:type="xs:int">5</value1>
                        <value2 xmlns:xsi="http://www.w3.org/2001/XMLSchema" xsi:type="xs:int">ca</value2>
                     </currency>
                  </item>
                  <item2>
                     <a>1</a>
                     <c>3</c>
                  </item2>
                  <item3>
                     <e>2</e>
                  </item3>
                  <item4>
                     <n>r</n>
                  </item4>
               </l3>
            </L2>
         </L1>
      </Envelope>
   </Body>
</start>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top