Subject: Re: [xsl] Namespace attached to host doc rather than payload From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx> Date: Wed, 18 Jun 2003 10:44:15 +0100 |
Hi David, > To be conformant with the specification I am trying to meet, the > namespace of the payload document must appear on the "payload" > element as above. However, when I run a stylesheet transformation on > the document (using .NET 1.1 System.Xml.Xsl.XslTransform) the > namespace is moved to top-level "ListRecords" element. First, you need to understand that the namespace declarations that you see in the result of your transformation come about because of the position of namespace nodes within the result tree that you're generating. A namespace declaration will be added to an element if it has a namespace node that its parent doesn't have. So the tree that you want to create looks like: ListRecords +- record +- header | +- identifier | +- "i1" +- body +- payload | \- namespace: x = http://www.example.com/ex/ +- x:one | | \- namespace: x = http://www.example.com/ex/ | +- "one" +- x:two | | \- namespace: x = http://www.example.com/ex/ +- "two" (I've omitted the namespace node for the XML namespace from the above, for brevity.) You want the <payload> element to have a namespace node that associates the prefix 'x' with the namespace 'http://www.example.com/ex/' but for none of its parents to have that namespace node. When you create an element using a literal result element such as the <ListRecords> element in: > <xsl:template match="data"> > <ListRecords> > <xsl:apply-templates select=".//datum" /> > </ListRecords> > </xsl:template> then the resulting element is given namespace nodes for all the namespaces that are in-scope for that element, minus the XSLT namespace and minus those namespaces that are specified as being excluded result prefixes (using the [xsl:]exclude-result-prefixes attribute). In your stylesheet, you declare the http://www.example.com/ex/ namespace right at the top level of the stylesheet, on the <xsl:transform> element, and you don't list it as an excluded namespace. That means that it's in-scope throughout the stylesheet, so every element that you create with a literal result element gets a namespace node for that namespace. This is why you get the namespace declaration on the <ListRecords> element in the result. What you need to do is make sure that the namespace node for the http://www.example.com/ex/ namespace is either only in scope for the <payload> element or exclude it for all but the <payload> element. To achieve the effect that you want by only having the namespace in scope for the <payload> element, I think it would be easiest to split the stylesheet into two, since you want to use the 'x' namespace in other templates -- one part that handles the wrapper and one part that handles the payload -- and include the former into the latter. For example: --- wrapper.xsl --- <?xml version="1.0" encoding="UTF-8"?> <xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:include href="payload.xsl" /> <xsl:output method="xml" omit-xml-declaration="yes" /> <xsl:template match="data"> <ListRecords> <xsl:apply-templates select=".//datum" /> </ListRecords> </xsl:template> <xsl:template match="datum"> <record> <header> <identifier> <xsl:value-of select="identifier" /> </identifier> </header> <body> <xsl:apply-templates select="." mode="payload" /> </body> </record> </xsl:template> </xsl:transform> --- --- payload.xsl --- <xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:q="http://www.example.com/queue/" xmlns:x="http://www.example.com/ex/" exclude-result-prefixes="q"> <xsl:template match="datum" mode="payload"> <payload> <xsl:apply-templates select=".//q:one" /> <xsl:apply-templates select=".//q:two" /> </payload> </xsl:template> <xsl:template match="q:one"> <x:one> <xsl:value-of select="." /> </x:one> </xsl:template> <xsl:template match="q:two"> <x:two> <xsl:value-of select="." /> </x:two> </xsl:template> </xsl:transform> --- To achieve the effect you want by managing exclude-result-prefixes, you need to exclude the 'x' prefix only on the subtree that's used for generating the wrapper: <?xml version="1.0" encoding="UTF-8"?> <xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:q="http://www.example.com/queue/" xmlns:x="http://www.example.com/ex/" exclude-result-prefixes="q"> <xsl:output method="xml" omit-xml-declaration="yes" /> <xsl:template match="data"> <ListRecords xsl:exclude-result-prefixes="x"> <xsl:apply-templates select=".//datum" /> </ListRecords> </xsl:template> <xsl:template match="datum"> <record xsl:exclude-result-prefixes="x"> <header> <identifier> <xsl:value-of select="identifier" /> </identifier> </header> <body> <xsl:apply-templates select="." mode="payload" /> </body> </record> </xsl:template> <xsl:template match="datum" mode="payload"> <payload> <xsl:apply-templates select=".//q:one" /> <xsl:apply-templates select=".//q:two" /> </payload> </xsl:template> <xsl:template match="q:one"> <x:one> <xsl:value-of select="." /> </x:one> </xsl:template> <xsl:template match="q:two"> <x:two> <xsl:value-of select="." /> </x:two> </xsl:template> </xsl:transform> You'll notice that in both stylesheets I've used a separate template, in 'payload' mode, to generate the <payload> element, so that it appears in a different scope from its parent and can therefore have different namespace nodes on it. Let us know if anything is unclear. 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 -> |
---|---|---|
Re: [xsl] Namespace attached to hos, david_n_bertoni | Thread | [xsl] Using msxsl:script or EXSLT f, Claudio Russo |
Re: [xsl] grouping by unique..., David Carlisle | Date | Re: [xsl] Special Characters in IE , David Carlisle |
Month |