Subject: [xsl] Removing namespaces from source document (long) From: "Stephen Ng" <stephen.ng@xxxxxxxxxxx> Date: Sun, 7 Apr 2002 18:46:10 -0400 |
I have the feeling this is a newbie faq thing, but I'm still confused after doing a bit of searching this weekend so I'm posting.... I have some (unused) namespace declarations in my source xml document that I want to banish. For example: <?xml version="1.0" encoding="UTF-8"?> <root xmlns:good-ns="http://good.com" xmlns:bad-ns="http://bad.com"> <parent color="red"> <good-ns:child shape="square"> some text </good-ns:child> </parent> </root> I want to transform this to get: <?xml version="1.0" encoding="UTF-8"?> <root xmlns:good-ns="http://good.com"> <parent color="red"> <good-ns:child shape="square"> some text </good-ns:child> </parent> </root> I understand that, in general, the xslt processor must emit the "bad-ns" declaration at the top because it can't tell that it isn't used later. So, of course, an identity template just gives me the same thing <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="node()|@*"> <xsl:copy-of select="."/> </xsl:template> </xsl:stylesheet> Jeni Tennison in her book seems to be saying this is because I'm doing a copy-of. Quoting liberally: --- When you copy an element from the source tree using xsl:copy-of, the element, all its namespace nodes, all its attributes, and all its children are copied - you generate a deep copy. This means that any namespaces in scope for that element in the source have to be in scope for that element in the result. Because source XML often declares namespaces that you're not interested in, this can lead to unwanted namespace declarations. You can remove these namespace declarations by using a recursive shallow copy, rather than the deep copy generated by xsl:copy-of. You can generate shallow copies recursively with an identity template, as shown in the following example: <xsl:template match="@*|node()" mode="copy"> <xsl:copy> <xsl:apply-templates select="@*|node()" mode="copy" /> </xsl:copy> </xsl:template> --- But if I do: <xsl:template match="/"> <xsl:apply-templates mode="copy"/> </xsl:template> plus her template, I get the same results: bad-ns is still declared. Am I misunderstanding her example? Ken Holman in http://www.biglist.com/lists/xsl-list/archives/200003/msg00303.html has an example of a stylesheet which omits a namespace which originates from the source document, but it's done by hard-wiring the element name inside the stylesheet: <xsl:template match="/"> <!--root rule--> <result> <xsl:apply-templates select="/doc/para"/> </result> </xsl:template> <xsl:template match="para"> <para> <xsl:apply-templates/> </para> </xsl:template> This is not general though, so I wrote: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:good-ns="http://good.com"> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="*"> <xsl:element name="{name()}"> <xsl:apply-templates select="node()|@*"/> </xsl:element> </xsl:template> <xsl:template match="@*"> <xsl:copy/> </xsl:template> </xsl:stylesheet> which seems to work. The "good" namespace must be declared for <xsl:element> to properly emit the element. So, my questions are: Is this correct? and Is there a better way to do this? and if not, Isn't this a bit convoluted for what seems like a pretty common task? Thanks, Stephen Ng Lumigent XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] Conditional indentation?, Michael Kay | Thread | Re: [xsl] Removing namespaces from , Christopher R. Maden |
[xsl] Conditional indentation?, Ned Batchelder | Date | Re: [xsl] Counting proceding elemen, Joerg . Heinicke |
Month |