-1

In my case,The Input xml must have a declaration of namespace of which the root element (i.e. <message>) is part of .

In the example 1,<message> element is a part of namespace http://www.origostandards.com/schema/mtg/v2.It is declared in the xml and the <message> element is present in the xml with the prefix mtg.The styelesheet which I have developed conforms to this requirement, but doesn't preserve the namespace for other elements than the root element. If namespace of which the message element is a part of, is not declared (example2), then the styelesheet must produce an output having the default namespace http://www.origoservices.com declared in the root element.(See example2)

However, the stylesheet which I have developed works well in case of (example 2) which doesn't have the namespace prefixes assigned to the elements and doesn't work for the xmls having namespace element names prefixed with namespace (example1).

Example 1 input xml

<?xml version="1.0"?>
<mtg:message xmlns:ce="http://www.origostandards.com/schema/ce/v2" xmlns:mtg="http://www.origostandards.com/schema/mtg/v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<mtg:m_control id="m_control1">
    <mtg:control_timestamp>2014-12-18T10:06:00-05:00</mtg:control_timestamp>
    <mtg:message_id>c5-a4e0-aa0090358c7f</mtg:message_id>
    <mtg:retry_number>0</mtg:retry_number>
    <mtg:expected_response_type>synchronous</mtg:expected_response_type>
    <mtg:initiator_id>temp</mtg:initiator_id>
    <mtg:responder_id/>
</mtg:m_control>
<ce:m_content>
    <ce:b_control>
        <ce:reference>xyz</ce:reference>
    </ce:b_control>
</ce:m_content>
</mtg:message>

Actual output

 <?xml version="1.0" encoding="UTF-8"?>
 <mtg:message xmlns:ce="http://www.origostandards.com/schema/ce/v2" xmlns:mtg="http://www.origostandards.com/schema/mtg/v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<m_control xmlns="http://www.origostandards.com/schema/mtg/v2" id="m_control1">
    <control_timestamp>2014-12-18T10:06:00-05:00</control_timestamp>
    <message_id>c5-a4e0-aa0090358c7f</message_id>
    <retry_number>0</retry_number>
    <expected_response_type>synchronous</expected_response_type>
    <initiator_id>temp</initiator_id>
    <responder_id/>
</m_control>
<m_content xmlns="http://www.origostandards.com/schema/mtg/v2">
    <b_control>
        <reference>xyz</reference>
    </b_control>
</m_content>
</mtg:message>

Expected Output

 <?xml version="1.0"?>
 <mtg:message xmlns:ce="http://www.origostandards.com/schema/ce/v2" xmlns:mtg="http://www.origostandards.com/schema/mtg/v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <mtg:m_control id="m_control1">
    <mtg:control_timestamp>2014-12-18T10:06:00-05:00</mtg:control_timestamp>
    <mtg:message_id>c5-a4e0-aa0090358c7f</mtg:message_id>
    <mtg:retry_number>0</mtg:retry_number>
    <mtg:expected_response_type>synchronous</mtg:expected_response_type>
    <mtg:initiator_id>temp</mtg:initiator_id>
    <mtg:responder_id/>
</mtg:m_control>
<ce:m_content>
    <ce:b_control>
        <ce:reference>xyz</ce:reference>
    </ce:b_control>
</ce:m_content>
</mtg:message>

Example 2 - Stylesheet is working as expected for this Input xml

<message>
  <m_control>
    <control_timestamp>2014-11-05T09:30:38.308</control_timestamp>
    <retry_number>0</retry_number>
    <expected_response_type>synchronous</expected_response_type>
     <responder_id>Exchange Life 1</responder_id>
   </m_control>
</message>

Expected and Actual Output

<message xmlns="http://www.origoservices.com">
<m_control>
  <control_timestamp>2014-11-05T09:30:38.308</control_timestamp>
  <retry_number>0</retry_number>
  <expected_response_type>synchronous</expected_response_type>
  <responder_id>Exchange Life 1</responder_id>
 </m_control>
 </message>

My stylesheet

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dp="http://www.datapower.com/extensions" xmlns:regexp="http://exslt.org/regular-expressions" extension-element-prefixes="dp" xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="dp regexp exsl">
      <xsl:output method="xml" indent="yes" version="1.0"/>

       <xsl:variable name="origo-svc-ns" select="'http://www.origoservices.com'"/>

      <!--xsl:template match="/message"-->
      <xsl:template match="/*[local-name()='message']">
         <xsl:variable name="name" select="name()"/>
         <xsl:variable name="namespace-in" select="namespace-uri(/*[1])"/>
         <xsl:variable name="initiator_id" select="/*[local-name()='message']/*[local-name()='m_control']/*[local-name()='initiator_id']"/>

   <!--Below code tests if default namespace declaration is present. If not, then assigns the 'default namespace' to 'namespace' variable. Also, it assigns context variable  "AddNamespace"  with value "Y" if default namespace declaration is not present -->       

         <xsl:variable name="namespace">
                  <xsl:choose>
                      <xsl:when test="$namespace-in = '' and ($initiator_id = 'True Potential' or $initiator_id = '2Plan' or $initiator_id = '356356536' or $initiator_id = 'Assyst Software') ">
                              <xsl:value-of select="$origo-svc-ns"/>
                              <dp:set-variable name="'var://context/FL/AddNamspace'" value="'Y'"/>
                      </xsl:when>
                     <xsl:otherwise>
                              <xsl:value-of select="$namespace-in"/>
                     </xsl:otherwise>
                </xsl:choose>
      </xsl:variable>

     <!-- - In below statement, {$namespace} will copy over the default namespace declarartion to the destination.
  - copy-of select statement will copy over all the namespace declaration in the source xml 
  - apply-template will copy over evrything else from the source to destination
  - xsl:element wil create an element node (in this case <message> ) in the destination document.      
    -->

    <xsl:element name="{$name}" namespace="{$namespace}">
       <xsl:copy-of select="namespace::*"/>
      <xsl:apply-templates select="@*|node()|comment()|processing-instruction()|text()">
      <xsl:with-param name="ns-uri" select="$namespace"/>

     </xsl:apply-templates>
     </xsl:element>
  </xsl:template>

  <xsl:template match="node()">

    <xsl:param name="ns-uri"/>
    <xsl:element name="{local-name()}" namespace="{$ns-uri}">
     <xsl:copy-of select="namespace::*"/>
       <xsl:apply-templates select="@*|node()|comment()|processing-instruction()|text()">
        <xsl:with-param name="ns-uri" select="$ns-uri"/>
       </xsl:apply-templates>
     </xsl:element>
  </xsl:template>

  <xsl:template match="@*|comment()|processing-instruction()|text()">
       <xsl:param name="ns-uri"/>
       <xsl:copy>
      <xsl:apply-templates select="@*|node()|comment()|processing-instruction()|text()">
        <xsl:with-param name="ns-uri" select="$ns-uri"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Example of the xml having default namespace declared http://www.origoservices.com is a default namespace in the below example.

  <message xmlns="http://www.origoservices.com" xmlns:a="https://www.bbb.com">
  <m_control>
    <control_timestamp>2014-11-05T09:30:38.308</control_timestamp>
    <message_id>2840c35d-d294-4179-baa1-55ea2ce0b9ac</message_id>
    <retry_number>0</retry_number>
    <message_type>Quotation Request</message_type>
          <message_version>/origo/3.7/QNBPensionAnnuityQuoteRequest.xsd</message_version>
    <expected_response_type>synchronous</expected_response_type>
    <initiator_id>Friends Provident</initiator_id>
       <initiator_orchestration_id>2944460</initiator_orchestration_id>
    <responder_id>Exchange Life 1</responder_id>
</m_control>
 </message>
potame
  • 7,597
  • 4
  • 26
  • 33
user2607367
  • 225
  • 4
  • 25
  • I don't understand the meaning of "*default namespace declaration*". Can you provide an example of such an XML, which works well with your XSLT? Thanks. – potame May 13 '15 at 09:04
  • @potame I have updated the question by adding an example xml at the end of it. My understanding with the namespace concept is not very clear, hence I might have mistaken in calling it as "default namespace declaration" – user2607367 May 13 '15 at 09:20
  • 1
    OK, it is bit clearer but in your expected XML output, I don't see any *default namespace* added. – potame May 13 '15 at 09:27
  • +1 for identifying the flaw in my question.I have updated my question. However, the basically my problem is , the styelesheet that I have developed doesn't preserves the namespaces in case of the example 1 provided in the question. – user2607367 May 13 '15 at 10:23

2 Answers2

0

It is a bit messy, I can't figure out why you don't use the <xsl:copy-of> instruction.

Such stylesheet is much more simple and will do the job properly (I have remove some the the code in first template because I didn't find any use to it for the issue we're interested in here:

<xsl:stylesheet version="1.0" 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:dp="http://www.datapower.com/extensions" 
        xmlns:regexp="http://exslt.org/regular-expressions" 
        xmlns:ce="http://www.origostandards.com/schema/ce/v2"
        xmlns:mtg="http://www.origostandards.com/schema/mtg/v2"
        xmlns:exsl="http://exslt.org/common" 
        exclude-result-prefixes="dp regexp exsl">

    <xsl:output method="xml" indent="yes" version="1.0"/>

    <xsl:variable name="origo-svc-ns" select="'http://www.origoservices.com'"/>

    <xsl:template match="/message">
        <xsl:variable name="name" select="name()"/>


     <!-- - In below statement, {$namespace} will copy over the default namespace declarartion to the destination.
  - copy-of select statement will copy over all the namespace declaration in the source xml 
  - apply-template will copy over evrything else from the source to destination
  - xsl:element wil create an element node (in this case <message> ) in the destination document.      
    -->

      <xsl:element name="{$name}" namespace="{$origo-svc-ns}">
        <!--xsl:copy-of select="namespace::*"/-->
        <xsl:apply-templates select="@*|node()|comment()|processing-instruction()|text()" />
      </xsl:element>
    </xsl:template>

    <xsl:template match="* | mtg:* | ce:*">
        <xsl:copy-of select="."/>
    </xsl:template>

</xsl:stylesheet>

Some explanations:

  1. first I declare the mtg and ce namespaces so that I can use them in the stylesheet.
  2. then I match and process the <message> element with no namespace attached. This element is copied with the appropriate namespace attached, and the child elements are processed
  3. all the other elements are simply copied in the output, with all the sub-elements (and the namespaces).

I've checked this code with both entries (XML examples 1 and 2).

potame
  • 7,597
  • 4
  • 26
  • 33
  • The reason why my xslt looks complicated, because I have to set a value of `context variable` in Datapower to a certain value (lets say 'Y') if a default namespace declaration is not present in the request xml. In my xslt,I am trying to achieve this by using `` . Also, not all request xml will have the same namespaces, hence I have to be dynamic in my approach. Your solution doesn't take care of these things.I hope I have not confused you. – user2607367 May 13 '15 at 15:01
  • OK, it is still possible in this XSLT to restore the removed code. Can you explain the *dynamical aspect* needed in your stylesheet? Is it the purpose of the ``? – potame May 13 '15 at 15:14
0

Your question is very difficult, if not impossible, to understand. Same as your previous question (of which this is a spin-off), it lacks a clear statement of purpose.

If we assume that you just want your stylesheet to perform a certain transformation when the root element is in a default namespace (or in no namespace), and another transformation when it isn't (i.e. it has a prefix), then this could be achieved quite simply, for example:

<xsl:template match="/">
    <xsl:choose>
        <xsl:when test="name(*)=local-name(*)">
            <!-- root element is in a default or no namespace; apply transformation A -->
        </xsl:when>
        <xsl:otherwise>
            <!-- root element has a prefix; apply transformation B -->
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
Community
  • 1
  • 1
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51