1

I'd like to copy only header element with all subnodes and add to every subnode prefix "v11"(including header element)

Source xml:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <ns3:createReservationRequest xmlns:ns3="ns3URL" xmlns:ns2="ns2URL">
            <header>
                <language isoCountryCode="US" isoLanguageCode="en"/>
                <channel name="DT">
                    <subChannel name="WEBWB">
                        <subChannel name="WEBWB">
                            <subChannel name="Functester">
                                <subChannel name="ecom"/>
                            </subChannel>
                        </subChannel>
                    </subChannel>
                </channel>
            </header>
            <ns3:agentInfo>
                <ns2:agentDutyCode>PR</ns2:agentDutyCode>
            </ns3:agentInfo>
        </ns3:createReservationRequest>
    </soap:Body>
</soap:Envelope>

Desired result xml:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
              xmlns:v1="v1URL"
              xmlns:v11="v11URL">
    <soapenv:Body>
        <v1:createBookerEventRequest>
            <v11:header>
                <v11:channel name="DT">
                    <v11:subChannel name="WEBWB">
                        <v11:subChannel name="WEBWB">
                            <v11:subChannel name="Functester">
                                <v11:subChannel name="ecom"/>
                            </v11:subChannel>
                        </v11:subChannel>
                    </v11:subChannel>
                </v11:channel>
            </v11:header>
        </v1:createBookerEventRequest>
    </soapenv:Body>
</soapenv:Envelope>

I've tried to implement this using example from here . I've written the following xsl:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:v11="v11URL">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>

    <xsl:template match="/">
        <xsl:copy>
            <xsl:apply-templates select="//*[local-name()='header']/*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="//*[local-name()='header']/*">
        <xsl:element name="v11:{name()}" inherit-namespaces="no">
            <xsl:apply-templates select="node()|@*"/>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

But it doesn't copy subchannels into result xml. And also adds unwanted "xmlns:v11="http://example.com/schema/common/ATPCommonServiceTypes/v1" attribute to header subnodes. Any help is appreciated

2
  • 2
    Please post a namespace-wellformed XML input sample, currently the ns2:agentDutyCode has a prefix that is not declared. Commented Jun 26, 2014 at 14:32
  • 1
    And the root element is not closed. Commented Jun 26, 2014 at 14:33

2 Answers 2

2

Here is my (edited) suggestion:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
            xmlns:v1="v1URL"
            xmlns:v11="v11URL"
            xmlns:ns3="ns3URL"
            exclude-result-prefixes="soap ns3">

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

<xsl:template match="/*">
  <xsl:copy>
    <xsl:copy-of select="document('')/xsl:stylesheet/namespace::*[local-name() = ('v1', 'v11')]"/>
    <xsl:apply-templates select="@* , node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="*[not(namespace-uri())]">
  <xsl:element name="v11:{local-name()}">
    <xsl:apply-templates select="@* , node()"/>
  </xsl:element>
</xsl:template>

<xsl:template match="ns3:createReservationRequest">
  <v1:createBookerEventRequest>
    <xsl:apply-templates select="@* , node()"/>
  </v1:createBookerEventRequest>
</xsl:template>

<xsl:template match="ns3:agentInfo"/>

</xsl:stylesheet>
Sign up to request clarification or add additional context in comments.

Comments

2

I added a xmlns declaration to agentDutyCode since it is missing a namespace declaration:

<ns2:agentDutyCode xmlns:ns2="ns2URL">PR</ns2:agentDutyCode>

Using the source with this stylesheet (templates explained in the comments):

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:v11="v11URL"
    xmlns:v1="v1URL"
    xmlns:ns3="ns3URL"
    exclude-result-prefixes="ns3">

    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>

    <!-- Copies Envelope and Body preserving their namespace -->
    <xsl:template match="soap:Envelope | soap:Body">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <!-- Creates the createReservationRequest element -->
    <xsl:template match="ns3:createReservationRequest">
        <v1:createBookerEventRequest>
            <xsl:apply-templates/>
        </v1:createBookerEventRequest>
    </xsl:template>

    <!-- Ignores language and agentInfo subtrees -->
    <xsl:template match="language"/>
    <xsl:template match="ns3:agentInfo"/>

    <!-- Matches all other elements -->
    <xsl:template match="*">
        <xsl:element name="v11:{local-name()}" inherit-namespaces="no">
            <xsl:apply-templates select="node()|@*"/>
        </xsl:element>
    </xsl:template>

    <!-- Copies attributes -->
    <xsl:template match="@*">
        <xsl:copy>
            <xsl:value-of select="."/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

You will have this result:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <v1:createBookerEventRequest xmlns:v11="v11URL" xmlns:v1="v1URL">
         <v11:header>
            <v11:channel name="DT">
               <v11:subChannel name="WEBWB">
                  <v11:subChannel name="WEBWB">
                     <v11:subChannel name="Functester">
                        <v11:subChannel name="ecom"/>
                     </v11:subChannel>
                  </v11:subChannel>
               </v11:subChannel>
            </v11:channel>
         </v11:header>
      </v1:createBookerEventRequest>
   </soap:Body>
</soap:Envelope>

Here is an XSLT Fiddle where you can see the result.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.