Subject: Re: [xsl] Namespace de-duplication for dynamically generated elements From: Florent Georges <lists@xxxxxxxxxxxx> Date: Tue, 9 Sep 2008 10:50:04 +0200 (CEST) |
Ian Stokes-Rees wrote: Hi > We want a single XSLT which will handle these without a priori > knowledge of the QNames or namespace *inside* the @name attribute. First of all, rather than dealing with parsing the QName myself, I would use resolve-QName(): <xsl:template match="foo"> <xsl:variable name="qn" select="resolve-QName(@name, .)"/> <xsl:element name="{ $qn }" namespace="{ namespace-uri-from-QName($qn) }"> <xsl:apply-templates select="@*|node()"/> </xsl:element> </xsl:template> I find that weird that when you have a QName (so a local name, a prefix and a ns URI,) you can't just use: <xsl:element name="{ $qn }"/> Then what you describe doesn't match the output you showed. You should have got (without prefixes): <zip> apple </zip> <zap> orange </zap> Then what you described (having the ns declarations on the subelements only) can be because you create a new element instead of copying the initial order element. What you want is to ensure that the output element has the correct binding, and you can do that copying the namespaces of order: <xsl:template match="order"> <output> <xsl:copy-of select="namespace::*"/> <xsl:apply-templates select="@*|node()"/> </output> </xsl:template> But the namespace axis is deprecated in XPath 2.0. So you might want to use the following instead: <!-- Same as <xsl:copy-of select="$context/namespace::*"/>, but without using the deprecated axis namespace::. --> <xsl:function name="fg:copy-namespaces"> <xsl:param name="context" as="element()"/> <xsl:for-each select="in-scope-prefixes($context)"> <xsl:namespace name="{ . }" select=" namespace-uri-for-prefix(., $context)"/> </xsl:for-each> </xsl:function> <xsl:template match="order"> <output> <xsl:sequence select="fg:copy-namespaces(.)"/> <xsl:apply-templates select="@*|node()"/> </output> </xsl:template> So here is a sample of transform that gives you what you are after I think, for your sample: <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fg="http://www.fgeorges.org/xslt/functions" version="2.0"> <!-- Modified Identity Transform pattern. --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- Copy initial ns bindings. --> <xsl:template match="order"> <output> <xsl:copy-of select="namespace::*"/> <xsl:apply-templates select="@*|node()"/> </output> </xsl:template> <!-- Throw the @name away. --> <xsl:template match="foo/@name"/> <!-- Change the name of the element regarding @name. --> <xsl:template match="foo"> <xsl:variable name="qn" select="resolve-QName(@name, .)"/> <xsl:element name="{ $qn }" namespace="{ namespace-uri-from-QName($qn) }"> <xsl:apply-templates select="@*|node()"/> </xsl:element> </xsl:template> <!-- Same as <xsl:copy-of select="$context/namespace::*"/>, but without using the deprecated namespace:: axis. --> <xsl:function name="fg:copy-namespaces"> <xsl:param name="context" as="element()"/> <xsl:for-each select="in-scope-prefixes($context)"> <xsl:namespace name="{ . }" select=" namespace-uri-for-prefix(., $context)"/> </xsl:for-each> </xsl:function> </xsl:stylesheet> Regards, --drkm
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] Namespace de-duplication , Michael Kay | Thread | Re: [xsl] Namespace de-duplication , Florent Georges |
RE: [xsl] Namespace de-duplication , Michael Kay | Date | Re: [xsl] Namespace de-duplication , Florent Georges |
Month |