RE: [xsl] Getting rid of xmlns="" attributes

Subject: RE: [xsl] Getting rid of xmlns="" attributes
From: "Lars Huttar" <lars_huttar@xxxxxxx>
Date: Tue, 30 Dec 2003 20:34:10 -0600
If I understand you right, the source XML elements have no
namespace, and you want the result XML elements to be in no
namespace. However,

> I need
> to add two namespaces to the XML.

I take this to mean you want to add two namespace
declarations to the output,
"http://tempuri.org/FormSchema.xsd";
and
"http://www.w3c.org/2001/XMLSchema-instance";

Clearly the desired prefix for the latter is "xsi",
and you've got that covered.
But what prefix do you want for the former? And what
elements do you want to be in that namespace?
In your stylesheet you're using the null prefix,
i.e. you're making "...tempuri.org..." the default namespace.

As a result, your output <template> element is in
this "...tempuri.org..." namespace (because result tree
elements with no namespace prefix go in the stylesheet's
default namespace). Is that what you wanted?
Did you want the other elements to be in that namespace too?

As you hinted at, xsl:copy-of copies the child elements
and preserves their namespaces, i.e. no namespace. So
the serializer has to add a declaration xmlns="" to the children
in order to override the xmlns="...tempuri.org..." on the parent.

If you want the child elements to be in the tempuri.org
namespace too, you'll need to use a modified identity transform
(as I wrote in a message on this list earlier today... is this
an FAQ?):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

  <xsl:template match="*" priority="3">
    <xsl:element name="{local-name()}"
	 	namespace="http://www.tempuri.org/...";>
      <xsl:apply-templates select="@*|node()" />
    </xsl:element>
  </xsl:template>

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


More interspersed below...


Erik Allen wrote:
> 
> 	I've been using XSL for a few months now and I've been given a
> request for a transformation of our XML document into another XML
> document, with only some slight changes. One of the changes 
> is to remove
> a xml:space="preserve" attribute, but I consider that a 
> trivial problem
> that I can easily solve. (I'm just explicitly writing the element with
> the two other attributes that appear.) The bigger problem is 
> that I need
> to add two namespaces to the XML.
> 	From what I've read on this list, the best place to do something
> like that is to place the namespace definitions within the
> <xsl:stylesheet> element. I've done that, but now all the 
> child elements
> have xmlns="" appearing within them. My XSL looks like this:
> 
> <?xml version="1.0" encoding="iso-8859-1"?>
> <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
> 			xmlns="http://tempuri.org/FormSchema.xsd";
> 	
> xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance";
> 			version = '1.0'>
> 
> <xsl:output method="xml"/>
> 
> <xsl:template match="/template">
> 	<template>
> 		<xsl:attribute name="version">
> 			<xsl:value-of select="@version"/>
> 		</xsl:attribute>
> 		<xsl:attribute name="readVersion">
> 			<xsl:value-of select="@readVersion"/>
> 		</xsl:attribute>
> 		<xsl:copy-of select="*"/>
> 	</template>
> </xsl:template>
> 
> </xsl:stylesheet>
> 
> 	The transformation appears to work fine, except, as I said, the
> child elements of the root <template> element, all have the attribute
> xmlns="". A short snippet of it would be this:
> 
> <?xml version="1.0" encoding="utf-8"?>
> <template xmlns="http://tempuri.org/FormSchema.xsd";
> xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"; version="3"
> readVersion="3">
>   <exportTimeStamp xmlns="">
>     <date>2003-12-29</date>
>     <time>15:31:34</time>
>   </exportTimeStamp>
>   <templateInfo xmlns="" name="" id="1139410602" revision="1">
>     
>   </templateInfo>
>   ...
> </template>
> 
> 	I've found that if I change the namespace in the
> <xsl:stylesheet> from xmlns to xmlns:y, then I don't get the rogue
> attribute,

That makes sense. You no longer have a non-null default namespace,
so there is no need to override the default namespace to produce
elements that are in no namespace.

> but that is also giving me the incorrect namespace.

Here is where I would need more specifics to understand what you want.
Which elements have the incorrect namespace and what namespace
did you want them to have?

(Terminology precision check ... do you mean the namespace is incorrect,
or a namespace declaration, or a namespace prefix?)

Do you want all of the output XML to be in no namespace? all
in the tempuri namespace? some of each?
If the latter, what namespace prefix do you want used for each?
You can't use "" as a prefix for two different namespaces,
unless you put xmlns="..." in multiple places.

> The
> source XML does not have any namespaces defined within it, and I think
> that I read somewhere that the <xsl:copy-of> might have issues with
> that. 
> 	Is there anyway to get the namespaces to come out correctly,
> without giving me the xmlns=""?
> 
> 	Erik Allen
> 

Hope this helps,
Lars


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread