Mano
Mano

Reputation: 143

Namespace removal for modified element in XSL

I am having a input XML, in which one elements schema got changed. So as per the new schema, I renamed it. Now for that particular element, I am getting an extra namespace in the output XML.

I used exclude prefixes, but it didnot removed. I want only that particular element which got renamed to get removed namespace. Somehow, the XSL I used before is stripping of all the namespaces which comes at soap envelope, soap body etc, not only for the particular element.

Why only the changed element is giving namespace error. Am I giving wrong schema declaration, giving new schema for old element,(my doubt also, but change to old schema has no affect) or anyother error. Any suggestions on this are welcome.

Format of input XML is fixed. So have to make changes only in XSLT to remove the extra namespace coming after the renamed element(PartyDetails element). All the other elements and their namespace, contracts need to be intact.

    <?xml version="1.0" encoding="UTF-8"?>
    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Header />
    <s:Body>
    <MethodResponseType xmlns="http://example.test.com/Trialmethods/Run">
    <MessageResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <ListResponse i:nil="true" />
    <OptionsResponse i:nil="true" />
    <PartyResponse>
    <DemoHolder>
    <Details>
    <ContractType>
    <ID>001</ID>
    <Name>
    <FirstName>Mano</FirstName>
    <Initial>1</Initial>
    </Name>
    </ContractType>
    </Details>
    </DemoHolder>
    </PartyResponse>
    </MessageResponse>
    </MethodResponseType>
    </s:Body>
    </s:Envelope>

XSLT for namespace removal.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" 
xmlns:ns="http://example.test.com/Trialmethods/Run"
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" 
exclude-result-prefixes="ns xsl">

<xsl:template match="/">
    <xsl:apply-templates select="*"/>
</xsl:template>

<!-- Identity template, provides default behavior that copies all content-->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<!-- More specific template for ns:Details that provides custom behavior -->
<xsl:template match="ns:Details">
    <PartyDetails>
        <xsl:apply-templates select="*" mode="strip"/>
    </PartyDetails>
</xsl:template>

<!-- template to strip out namespaces-->
 <xsl:template match="*" mode="strip">
    <xsl:element name="{local-name()}">
        <xsl:apply-templates select="@*" mode="copy"/>
        <xsl:apply-templates select="*|text()" mode="strip"/>
    </xsl:element>
     </xsl:template>
     </xsl:stylesheet>

Output with empty namespace at renamed element.

  <?xml version="1.0" encoding="UTF-8"?>
  <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header/>
  <s:Body>
  <MethodResponseType xmlns="http://example.test.com/Trialmethods/Run">
  <MessageResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <ListResponse i:nil="true"/>
    <OptionsResponse i:nil="true"/>
    <PartyResponse>
      <DemoHolder>
        <PartyDetails xmlns=""><ContractType>
            <ID>001</ID>
            <Name>
              <FirstName>Mano</FirstName>
              <Initial>1</Initial>
            </Name>
          </ContractType></PartyDetails>
      </DemoHolder>
    </PartyResponse>
             </MessageResponse>
      </MethodResponseType>
      </s:Body>
      </s:Envelope>

Upvotes: 0

Views: 428

Answers (1)

ptha
ptha

Reputation: 916

It's quite hard to follow your question, and there seems to be some typos in your XML, XSL, but here goes...

I assume your XML input document that you are trying to translate is:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
        <MyRequest>
            <ns:Details xmlns:ns="www.newschema">
                <ID>123</ID>
                <Name>
                    <FirstName>John</FirstName>
                </Name>
            </ns:Details>
        </MyRequest>
    </soapenv:Body>
</soapenv:Envelope>

If the output XML you want after the translation is:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
        <MyRequest>
            <PartyDetails>
                <ID>123</ID>
                <Name>
                    <FirstName>John</FirstName>
                </Name>
            </PartyDetails>
        </MyRequest>
    </soapenv:Body>
</soapenv:Envelope>

Then something like the following XSLT will work:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:ns="www.newschema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" exclude-result-prefixes="ns xsl">
    <xsl:template match="/">
        <xsl:apply-templates select="*"/>
    </xsl:template>

    <!-- Identity template, provides default behavior that copies all content into the output -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <!-- More specific template for ns:Details that provides custom behavior -->
    <xsl:template match="ns:Details">
        <PartyDetails>
            <xsl:apply-templates select="*" mode="strip"/>
        </PartyDetails>
    </xsl:template>

    <!-- template to strip out namespaces-->
    <xsl:template match="*" mode="strip">
        <xsl:element name="{local-name()}">
            <xsl:apply-templates select="@*" mode="copy"/>
            <xsl:apply-templates select="*|text()" mode="strip"/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

As I said you seem to have some typos in your XML/XSL

  1. xmlsns:ns instead of xmlns:ns
  2. <xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> instead of <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  3. <xsl:template match="Details" ns=www.Newschema> instead of <xsl:template match="ns:Details">

Ok since you've updated your question to use my XSL, I can see the <PartyDetails xmlns=""> that you're talking about. How about the following:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns="http://example.test.com/Trialmethods/Run" xmlns:ns="http://example.test.com/Trialmethods/Run" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" exclude-result-prefixes="xsl">
    <xsl:template match="/">
        <xsl:apply-templates select="*"/>
    </xsl:template>
    <!-- Identity template, provides default behavior that copies all content-->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    <!-- More specific template for ns:Details that provides custom behavior -->
    <xsl:template match="ns:Details">
        <xsl:element name="PartyDetails">
            <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

I've set the default namespace xmlns="http://example.test.com/Trialmethods/Run", but you also need the xmlns:ns="http://example.test.com/Trialmethods/Run" for the match on ns:Details to work, as well as removing ns from the exclude-result-prefixes="xsl". I've also removed the template with the strip mode. For me this produces the output:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Header/>
    <s:Body>
        <MethodResponseType xmlns="http://example.test.com/Trialmethods/Run">
            <MessageResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
                <ListResponse i:nil="true"/>
                <OptionsResponse i:nil="true"/>
                <PartyResponse>
                    <DemoHolder>
                        <PartyDetails>
                            <ContractType>
                                <ID>001</ID>
                                <Name>
                                    <FirstName>Mano</FirstName>
                                    <Initial>1</Initial>
                                </Name>
                            </ContractType>
                        </PartyDetails>
                    </DemoHolder>
                </PartyResponse>
            </MessageResponse>
        </MethodResponseType>
    </s:Body>
</s:Envelope>

Upvotes: 1

Related Questions