RE: [xsl] Node renaming problem

Subject: RE: [xsl] Node renaming problem
From: "Michael Kay" <michael.h.kay@xxxxxxxxxxxx>
Date: Thu, 10 Oct 2002 09:10:00 +0100
>    It's been over a year since I last worked with XSL and am having a 
> difficult time remembering the simplest of things.  In a 
> current project, I 
> want to add a prefix to a particular node tree such that
> <math>
>    <apply>
>      <power/>
>      <ci>x</ci>
>      <cn>2</cn>
>    </apply>
> </math>
> becomes
> <m:math>
>    <m:apply>
>      <m:power/>
>      <m:ci>x</m:ci>
>      <m:cn>2</m:cn>
>    </m:apply>
> </m:math>

Presumably you want the result to be well-formed XML, in which case the
"m" namespace must be declared? If not (and perhaps anyway), your best
bet is to do a global replace using a text editor.
> (The subnodes must carry the prefix because that is how the 
> third-party 
> browser plugin is configured to parse them.)
> I wrote the following named template, but I think I did it the hard 
> way.  Plus my test for text-only nodes is incorrect.
>    <xsl:template name="str:prepend-ns">
>      <xsl:param name="tags" select="."/>
>      <xsl:param name="ns" select="'alt'"/>
>      <xsl:for-each select="$tags">
>        <xsl:choose>
>          <!-- WRONG -->
>          <xsl:when test=".=text()">
>            <xsl:copy-of select=."/>
>          </xsl:when>
>          <xsl:otherwise>
>            <xsl:variable name="tagName" select="concat($ns, ':', 
> local-name(.))"/>
>            <xsl:element name="{$tagName}">

Giving the elements a prefix of "m" is cosmetic. The key question is
what namespace you want the elements in. You haven't bound "m" to any
namespace. The spec says "the QName is expanded into an expanded-name
(ie., a namespace-uri/local-name pair) using the namespace declarations
in effect for the xsl:element element". It doesn't actually say what
happens if the prefix isn't in scope. Interestingly, this omission is
still present in the XSLT 2.0 draft. My interpretation has always been
that it is an error, but your XSLT processor seems to interpret it
differently, or to attempt a recovery action.
> This is the result using MSXSL4.0:
> <m:math xmlns="">
>    <m:apply xmlns="">
>      <m:power xmlns="" />
>      <ci>x</ci>
>      <cn>2</cn>
>    </m:apply>
> </m:math>

This isn't well-formed XML, so I don't think any XSLT processor should
produce this result. Raise a bug report.
> 1) How should I properly check to see if the current node is a text()?

Instead of xsl:for-each and xsl:choose, use template rules.

> 2) How do I avoid the unnecessary xmlns="" attributes?

Use the namespace attribute of xsl:element to say what namespace you
want the result elements to be in. The system has guessed that you want
them in no namespace, which is a reasonable thing to assume, and it has
therefore generated xmlns="" to 

> 3) Am I overcomplicating everything?
The key question is, are you trying to produce namespace-well-formed XML
output, and if so, what namespace do you want it in?

Michael Kay
Software AG
home: Michael.H.Kay@xxxxxxxxxxxx
work: Michael.Kay@xxxxxxxxxxxxxx 

 XSL-List info and archive:

Current Thread