RE: Matching namespaces on source documents

Subject: RE: Matching namespaces on source documents
From: "Richman, Jeremy" <jrichman@xxxxxxxxxxxx>
Date: Tue, 9 Nov 1999 12:29:44 -0500
Thanks Mike Brown and Michael Kay, those are very comprehensive
explanations.

The stylesheet I was trying to create precluded putting the namespace
declaration into the stylesheet element, because my transformation was
from an old version of an XSL stylesheet to a new one.  The 'source
document'
declared the xsl prefix in its document element (xsl:stylesheet) and
gave it a different namespace than my transformation sheet did.

For example, one of the required changes was to change the old xsl:number
attribute
level="multi" to level="multiple".

The sample case for this is:

Source document stylesheet (needs to be transformed to newer version):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl";>
  <xsl:template match="Section">
    <xsl:number count="Chapter|Section" level="multi" format="1.1"/>
  </xsl:template>
</xsl:stylesheet>

transformation stylesheet:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
<xsl:output method="xml" xml-declaration="yes" encoding="UTF-8"
indent="yes"/>

<!-- Convert @level=multi to @level=multiple -->
<xsl:template match="@level[local-name(..)='number' and
                        .='multi' and
                        namespace-uri(..)='http://www.w3.org/TR/WD-xsl']">
   <xsl:attribute name="level">multiple</xsl:attribute>
</xsl:template>
</xsl:stylesheet>

This works with LotusXSL, but XT gives the following error:
file:in.xsl:1: no such prefix "xmlns".

I'm not sure whether this is a problem with XT or whether it is
being correctly rigorous where LotusXSL is not.

Note: of course my example is deliberately simplified and does not create
the correct xsl:stylesheet element on the output, nor copy the rest of the
source documents.  The basic templates I used for those tasks are:

<!-- ************************************************************ -->
<!-- *         Rule for stylesheet element                        -->
<!-- *           High priority to assure this rule is used        -->
<!-- ************************************************************ -->

<xsl:template match="/*" priority="10">
   <xsl:text>&#xA;</xsl:text>
   <xsl:element name="xsl:stylesheet">
      <xsl:attribute
name="xmlns:xsl">http://www.w3.org/1999/XSL/Transform</xsl:attribute>
      <xsl:apply-templates select="node()"/>
   </xsl:element>
</xsl:template>

<!-- ************************************************************ -->
<!-- *   DEFAULT COPY RULES FOR elements, attributes, comments,   -->
<!-- *      processing-instructions and text                      -->
<!-- *   These all have low priority to ensure they are picked    -->
<!-- *      as a last resort.                                     -->
<!-- *                                                            -->
<!-- *   The default rules for xsl: and fo: elements have         -->
<!-- *     a higher priority than the other fall-back default.    -->
<!-- ************************************************************ -->

<!-- Default copy for attributes, with a low priority -->
<xsl:template match="@*" priority="-1">
   <xsl:copy/>
</xsl:template>

<!-- Default copy for fo attributes, with a slightly higher priority -->
<xsl:template match="@*[namespace-uri(..)='http://www.w3.org/TR/WD-xsl/FO']"
priority="-0.9">
   <xsl:attribute name="{local-name(.)}">
      <xsl:call-template name="inches-to-in">
         <xsl:with-param name="content"><xsl:value-of
select="."/></xsl:with-param>
      </xsl:call-template>
   </xsl:attribute>
</xsl:template>

<!-- Default copy rules for fo:elements; low priority -->
<xsl:template match="*[namespace-uri(.)='http://www.w3.org/TR/WD-xsl/FO']"
priority="-1">
   <xsl:element name="fo:{local-name(.)}"
      ><xsl:apply-templates select="@*|node()"
   /></xsl:element>
</xsl:template>

<!-- Default copy rules for xsl:elements; low priority -->
<xsl:template match="*[namespace-uri(.)='http://www.w3.org/TR/WD-xsl']"
priority="-1">
   <xsl:element name="xsl:{local-name(.)}"
      ><xsl:apply-templates select="@*|node()"
   /></xsl:element>
</xsl:template>

<!-- Default copy rules for all other elements; lowest priority -->
<xsl:template match="*" priority="-2">
   <xsl:element name="{local-name(.)}"
      ><xsl:apply-templates select="@*|node()"
   /></xsl:element>
</xsl:template>

<!-- Default copy rule for comments, processing instructions and text -->
<xsl:template match="comment()|processing-instruction()|text()"
priority="-1">
   <xsl:copy>
      <xsl:apply-templates select="node()"/>
   </xsl:copy>
</xsl:template>

Jeremy

Mike Brown wrote:
To expand on Michael Kay's explanation...

> <xsl:template match="test:foo">

This says "this template matches elements with the local name
'foo' that have associated with them a namespace URI that has
been assigned to the 'test' prefix in this stylesheet" ... 
it does *not* say "this template matches elements designated
'test:foo' in the source document".

It's kind of confusing because you do have access to the
'test' prefix from the source document, but not in this way.

You're matching the namespace URI that 'foo' is assigned to,
not 'foo'. It might help if you consider what happens when
you don't use prefixes:

  <?xml version="1.0"?>
  <document>
     <foo xmlns="http://www.test.org";>hello world</foo>
  <document>

How would you make a template match this foo? match="foo"
wouldn't work because the namespace URI is not null.
match="foo[namespace-uri(.)='http://www.test.org']" would
probably work, but is inconvenient. So, you can declare
a prefix-to-namespace-URI assignment in your stylesheet:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
  xmlns:mytest="http://www.test.org";>

and then use <xsl template match="mytest:foo">. The URIs have
to match between the stylesheet and source document. Whether
the prefixes do or don't is irrelevant.

One of the consequences of this is that there's apparently
no way of knowing whether the prefix assignment was done in
the stylesheet to aid in processing or if you're intending
to have the assignment appear in the result tree. Your
XSL processor might be inclined to put the assignment in the
output, even if the prefix is not used in the result tree.
The result tree would probably have to be reparsed after it
is built in order to determine whether the prefix is
actually needed. Then you're still left wondering what to do
if you wanted the prefix to be declared anyway...

Someone else may want to comment/correct me on this. I know
it has come up before.

- -Mike


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


Current Thread