Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XSLT transform XML with default namespace without adding prefix?

Tags:

.net

xml

xslt

I am trying to transform an XML file with the following namespace, but couldn't 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">  

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 ?

like image 913
Paul L Avatar asked Sep 06 '10 05:09

Paul L


3 Answers

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">
 <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">
  <Goods>
    <item name="tobacco">
      <price>5</price>
      <quantity>1000</quantity>
    </item>
    <item name="wine">
      <price>3</price>
      <quantity>5000</quantity>
    </item>
  </Goods>
</pExport>
like image 62
Dimitre Novatchev Avatar answered Oct 07 '22 17:10

Dimitre Novatchev


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.

like image 37
dolmen Avatar answered Oct 07 '22 17:10

dolmen


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">
  <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"></element>
<ns01:element xmlns:ns01="http://test.com"></ns01:element>

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

like image 22
samjudson Avatar answered Oct 07 '22 18:10

samjudson