Illustrations re: Namespace node processing (long)

Subject: Illustrations re: Namespace node processing (long)
From: "G. Ken Holman" <gkholman@xxxxxxxxxxxxxxxxxxxx>
Date: Wed, 08 Mar 2000 20:32:15 -0800
(please be careful if responding to this note to *not* copy the entire contents into your reply unnecessarily ... thanks!)

Looking back over the messages today about the confusion of namespace declarations, I decided to look at all aspects of the situation instead of just embedded documentation as I had earlier.

According to the XSLT 1.0 Recommendation,

  "The designation of a namespace as an excluded namespace is
   effective within the subtree of the stylesheet rooted at the
   element bearing the exclude-result-prefixes or
   xsl:exclude-result-prefixes attribute"

.... which is to say that the attribute has *no* relation to the namespaces used in the source node tree.

So, my book correctly addresses the issue about having namespaces in the *stylesheet* ... yet the confusion today was about namespaces in the source.

I've written the following to illustrate through separate short examples what may have been going on with the appearance of namespace declarations in the result that possibly caused confusion.

First, here are the sources of all of the files I'm using down below:

(1) - an XML source file without namespaces

T:\ftemp>type test.xml
<?xml version="1.0"?>
<doc>
  <para>First para</para>
  <para>Second para</para>
</doc>

(2) - an XML source file with namespaces

T:\ftemp>type testns.xml
<?xml version="1.0"?>
<doc xmlns:ken="ken.com">
  <para>First para</para>
  <para>Second para</para>
</doc>

(3) - an XSLT stylesheet without namespaces

T:\ftemp>type test.xsl
<?xml version="1.0"?><!--filename.xsl-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                version="1.0">
<xsl:output method="xml"/>

<xsl:template match="/">                         <!--root rule-->
 <result>
  <xsl:copy-of select="/doc/para"/>
 </result>
</xsl:template>

</xsl:stylesheet>

(4) - an XSLT stylesheet with a documentation namespace

T:\ftemp>type testns.xsl
<?xml version="1.0"?><!--filename.xsl-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                version="1.0" xmlns:ken="ken.com">
<xsl:output method="xml"/>

<ken:hello>test</ken:hello>

<xsl:template match="/">                         <!--root rule-->
 <result>
  <xsl:copy-of select="/doc/para"/>
 </result>
</xsl:template>

</xsl:stylesheet>

(5) - an XSLT stylesheet with an exclude on a literal result element

T:\ftemp>type testnsex.xsl
<?xml version="1.0"?><!--filename.xsl-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                version="1.0" xmlns:ken="ken.com">
<xsl:output method="xml"/>

<ken:hello>test</ken:hello>

<xsl:template match="/">                         <!--root rule-->
 <result xsl:exclude-result-prefixes="ken">
  <xsl:copy-of select="/doc/para"/>
 </result>
</xsl:template>

</xsl:stylesheet>

(6) - an XSLT stylesheet with an exclude on the document element of the stylesheet

T:\ftemp>type testnsde.xsl
<?xml version="1.0"?><!--filename.xsl-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                version="1.0" xmlns:ken="ken.com"
                exclude-result-prefixes="ken">
<xsl:output method="xml"/>

<ken:hello>test</ken:hello>

<xsl:template match="/">                         <!--root rule-->
 <result>
  <xsl:copy-of select="/doc/para"/>
 </result>
</xsl:template>

</xsl:stylesheet>

(7) - an XSLT stylesheet with an exclude on the document element of the stylesheet and using template rules instead of copy-of:

T:\ftemp>type testnstr.xsl
<?xml version="1.0"?><!--filename.xsl-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                version="1.0" xmlns:ken="ken.com"
                exclude-result-prefixes="ken">
<xsl:output method="xml"/>

<ken:hello>test</ken:hello>

<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>

</xsl:stylesheet>

(8) - an XSLT stylesheet using template rules without any exclude-result-prefixes=

<?xml version="1.0"?><!--filename.xsl-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                version="1.0">
<xsl:output method="xml"/>

<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>

</xsl:stylesheet>

=============8<----------------------

(T1) - Okay, so first no namespaces to show the desired result:

T:\ftemp>xt test.xml test.xsl
<?xml version="1.0" encoding="utf-8"?>
<result><para>First para</para><para>Second para</para></result>

(T2) - Introducing the documentation namespace without an exclude produces a result:

T:\ftemp>xt test.xml testns.xsl
<?xml version="1.0" encoding="utf-8"?>
<result xmlns:ken="ken.com"><para>First para</para><para>Second para</para></result>


.... where the processor emits a contingent declaration *just in case*.

(T3) - Using an exclude-result-prefixes= on the stylesheet document element filters it out (this is as far as I have gone in my book to date, focusing on the use of namespaces in embedded documentation):

T:\ftemp>xt test.xml testnsde.xsl
<?xml version="1.0" encoding="utf-8"?>
<result><para>First para</para><para>Second para</para></result>

(T4) - Using an exclude-result-prefixex= on the literal result element isn't recognized for XT (an http://www.jclark.com/xml/xt.html documented limitation, so we shouldn't be expecting it, but that might be the source of some confusion), but does for Saxon:

T:\ftemp>xt test.xml testnsex.xsl
<?xml version="1.0" encoding="utf-8"?>
<result xmlns:ken="ken.com"><para>First para</para><para>Second para</para></result>
T:\ftemp>saxon test.xml testnsex.xsl
<?xml version="1.0" encoding="utf-8" ?><result><para>First para</para><para>Second para</para></result>


(T5) - Now, the source file with the namespace declaration on the document element is processed with both types of exclude-result-prefixes= and while the document element of the result doesn't have the namespace declaration, the descendants do:

T:\ftemp>saxon testns.xml testnsex.xsl
<?xml version="1.0" encoding="utf-8" ?><result><para xmlns:ken="ken.com">First para</para><para xmlns:ken="ken.com">Second para</para></result>
T:\ftemp>xt testns.xml testnsde.xsl
<?xml version="1.0" encoding="utf-8"?>
<result><para xmlns:ken="ken.com">First para</para><para xmlns:ken="ken.com">Second para</para></result>
T:\ftemp>saxon testns.xml testnsde.xsl
<?xml version="1.0" encoding="utf-8" ?><result><para xmlns:ken="ken.com">First para</para><para xmlns:ken="ken.com">Second para</para></result>


At first one might not expect the above behaviour in Test5 ... if none of my result tree descendents utilize the namespace, then why would each one get a namespace declaration? It has nothing to do with the exclude-result-prefixes= because the scope of that attribute is in the stylesheet.

It is because of the use of <xsl:copy-of> and the first sentence of section 5.4 of the XPath 1.0 Recommendation:

   "Each element has an associated set of namespace
    nodes, one for each distinct namespace prefix that
    is in scope for the element"

Thus, the <para> elements of the source node tree each have an invisible namespace node for the "ken" namespace that we cannot see.

Because I used <xsl:copy-of>, I copied *all* of the nodes of the source tree (including the invisible namespace nodes) to the result tree ... hence, the processor is obliged to put out the namespace declaration for the namespace nodes found in the result tree.

(T6) - So, to avoid using <xsl:copy-of> I then used the stylesheet that uses template rules instead:

T:\ftemp>xt testns.xml testnstr.xsl
<?xml version="1.0" encoding="utf-8"?>
<result><para>First para</para><para>Second para</para></result>

.... and sure enough, since my stylesheet isn't adding any namespace nodes to the result tree, there are no namespace declarations in the result.

(T7) - The last test looks at *not* using exclude-result-prefixes= but still having namespaces in the source to illustrate there was never any need for exclude-result-prefixes= to handle source issues:

T:\ftemp>xt testns.xml testtr.xsl
<?xml version="1.0" encoding="utf-8"?>
<result><para>First para</para><para>Second para</para></result>

... and note that since I didn't copy any of the invisible (or visible) namespace nodes, the end result doesn't need any namespace declarations.



There is the evidence supporting the Recommendations ... and it seems the processors here obey the rules where they are documented to obey the rules. Perhaps the key that was missing was the knowledge of the hidden namespace nodes implied by the scope of ancestral namespace declarations.

I will put all of the above into the next edition of our book, with some of the sentences fleshed out and perhaps rearranged as I think about the best way to present it. I don't think I've missed any of the combinations or the explanations ... if something still isn't said about namespace processing, please post your question.

I hope this helps.

................ Ken

--
G. Ken Holman                    mailto:gkholman@xxxxxxxxxxxxxxxxxxxx
Crane Softwrights Ltd.             http://www.CraneSoftwrights.com/s/
Box 266, Kars, Ontario CANADA K0A-2E0   +1(613)489-0999   (Fax:-0995)
Web site: XSL/XML/DSSSL/SGML services, training, libraries, products.
Practical Transformation Using XSLT and XPath      ISBN 1-894049-04-7
Next instructor-led training:    2000-05-02,2000-05-11/12,2000-05-15,
-                                    2000-06-12,2000-06-13,2001-01-27


XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list



Current Thread