Subject: Re: [xsl] spurious attribute From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Tue, 26 Feb 2002 09:50:54 +0000 |
Hi Simon, > I have some xml I'm transforming either into html or into xhtml. i'd > prefer the latter, but if that's going to cause a problem, i'll > settle for the former). I'm using MSXML 3.0 parser and transforming > by running a little JS script with the Windows Scripting Host. A > majority of the tags generated are coming out with an xmlsn="" empty > attribute and I don't know why. I'm sure this is something to do > with the xsl:stylesheet and xsl:output elements i'm using, but can't > immediately see what about them may cause this to happen. The xmlns="" attributes are there to reset the default namespace to no namespace. My guess would be that somewhere in the stylesheet, you have something like: <xsl:template match="/"> <html xmlns="http://www.w3.org/1999/xhtml"> ... <xsl:apply-templates /> ... </html> </xsl:template> <xsl:template match="foo"> <p> <xsl:apply-templates /> </p> </xsl:template> To understand what's going on, you have to understand namespaces and how XSLT generates elements. Attributes that begin with 'xmlns' are namespace declarations; they associate a prefix with a namespace URI. In the above, the xmlns attribute is a namespace declaration for the XHTML namespace, and it makes the XHTML namespace the default namespace. Namespace declarations have a certain scope, namely the element that they are on and their descendants. In the above, the XHTML default namespace declaration has a scope of the html element, its children in that template, down to the xsl:apply-templates element. Note that the scope of the namespace follows the structure of the XSLT stylesheet as an XML document, not the flow of the stylesheet as it runs. Setting the default namespace means that any element in the scope of the namespace that doesn't have a prefix is placed in that namespace. So in the above, the html element is in the XHTML namespace because it doesn't have a prefix and because there's a default namespace declaration for the XHTML namespace in scope. On the other hand, there's no default namespace declaration in scope for the p element in the second template. That means that the p element is in no namespace. When the XSLT processor generates the result tree, it creates new elements, which might or might not have a namespace. When you create an element with a literal result element, such as the html and p elements in the above, then the namespace of the element in the result is the same as the namespace of the literal result element in the stylesheet. Thus the above generates an html element in the XHTML namespace, and a p element in no namespace. When the XSLT processor serialises the result tree, it needs to make sure that the elements in the result document are in the correct namespaces. Elements in no namespace cannot have a prefix, so it only has a couple of options here: <html:html xmlns:html="http://www.w3.org/1999/xhtml"> ... <p>...</p> ... </html:html> [I've used the prefix 'html' for clarity; usually a processor would actually use something like 'ns1', since it can't know what prefix 'makes sense' for a particular namespace.] or: <html xmlns="http://www.w3.org/1999/xhtml"> ... <p xmlns="">...</p> ... </html> Processors will usually opt for the second of the choices because they try to preserve the prefixes (or lack of them) that you've used on the literal result elements. So how do you fix it? Well, what you wanted was for both the html and the p element to be in the XHTML namespace. If you move the default namespace declaration so that it covers both the html element and the p element in the stylesheet, then both the elements will be in the XHTML namespace, and therefore the processor won't have to reassign the default namespace when it serialises the result tree. To make the XHTML namespace the default namespace throughout the stylesheet, declare it in the xsl:stylesheet document element: <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:xql="#xql-functions" xmlns:auto-ns1="http://www.w3.org/TR/WD-xsl" xmlns:global="#local-functions" xmlns="http://www.w3.org/1999/xhtml"> ... </xsl:stylesheet> That way any literal result element that you specify without a prefix will be placed in the XHTML namespace, and the elements in the result will therefore all be in the XHTML namespace. The processor will work out that it only needs to place a namespace declaration on the html element and all the elements in the document will be in scope of that namespace declaration. The moral of the story is that you can't treat namespace declarations like other attributes. Cheers, Jeni --- Jeni Tennison http://www.jenitennison.com/ XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
[xsl] spurious attribute, Simon Dell | Thread | [xsl] Transform into text or bmp, Jean . Ossmann |
Re: [xsl] Difference between these , Trevor Nash | Date | Re: [xsl] Difference between these , Peter Davis |
Month |