Re: [xsl] namespace xmlns="http://www.w3.org/1999/xhtml"

Subject: Re: [xsl] namespace xmlns="http://www.w3.org/1999/xhtml"
From: "James A. Robinson" <jim.robinson@xxxxxxxxxxxx>
Date: Sun, 14 Jan 2007 00:28:58 -0800
>   I have been reading the FAQ entry:
> [XHTL to fo, namespace problems.]
> http://www.dpawson.co.uk/xsl/sect2/N5536.html#d6784e1669
>   I thought this would work for me, but I can't get any output using
> (1). My xml is the following:

You haven't told us what output you want, so I'm going to go with
the assumption that the use of that FAQ question indicates you want to
extract elements and have them tagged with a default namespace.

> <html xmlns="http://www.w3.org/1999/xhtml";>
> <head>...</head>
> <body>...</body>
> </html>

So this is XML tagged with an XHTML namespace, they values are unprefixed,
but the root contains an xmlns attribute, meaning untagged elements are
in the specified namespace (http://www.w3.org/1999/xhtml).

I know that's probably an obvious statement, but it's an important one
to remember, and here is why: XSLT needs to know what namespace you are
interested in.

> <?xml version="1.0" encoding="UTF-8"?>
> <xsl:stylesheet version="1.0"
>                 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>                 xmlns="http://www.w3.org/1999/xhtml";>
> <xsl:template match="/">
>     <xsl:for-each select="html/body">
>       <xsl:value-of select="."/>
>     </xsl:for-each>
> </xsl:template>
> </xsl:stylesheet>

This is where the above warning re namespaces comes in.  Your stylesheet
says to copy the textual value of the descendent html/body element in
the *null* namespace. The declaration of the xmlns default namespace you
set in  your xsl:stylesheet element has zero impact on what the XPath
selection 'html/body" is targeting.

The null namespace isn't what you want, you want the extract the html/body
descendent in the xhtml namespace.  I'm also assuming you want xsl:copy-of
instead of xsl:value-of.  The former will copy an element wholesale,
the latter creates a text node.

If my guess about what you want for output is correct, perhaps something
like this will work better:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="1.0"
  xmlns:xhtml="http://www.w3.org/1999/xhtml";>
  <xsl:template match="/">
    <xsl:copy-of select="xhtml:html/xhtml:body"/>
  </xsl:template>
</xsl:stylesheet>

which for me, using an XSLT 1.0 processor, emits

<?xml version="1.0" encoding="utf-8"?>
<body xmlns="http://www.w3.org/1999/xhtml";>...</body>

Now, if you were using XSLT 2.0 you could use a nice feature which
allows you to set the default namespace used in XPath selections
by using an xpath-default-namespace attribute:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="2.0"
  xpath-default-namespace="http://www.w3.org/1999/xhtml";>
  <xsl:template match="/">
    <xsl:copy-of select="html/body"/>
  </xsl:template>
</xsl:stylesheet>

If you start adding multiple namespaces into the mix you will also need
to read up on the exclude-result-prefixes attribute, as that can also get
in your way when generating some XML documents which are DTD oriented (and
which therefore often cause problems for XML using namespace prefixes)

Jim

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
James A. Robinson                       jim.robinson@xxxxxxxxxxxx
Stanford University HighWire Press      http://highwire.stanford.edu/
+1 650 7237294 (Work)                   +1 650 7259335 (Fax)

Current Thread