views:

24

answers:

1

Hi guys,

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"&gt;
  <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"&gt;
  <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?

would really appreciate any help on this one,

Kind regards TM

Editted 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>
+1  A: 

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"&gt;
 <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"&gt;
  <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"&gt;
  <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"&gt;
 <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.

Dimitre Novatchev
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
@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.
Dimitre Novatchev