After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 302020 - Duplicate attributes again & namespace errors (?) new in 1.1.12
Duplicate attributes again & namespace errors (?) new in 1.1.12
Status: RESOLVED FIXED
Product: libxslt
Classification: Platform
Component: general
1.1.12
Other Linux
: Normal normal
: ---
Assigned To: kbuchcik
libxml QA maintainers
Depends on:
Blocks:
 
 
Reported: 2005-04-26 10:01 UTC by Thomas Blatter
Modified: 2006-05-19 10:09 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Thomas Blatter 2005-04-26 10:01:51 UTC
Distribution/Version: current debian sarge

Testcase:
xsl:
<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
  xmlns:test="http://example.com/xmlns/test">
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template name="copyWhatever" priority="0.6" match="text()|node()|@*">
  <xsl:copy>
    <xsl:apply-templates select="text()|node()|@*" />
  </xsl:copy>
</xsl:template>
<xsl:template match="/" priority="1">
  <xsl:apply-templates select="node()|text()|@*" />
</xsl:template>
<xsl:template match="@label" priority="1">
  <xsl:attribute name="{name()}" namespace="{namespace-uri()}">
    <xsl:value-of select="." />
  </xsl:attribute>
</xsl:template>
<xsl:template match="test:test[parent::test:use]" priority="1">
  <xsl:copy>
    <xsl:apply-templates
select="/test:root/test:def/test:test[@name=current()/@name]/@*" />
    <xsl:apply-templates select="@*" />
    <xsl:apply-templates select="text()|node()" />
  </xsl:copy>
</xsl:template>
</xsl:stylesheet>
xml:
<?xml version="1.0"?>
<root
  xmlns="http://example.com/xmlns/test"
  xmlns:test="http://example.com/xmlns/test"
  >
  <def>
    <test name="foo" label="bleh" def="new" />
  </def>
  <use>
    <test name="foo" label="foo" other="bar"/>
  </use>
</root>
output in 1.1.12:
<?xml version="1.0"?>
<root xmlns="http://example.com/xmlns/test"
xmlns:test="http://example.com/xmlns/test">
  <def>
    <test xmlns="" name="foo" label="bleh" def="new"/>
  </def>
  <use>
    <test xmlns="" name="foo" label="bleh" def="new" label="foo" other="bar"/>
  </use>
</root>

xsltproc was compiled against libxml 20603, libxslt 10102 and libexslt 802:
This version did not produce the duplicate attributes and the in my opinion
wrong xmlns=""

xsltproc was compiled against libxml 20616, libxslt 10112 and libexslt 810
This version produces above output. Removing the redundant namespace=..
attribute on xsl:attribute fixes the problem.
Comment 1 Thomas Blatter 2005-04-27 08:08:57 UTC
Checked now as well the most recent 1.1.14 binaries for windows:

Using libxml 20619CVS2407, libxslt 10114CVS1011 and libexslt 812CVS1011

They produce the same result.
Comment 2 Thomas Blatter 2005-05-04 13:36:19 UTC
Added test from the web, with an additional bug appearing in both xsltproc
1.1.12 debian sarge and 1.1.14 windows. This second bug is not respecting
"Adding an attribute to an element replaces any existing attribute of that
element with the same expanded-name." of the xsl specification.
Testcase from the web:

xsltproc http://bebabo.homelinux.org/test/xsltproc_bug/test.xsl
http://bebabo.homelinux.org/test/xsltproc_bug/test.xml
Comment 3 kbuchcik 2006-05-15 18:42:45 UTC
True, the result is wrong.
I tried with the current CVS HEAD (> 1.1.16): this produces the same
result.
Comment 4 kbuchcik 2006-05-15 19:09:56 UTC
The bug producing the incorrect namespace "undeclaration" (xmlns="") is
in:
xsltAttributeInternal() (attributes.c)
 --> namespace = xsltEvalAttrValueTemplate(ctxt, inst,
      (const xmlChar *) "namespace", XSLT_NAMESPACE);
  
  xsltEvalAttrValueTemplate() returns here the empty string for the
    expression "{namespace-uri()}"

  Unfortunately the next code-line does not check for the
  empty string, but just for NULL:

  if (namespace != NULL) {
    ns = xsltGetSpecialNamespace(ctxt, inst, namespace, prefix,
      ctxt->insert);

  Thus xsltGetSpecialNamespace() undeclares the current default namespace.

     
  
Comment 5 kbuchcik 2006-05-15 20:11:09 UTC
The second bug, producing the duplicate @same via xsl:attribute,
is also located in xsltAttributeInternal() (attributes.c).

xsltAttributeInternal():

  Calls with an empty string:
  --> xsltGetSpecialNamespace():

  Here the default namespace is queried, which returns previously
  declared xmlns="" (see comment above).

  if ((prefix == NULL) && (URI[0] == 0)) { 
    ret = xmlSearchNs(out->doc, out, NULL);

    Now the code tries to undeclare the default namespace, which
    results in an error: xmlNewNs() will return NULL, since there is
    already a xmlns="" on the same element node.

    if (ret != NULL) {
      ret = xmlNewNs(out, URI, prefix);
      return(ret);

    NULL is returned and assigned to the newly created @same.

    At the end we get:
    <test xmlns="" name="foo" label="bleh" def="new" label="foo" other="bar"/>
    With the first @label being internally incorrectly bound to
    xmlns="" and the second @label being in no namespace; that's why
    it looks like the first @label wasn't overwritten.

This means xsltGetSpecialNamespace() is not able yet to handle namespace
declaration clashes. I think it should generate an error message if
it cannot create the desired ns-declaration.

Fixing the issue in the comment above, also heals this behaviour; but the
extra error message (if xmlNewNs() returns NULL) will be also added.

    
Comment 6 kbuchcik 2006-05-15 20:25:09 UTC
I wonder if xsltGetSpecialNamespace() should ever return an
xmlNs struct representing an xmlns="" at all. 
TODO: Check if this produces problems in other scenarios.
Comment 7 kbuchcik 2006-05-15 20:28:45 UTC
A reduced scenario for this:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:foo="urn:test:foo">
  <xsl:output indent="yes"/>  

  <xsl:template match="text()|node()|@*" priority="0.6">
    <xsl:copy>
      <xsl:apply-templates select="text()|node()|@*"/>
    </xsl:copy>
  </xsl:template>  

  <xsl:template match="@same" priority="1">    
    <xsl:attribute name="{name()}"
      namespace="{namespace-uri()}">generated</xsl:attribute>
  </xsl:template>

  <xsl:template match="foo:zoo" priority="1">    
    <xsl:copy>
      <xsl:apply-templates select="/foo:foo/foo:bar/@*"/>
      <xsl:apply-templates select="@*"/>
      <xsl:apply-templates select="text()|node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

<?xml version="1.0"?>
<foo xmlns="urn:test:foo" xmlns:test="urn:test:foo">
  <bar same="new" same-2="new"/>
  <zoo same="orig" same-2="orig" other="orig"/>
</foo>

The result:

<?xml version="1.0"?>
<foo xmlns="urn:test:foo" xmlns:test="urn:test:foo">
  <bar same="generated" same-2="new"/>
  <zoo same="generated" same-2="orig" other="orig"/>
</foo>

Comment 8 kbuchcik 2006-05-15 20:36:33 UTC
Fixed now in CVS, libxslt/attributes.c, revision 1.44 and
libxslt/namespaces.c 1.28.

Thanks for the report!

TODO: Add the reduced scenario to the regression tests.