Subject: Re: [xsl] Creating an attribute name of xmlns:xyz From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx> Date: Tue, 13 Feb 2001 12:49:43 +0000 |
Hi Gilles, > I an writing an xsl file which creates another xsl file. It works fine > except I need teh original xsl file to create the following statement: > > <stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" > xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0" version="1.0"> > > To do so, the following xsl statements are used: > > <element name="stylesheet"> > <attribute name="xmlns">http://www.w3.org/1999/XSL/Transform</attribute> > <attribute name="xmlns:xfa" > namespace="http://www.xfa.org/schema/xfa-data/1.0"> > http://www.xfa.org/schema/xfa-data/1.0 > </attribute> > <attribute name="version">1.0</attribute> > ... > </element> Namespace declarations (which are what the xmlns:... attributes are) aren't treated as attributes in XSLT. The purpose of a namespace declaration is to associate a particular prefix (e.g. 'xfa') with a particular namespace URI (e.g. http://www.xmfa.org/schema/xfa-data/1.0) in a particular document. Within a node tree, there are no namespace declarations. Instead, every element within the scope of a namespace declaration has a namespace *node* on it, representing the mapping between the prefix and the namespace URI. XSLT works on these namespace nodes - the namespace declarations themselves don't exist in a node tree. This works on the source XML (you can't select a namespace declaration with the attribute axis) and on the result XML (you can't create a namespace declaration as an attribute, which is what you're attempting to do above). Instead, namespace declarations are created automatically when a node tree is serialised into some output. When an element is written, if it has a namespace node on it but there's not been a namespace declaration that matches that namespace node, then the serialiser writes a namespace declaration on that element. So what you are really trying to do is to create a 'stylesheet' element in the result tree that has (at least) two namespace nodes on it: the XSLT namespace and the XFA namespace. And you'd like the XSLT namespace to be the default namespace (though logically it doesn't matter - it's just a case of which prefix is used for it). Now consider the node tree for the XSLT stylesheet itself. It will have things like xsl:template element nodes, namespace nodes for the XSLT namespace and so on. If you declare a namespace at the top of your stylesheet, then all the elements in the stylesheet node tree will have namespace nodes for that namespace. The rules for what namespace nodes are put on an element in the result tree depend on how you create the element. If you create the element with a literal result element, then most namespace nodes that are present on that literal result element are put in the result tree. If you use xsl:element, then the only extra namespace node that can be created is one that you use to identify the namespace of the element itself. [It's only *most* namespace nodes because some namespace nodes, namely the XSLT namespace node and any with prefixes given in the extension-element-prefixes or exclude-result-prefixes attributes, aren't put in the result tree. This has implications I'll come on to later.] So, there are two ways to get the XFA namespace node onto the element that you're creating. You can declare it for the stylesheet as a whole: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0"> ... <stylesheet version="1.0"> ... </stylesheet> ... </xsl:stylesheet> or you can declare it specifically for the stylesheet element that you're creating: <stylesheet version="1.0" xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0"> ... </stylesheet> Remember that this is *not* the same as creating an attribute on the 'stylesheet' element - the xmlns:xfa attribute is a namespace declaration, used to create a load of *namespace nodes* on the 'stylesheet' element and all its element descendants in the *stylesheet tree* (including any XSLT instructions that it holds). Because the 'stylesheet' element in the stylesheet node tree has this namespace node, it will be copied with it into the result tree, so the 'stylesheet' element in the result tree (or one of its ancestors) will have an equivalent namespace declaration on it. So that's the *easy* one! ;) Now, when we come to the XSLT namespace it's a bit more tricky because the XSLT namespace nodes aren't included within the result tree 'cos most of the time you don't care about them. If they *were* included, then most result documents would have XSLT namespace declarations all over the place - really annoying! Instead, there's a trick specifically designed to help you create stylesheets that create stylesheets: xsl:namespace-alias. xsl:namespace-alias allows you to say that the namespace URI of a particular namespace in the result tree should be replaced with another namespace URI. What you need to do is declare a namespace with a made-up namespace URI, for example http://www.w3.org/1999/XSL/TransformAlias, that you use as a placeholder for the XSLT namespace URI that you want to use. Then you can place this made-up namespace on any element in the same way as indicated above, e.g.: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0" xmlns="http://www.w3.org/1999/XSL/TransformAlias"> ... <stylesheet version="1.0"> ... </stylesheet> ... </xsl:stylesheet> Now, the 'stylesheet' literal result element's namespace nodes will include the alias for the XSLT namespace, as well as the XFA namespace node. In fact, because the 'stylesheet' element has no prefix, it will be placed in the default namespace, specified as "http://www.w3.org/1999/XSL/TransformAlias". You then use xsl:namespace-alias to tell the XSLT processor that the namespace URI "http://www.w3.org/1999/XSL/TransformAlias" (the default namespace) should be mapped to the namespace URI "http://www.w3.org/1999/XSL/Transform" in the final result. You refer to each of these namespaces using their prefix, or '#default' if it's the default namespace: <xsl:namespace-alias stylesheet-prefix="#default" result-prefix="xsl" /> The other approach would be to state that the 'stylesheet' element is in the XSLT namespace by defining it with the xsl:element element: <xsl:element name="stylesheet" namespace="http://www.w3.org/1999/XSL/Transform"> <xsl:attribute name="version">1.0</xsl:attribute> ... </xsl:element> This is quite a bit longer, especially because it means you have to define the other attributes using xsl:attribute elements and so on. I hope that helps, 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] Creating an attribute name of, Gilles Maurice | Thread | [xsl] does XSLT Processor validate , anand awasthi |
Re: [xsl] Copying Groups of Attribu, Oliver Becker | Date | Re: [xsl] Need for a technique, Dimitre Novatchev |
Month |