Home > Software design >  remove unwanted namespaces from child node
remove unwanted namespaces from child node

Time:08-19

Hello everyone this is the input XML and I want all the as it is XML structure inside a ns0:operationbody element. where opening < should be in entity form and > should be in '>' symbol.

Main problem is some extra namespaces are copying which are not in input XML child element

    <?xml version = '1.0' encoding = 'UTF-8'?>
    <root xmlns="GlobalInteraction.xsdobjects">
       <ns1:Account xmlns:ns1="GlobalInteraction.xsdobjects">
          <ns1:ExtReference>
             <commonProvide:ExternalSystem xmlns:commonProvide="commonentities.xsdobjects.extload">BFG</commonProvide:ExternalSystem>
             <commonProvide:ServiceElement2 xmlns:commonProvide="commonentities.xsdobjects.extload">
<!-- At this point no namespace is given but in output namespaces are displaying -->
                **<commonProvide:ElementNumber>30</commonProvide:ElementNumber>
                <commonProvide:PartNumber>60000283</commonProvide:PartNumber>**
             </commonProvide:ServiceElement2>
          </ns1:ExtReference>
          <ns1:CustomerLegalName xmlns:ns1="GlobalInteraction.xsdobjects">CLARINS</ns1:CustomerLegalName>
          <ns1:Type>Global</ns1:Type>
          <ns1:SubType>National</ns1:SubType>
       </ns1:Account>
    </root>

After running the code this is the output:

<ns0:OperationBody xmlns:ns0="serviceBusiness.xsdobjects.extload.services.classic.bt">&lt;root xmlns="GlobalInteraction.xsdobjects.extload">
   &lt;ns1:Account xmlns:ns1="GlobalInteraction.xsdobjects.extload">
      &lt;ns1:ExtReference xmlns:ns1="GlobalInteraction.xsdobjects.extload">
         &lt;commonProvide:ExternalSystem xmlns:commonProvide="commonentities.xsdobjects.extload" xmlns:ns1="GlobalInteraction.xsdobjects.extload">BFG&lt;/commonProvide:ExternalSystem>
      &lt;/ns1:ExtReference>
      &lt;ns1:ExtReference xmlns:ns1="GlobalInteraction.xsdobjects.extload">
         &lt;commonProvide:ExternalSystem xmlns:commonProvide="commonentities.xsdobjects.extload" xmlns:ns1="GlobalInteraction.xsdobjects.extload">BFG&lt;/commonProvide:ExternalSystem>
         &lt;commonProvide:ServiceElement2 xmlns:commonProvide="commonentities.xsdobjects.extload" xmlns:ns1="GlobalInteraction.xsdobjects.extload">
            &lt;commonProvide:ElementNumber xmlns:commonProvide="commonentities.xsdobjects.extload" xmlns:ns1="GlobalInteraction.xsdobjects.extload">30&lt;/commonProvide:ElementNumber>
            &lt;commonProvide:PartNumber xmlns:commonProvide="commonentities.xsdobjects.extload" xmlns:ns1="GlobalInteraction.xsdobjects.extload">60000283&lt;/commonProvide:PartNumber>
         &lt;/commonProvide:ServiceElement2>
      &lt;/ns1:ExtReference>
      &lt;ns1:CustomerLegalName xmlns:ns1="GlobalInteraction.xsdobjects.extload">CLARINS&lt;/ns1:CustomerLegalName>
      &lt;ns1:Type xmlns:ns1="GlobalInteraction.xsdobjects.extload">Global&lt;/ns1:Type>
      &lt;ns1:SubType xmlns:ns1="GlobalInteraction.xsdobjects.extload">National&lt;/ns1:SubType>
   &lt;/ns1:Account>
&lt;/root></ns0:OperationBody>

But requirement was I have to copy the whole input XML structure inside &lt; and >. But we can see extra namespaces are copying in the element where it is not present Please suggest me any solution

Here is my XSLT:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="serviceBusiness.xsdobjects.extload" xmlns:ns1="GlobalInteraction.xsdobjects.extload"
    xmlns:commonProvide="commonentities.xsdobjects.extload"
    exclude-result-prefixes="xsl ns1 commonProvide">


<xsl:template match="/">
<ns0:OperationBody>
  <xsl:apply-templates mode="escape"/>
</ns0:OperationBody>
</xsl:template>
<xsl:template match="*" mode="escape">
<!-- Begin opening tag -->
        <xsl:text>&lt;</xsl:text>
        <xsl:value-of select="name()"/>
        
        <!-- Namespaces -->
<xsl:variable name="namespace-in" select="' xmlns=&quot;GlobalInteraction.xsdobjects.extload&quot;'"/>
<xsl:variable name="namespace-ns1" select="' xmlns:ns1=&quot;GlobalInteraction.xsdobjects.extload&quot;'"/>
<xsl:variable name="namespace-common" select="' xmlns:commonProvide=&quot;commonentities.xsdobjects.extload&quot;'"/>

        <xsl:if test="not(ancestor::*)">
            <xsl:value-of select="$namespace-in"/>
        </xsl:if>
        
        <xsl:for-each select="namespace::*[name()='ns1' or name()='commonProvide']">
            
            <xsl:choose>
                <xsl:when test="name()='ns1'">
                    <xsl:value-of select="$namespace-ns1"/>
                </xsl:when>
                <xsl:when test="name()='commonProvide'">
                    <xsl:value-of select="$namespace-common"/>
                </xsl:when>
            </xsl:choose>
</xsl:for-each>

<!-- End opening tag -->
        <xsl:text disable-output-escaping="yes">&gt;</xsl:text>
        
        <!-- Content (child elements, text nodes, and PIs) -->
        <xsl:apply-templates select="node()" mode="escape" />
        
        <!-- Closing tag -->
        <xsl:text>&lt;/</xsl:text>
        <xsl:value-of select="name()"/>
        <xsl:text disable-output-escaping="yes">&gt;</xsl:text>
    </xsl:template>
    
    <xsl:template match="text()" mode="escape">
        <xsl:call-template name="escape-xml">
            <xsl:with-param name="text" select="."/>
        </xsl:call-template>
</xsl:template>

<xsl:template name="escape-xml">
        <xsl:param name="text"/>
        <xsl:if test="$text != ''">
            <xsl:variable name="head" select="substring($text, 1, 1)"/>
            <xsl:variable name="tail" select="substring($text, 2)"/>
            <xsl:choose>
                <xsl:when test="$head = '&amp;'">&amp;amp;</xsl:when>
                <xsl:when test="$head = '&lt;'">&amp;lt;</xsl:when>
                <xsl:when test="$head = '&gt;'"><xsl:value-of select="'&amp;gt;'" disable-output-escaping="yes"/></xsl:when>
                <xsl:when test="$head = '&quot;'">&amp;quot;</xsl:when>
                <xsl:when test="$head = &quot;&apos;&quot;">&amp;apos;</xsl:when>
                <xsl:otherwise><xsl:value-of select="$head"/></xsl:otherwise>
            </xsl:choose>
            <xsl:call-template name="escape-xml">
                <xsl:with-param name="text" select="$tail"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

CodePudding user response:

Your logic for processing namespaces is very strange. As far as I can see,

 <xsl:for-each select="namespace::*[name()='ns1' or name()='commonProvide']">
    
    <xsl:choose>
        <xsl:when test="name()='ns1'">
            <xsl:value-of select="$namespace-ns1"/>
        </xsl:when>
        <xsl:when test="name()='commonProvide'">
            <xsl:value-of select="$namespace-common"/>
        </xsl:when>
    </xsl:choose>
 </xsl:for-each>

is a rather long-winded way of writing

<xsl:if test="namespace::ns1">
  <xsl:value-of select="$namespace-ns1"/>
</xsl:if>
<xsl:if test="namespace::commonProvide">
  <xsl:value-of select="$namespace-common"/>
</xsl:if>

This isn't the immediate cause of the problem, although it provides a hint that you don't have a good understanding of how the namespace axis works.

The problem is that the namespace axis doesn't select the namespace declarations on an element, it selects all the in-scope namespaces for the element, including namespaces declared on parent elements. The way to eliminate the redundant namespaces is to test whether they're also present on the parent element:

<xsl:if test="namespace::ns1 and not(../namespace::ns1)">

etc

  • Related