0

I'm using XSLT 1.0 to transform some XML.

I'm not quite sure the best way to explain this, so will use some examples.

My input XML contains a specialization, using the xsi:type declaration. See the Payload node:

<ns0:RootNode xmlns:ns0="namespace1" xmlns:ns1="namespace2" xmlns:xsi="http://www.w3.org/2001/XMLSchema">
  <ns0:Payload xsi:type="ns1:SpecialPayload">
    <ns1:InnerNode>Hello</ns1:InnerNode>
  </ns0:Payload>
</ns0:RootNode>

When I send this through my XSLT (let's assume a 1 to 1 copy), I get the following output

<ns0:RootNode xmlns:ns0="namespace1" xmlns:xsi="http://www.w3.org/2001/XMLSchema">
  <ns0:Payload xsi:type="ns1:SpecialPayload">
    <ns1:InnerNode xmlns:ns1="namespace2">Hello</ns1:InnerNode>
  </ns0:Payload>
</ns0:RootNode>

Notice the ns1 namespace has been attached to the individual nodes within the payload node. In most cases this would be fine, however I need that declaration to happen earlier, i.e. on the root node, as it makes the xsi:type definition on the payload node invalid, because at this point the serializer does not know about the ns1 namespace, which prevents correct parsing downstream.

What can I do to force this namespace to be output a little earlier?

Edited XSLT Code:

  <!-- Replace The ESBMessage node with the SOAP method -->
  <xsl:template match="s1:ESBMessage" mode="copy">
    <s0:SendESBMessage>
      <s0:msg>
        <xsl:apply-templates select="*" mode="copy"/>
      </s0:msg>
    </s0:SendESBMessage>
  </xsl:template>

  <!-- Generic Copy -->
  <xsl:template match="*" mode="copy">
    <xsl:element name="{name(.)}" namespace="{namespace-uri(.)}">
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates mode="copy"/>
    </xsl:element>
  </xsl:template>
3
  • As you can see from my answer, your question is missing important and necessary information. Please, provide the minimal code example that demonstrates the problem. Commented Oct 12, 2010 at 1:56
  • Hi Dimitre, I have added a code example as requested. I'm just looking through your code to see if there is something there i'm missing. Thank you! Commented Oct 12, 2010 at 2:03
  • Your rule isn't an identity rule at all. You are saying: When matching an element in copy mode, create an element with the same QName and the same namespace URI. Add as content a copy of attribute childs and apply templates to node childs in copy mode. So, basicaly your are stripping in-scope namespaces, something that doesn't happend when ussing xsl:copy instruction. Commented Oct 12, 2010 at 12:25

1 Answer 1

1

Notice the ns1 namespace has been attached to the individual nodes within the payload node. In most cases this would be fine, however I need that declaration to happen earlier, i.e. on the root node, as it makes the xsi:type definition on the payload node invalid, because at this point the serializer does not know about the ns1 namespace, which prevents correct parsing downstream.

What can I do to force this namespace to be output a little earlier?

You can do something very simple: show us your code!

Your statement that a "simple copy" loses one of the namespaces of the top node, is not true for the following two "simple copies":

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

when this transformation is applied on the provided XML document:

<ns0:RootNode xmlns:ns0="namespace1" xmlns:ns1="namespace2" xmlns:xsi="http://www.w3.org/2001/XMLSchema">
  <ns0:Payload xsi:type="ns1:SpecialPayload">
    <ns1:InnerNode>Hello</ns1:InnerNode>
  </ns0:Payload>
</ns0:RootNode>

the result is identical:

<ns0:RootNode xmlns:ns0="namespace1" xmlns:ns1="namespace2" xmlns:xsi="http://www.w3.org/2001/XMLSchema">
  <ns0:Payload xsi:type="ns1:SpecialPayload">
    <ns1:InnerNode>Hello</ns1:InnerNode>
  </ns0:Payload>
</ns0:RootNode>

Here is the second "simple copy":

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  <xsl:copy-of select="."/>
 </xsl:template>
</xsl:stylesheet>

the result is again identical to the source XML document.

Sign up to request clarification or add additional context in comments.

2 Comments

Dimitre, I replaced my copy code with yours and it worked. Why is it that the * semantics does not do the same as node()?@*?
@themistry: I cannot answer your question without having seen your code. I guess that you are copying element nodes, but somehow you are not copying namespace nodes. This may happen if you are using the <xsl:element> instruction. Anyway, your unshown code, obviously isn't a "copy" transformation.

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.