tags:

views:

60

answers:

3

Hi, I am trying to transform an XML file with the following namespace, but could find out a way to make it working with the default namespace without adding a prefix to the output XML.

Original XML file:

<pExport xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://workflow.converga.com.au/compass"&gt;  

I can make it working by adding a prefix to the default namespace (the last one), but how could I output a XML without adding a prefix, it is possible by using XslCompiledTransform in .NET 4 ?

+1  A: 

You simply need to define your default namespace in the XSLT. If you also define one with a prefix as well so you can select items from the input XML with ease:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://workflow.converga.com.au/compass" xmlns:compass="http://workflow.converga.com.au/compass"&gt;
  <xsl:template match="compass:pExport">
    <pExport>...</pExport>
  ...

The above template will match against your input XML element - and the literal element created will be in the default output namespace (which is the same namespace).

Of course you should be aware that in XML the prefix is irrelevant - two items are identical if they have the same namespace and local name, even if the two prefixes are defined for that one namespace.

<element xmlns="http://test.com"&gt;&lt;/element&gt;
<ns01:element xmlns:ns01="http://test.com"&gt;&lt;/ns01:element&gt;

The two elements above are the same because they have the same fully qualified name.

samjudson
@samjudson: for copying the matched element with the same namespace, you don't need to declare a default namespace for output, `copy` instruction also works in that way.
Alejandro
@samjudson I think you are right in the sense that prefix shouldn't affect namespace. And your solution works in that sense. What I am looking for is a solution without adding my own prefix to the default namespace.
pstar
@samjudson: The prefix is irrelevant *in theory*. In practice, some parsers are not namespace compliant but you still want to generate the document with a compliant writer. Also the specifications of some XML-based standrards does not use a namespace at all.
dolmen
A: 

I can make it working by adding a prefix to the default namespace (the last one), but how could I output a XML without adding a prefix, it is possible by using XslCompiledTransform in .NET 4 ?

Here is a concrete example how to do it:

This transformation:

<xsl:stylesheet version="1.0"
 xmlns="http://workflow.converga.com.au/compass"
 xmlns:c="http://workflow.converga.com.au/compass"
 xmlns:ext="http://exslt.org/common"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 exclude-result-prefixes="c ext xsl">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pnewItem">
  <item name="wine">
   <price>3</price>
   <quantity>5000</quantity>
  </item>
 </xsl:param>

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

 <xsl:template match="c:item[last()]">
  <xsl:call-template name="identity"/>
  <xsl:copy-of select="ext:node-set($pnewItem)/*"/>
 </xsl:template>
</xsl:stylesheet>

when applied with XslCompiledTransform on the following XML document:

<pExport xmlns="http://workflow.converga.com.au/compass"&gt;
 <Goods>
  <item name="tobacco">
   <price>5</price>
   <quantity>1000</quantity>
  </item>
 </Goods>
</pExport>

produces the wanted (the same XML document with a new item added), correct result:

<pExport xmlns="http://workflow.converga.com.au/compass"&gt;
  <Goods>
    <item name="tobacco">
      <price>5</price>
      <quantity>1000</quantity>
    </item>
    <item name="wine">
      <price>3</price>
      <quantity>5000</quantity>
    </item>
  </Goods>
</pExport>
Dimitre Novatchev
Thank you, following your example, I made it working by adding extra default namespace without prefix and "exclude-result-prefixex" options. Actually I don't fully understand your code and how they are suppose to working (just learned XSLT yesterday). For example what are these <XSL:param> section in your first code block doing?
pstar
A minor thing, in the output XML the default namespace is always the first one, could I change that to the last one, which is the position from the original XML.
pstar
@pstar: The XSLT and XML W3C specifications do not mandate any specific order for attributes and namespace nodes. Their relative ordering is "implementation dependent". This means that depending on the concrete XSLT processor you're using you have either no control over the ordering of namespace declarations, or if you have some control, that this "feature" isn't portable and is not supported by other XSLT processors.
Dimitre Novatchev
@pstar: The `<xsl:param>` in my code serves the example I have chosen. In this example the goal of the transformation is to add a new item after the last one in the document. The body of the `<xsl:param>` instruction contains the actual `item` to be added. The value of a global-level `<xsl:param>` can be set externally when the transformation is being invoked. Thus the same transformation can be used to add different items, by passing them as parameters to the transformation.
Dimitre Novatchev
A: 

The key is to use the exclude-result-prefixes attribute on the stylesheet element.

There are some good explanations in this section of the XSLT FAQ.

dolmen
THank you Dolment for point out the information for me. Actually , I've already read a bit of XSLT, but didn't found it. Guess the FAQ is a little too much information for me.
pstar
A good way to thank for an answer is to vote for it clicking on the up arrow on the left side. Could you do it for mine?
dolmen