xsl-list
[Top] [All Lists]

RE: Saxon fails to exclude result prefixes?

2003-10-27 17:04:54
Basically, what happens when you have two namespace declarations for the
same namespace URI is (a) your request to exclude a result prefix is
actually a request to exclude all namespace nodes for that namespace
URI; (b) the serializer (according to the XSLT 1.0 spec) is allowed to
add extra namespace nodes, and is required to add them where the
namespace URI is actually used. One would like the serializer to add the
minimum set of necessary namespace nodes at this stage, but Saxon is
using the rule that if the namespace URI is used in the result, then it
adds back all the namespace nodes for that URI, regardless of prefix.
This is inelegant, but not non-conformant. The serializer is actually
allowed to output any namespace declarations it chooses.

Michael Kay


-----Original Message-----
From: owner-xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com 
[mailto:owner-xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com] On Behalf Of 
Lars Huttar
Sent: 27 October 2003 17:51
To: XSL-List (E-mail)
Subject: [xsl] Saxon fails to exclude result prefixes?


Hi all,
Maybe I'm missing something, but it sure seems like Saxon
isn't doing what it's supposed to in this case.
I'm using Saxon652. (But I have just now upgraded to 6.5.3
and found the same behavior.)
Can anybody confirm if this is a bug?

The situation:

I have a stylesheet that does an identity
transform for the most part, but discards some elements
and adds others. All elements in the input and the output
are in the namespace whose URI is "http://www.sil.org/namespace/gem";.

In the input, the outermost element, <system-model>,
has a namespace pseudo-attribute on it:

  <system-model xmlns="http://www.sil.org/namespace/gem";>

and no prefixes or other namespace declarations are used.
I would like the output to be the same way.

The problem:

The nodes that are copied via <xsl:copy> appear the same in 
the output as they do in the input, i.e. none of them have 
namespace declarations except the outermost. However, the 
nodes I create as literal result elements have a superfluous 
namespace declaration, e.g.

     <access xmlns:gem="http://www.sil.org/namespace/gem";
              role="guest" update="no" read="yes"/>

This happens even though (and whether or not) I put
   xsl:exclude-result-prefixes="gem"
on the literal result element <access>.
My reading of the spec leads me to believe that putting
   xsl:exclude-result-prefixes="gem"
here, or
   exclude-result-prefixes="gem"
on the <xsl:stylesheet> element, should prevent unnecessary 
declarations of the "gem" prefix in the output. (I have tried both.)

When I try this stylesheet with this input in Xalan or MSXSL,
I get what I wanted: <access> with no "gem" prefix declaration.

Is this indeed a bug in Saxon?
I checked the list of changes 6.5.2 - 6.5.3, the
list of known limitations of 6.5.3, and the Saxon bug tracker 
pages on Sourceforge, and didn't see this mentioned as a bug.


If this is not a bug and I'm just misunderstanding what 
(xsl:)exclude-result-prefixes is supposed to do, I would 
appreciate correction.


The files in question will be available at
  http://www.huttar.net/lars-kathy/test/Ethnologue.xml: the 
input document;
   .../role-extractor.xsl: the stylesheet;
   .../system-model.dtd: DTD for the input document;
   .../msxslout.xml: the output when processed by msxml;
   .../saxonout.xml: the output when processed by Saxon 653;

but at the moment I can't get the server to let me upload them.

So here's the stylesheet:

<?xml version="1.0" encoding="UTF-8"?>

<!-- role-extractor.xsl

  Input: a system model conforming to system-model.dtd
  Parameter: a role (e.g. 'guest' or 'admin')

  Output: the system model, filtered to include only items 
accessible to the given role.
  -->

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

  <xsl:param name="role" select="'admin'" />

  <!-- global variables -->
  <xsl:variable name="role-node" 
select="/*/gem:columnFour/gem:roles/*[(_at_)id = $role]
        | /*/gem:columnFour/gem:roles/gem:admin[$role = 'admin']" />
  <xsl:variable name="default-read">
    <xsl:choose>
      <xsl:when test="$role-node/@read = 'all'">yes</xsl:when>
      <xsl:otherwise>no</xsl:otherwise>
    </xsl:choose>
  </xsl:variable>
  <xsl:variable name="default-update">
    <xsl:choose>
      <xsl:when test="$role-node/@update = 'all'">yes</xsl:when>
      <xsl:otherwise>no</xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

  <!-- Top-level template -->
  <xsl:template match="/">
    <xsl:if test="not($role-node)">
      <xsl:message terminate="yes">Role "<xsl:value-of 
select="$role" />" unknown.</xsl:message>
    </xsl:if>
    <xsl:copy>
      <xsl:apply-templates select="node()"/>
    </xsl:copy>
  </xsl:template>

  <!-- Discard <attribute>s that the given role doesn't have 
access to. Modify others. -->
  <xsl:template match="gem:attribute">
    <xsl:choose>
      <!-- Discard <attribute>s that the given role 
explicitly has no access to. -->
      <xsl:when test="gem:access[(_at_)role = $role and @read = 'no']" />
      <!-- Discard <attribute>s that the given role doesn't 
have access to by default. -->
      <xsl:when test="$default-read = 'no' and 
not(gem:access[(_at_)role = $role and @read = 'yes'])" />

      <!-- The given role has read access to this attribute, 
so process the attribute. -->
      <xsl:otherwise>
        <xsl:copy>
          <!-- Copy everything except <access> elements -->
          <xsl:apply-templates 
select="@*|node()[not(self::gem:access)]" />
          <!-- create an <access> element only if needed 
(i.e. if this attribute is read-only) -->
          <xsl:if test="($default-update = 'no' and 
not(gem:access[(_at_)role = $role and @update =
'yes'])) or
                             gem:access[(_at_)role = $role and 
@update = 'no']">
           <access xsl:exclude-result-prefixes="gem"
                 role="{$role}" update='no' read='yes' /> 
<!-- @read is redundant but is there to conform to DTD -->
          </xsl:if>
        </xsl:copy>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="gem:roles">
    <!-- Discard all of <roles>' child elements except those 
that are required by the DTD. -->
    <xsl:apply-templates select="gem:guest | gem:admin" />
  </xsl:template>

  <!-- Everything else is preserved as-is. -->
  <!-- identity transform -->  <!-- Problem: namespace needs 
to be preserved too. -->
  <xsl:template match="@*|node()" priority="-1">
    <xsl:copy>
<!-- Debugging:
      <xsl:message>Copying node <xsl:value-of select="name()" 
/> with namespace-URI <xsl:value-of select="namespace-uri()" 
/></xsl:message> -->
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>


And here's an excerpt from the input XML:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE system-model SYSTEM "system-model.dtd">
<system-model xmlns="http://www.sil.org/namespace/gem";>
   <name>Ethnologue</name>
...
   <columnOne>
    <object id="d.ECoun" independent="yes" stage="phase1">
      <name>Ethnologue Country</name>
      <definition>The
  Ethnologue description of a country of the world.</definition>
      <attribute size="35" type="phrase">
        <name>Print_Name</name>
        <definition>LNAM -
  &#34;Print:&#34; format Country Name</definition>
      </attribute>
...
    </object>
   </columnOne>
   <columnFour>
      <roles>
         <guest id="guest" read="all" update="none"/>
         <admin read="all" update="all"/>
      </roles>
   </columnFour>
</system-model>


Expected output: the <attribute> whose <name> is Print_Name 
should have an <access> element that looks like this:

     <access role="guest" update="no" read="yes"/>

but instead I get this with Saxon:

     <access xmlns:gem="http://www.sil.org/namespace/gem";
              role="guest" update="no" read="yes"/>


Thanks,
Lars


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



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



<Prev in Thread] Current Thread [Next in Thread>