GNOME Bugzilla – Bug 132953
xsltproc: <xsl:attribute> fails with message 'node already has children'
Last modified: 2009-08-15 18:40:50 UTC
I'm using an XSLT-script to copy elements from one namespace into another. I.e., if I have two namespaces a and b, I want all occurences of a:foo to be transformed to b:foo. While doing so, xsltproc drops the attribute, and outputs an error message: 'node already has children'. I've reduced my stylesheet/source (test.xsl) document to make it easier to verify the bug. The stylesheet has to templates: the first is intended to rename all attributes from namespace o-config: to config:, and the second should copy all other content. The test file (test.xml) contains one such attribute. Note that the problem will NOT occur if the element in case does not contain any content (i.e., written as <config:config-item-set .../>). However, I do not see how this would make a difference to the XSLT. To the best of my knowledge, the XSLT is valid. If you need any more info, feel free to contact me. I'd be happy to help. :-) Please find below: 1) the content of test.xsl 2) the content of test.xml 3) the result of 'xsltproc test.xsl test.xml' 4) the result of 'xsltproc --version' > type test.xsl <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:o-config="http://openoffice.org/2001/config" xmlns:config="urn:oasis:names:tc:openoffice:xmlns:config:1.0" > <xsl:output method="xml"/> <xsl:template match="@o-config:*"> <xsl:attribute name="config:{local-name(.)}"> <xsl:value-of select="."/> </xsl:attribute> </xsl:template> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet> > type test.xml <?xml version="1.0" encoding="UTF-8"?> <office:document xmlns:office="http://openoffice.org/2000/office" xmlns:config="http://openoffice.org/2001/config"> <config:config-item-set config:name="view-settings"> </config:config-item-set> </office:document> > xsltproc test.xsl test.xml runtime error: file test.xsl line 13 element attribute xsl:attribute : node already has children <?xml version="1.0"?> <office:document xmlns:office="http://openoffice.org/2000/office" xmlns:config=" http://openoffice.org/2001/config"> <config:config-item-set> </config:config-item-set> </office:document> > xsltproc --version Using libxml 20424, libxslt 10020 and libexslt 711 xsltproc was compiled against libxml 20424, libxslt 10020 and libexslt 711 libxslt 10020 was compiled against libxml 20424 libexslt 711 was compiled against libxml 20424
The problem goes away with a newer version. However, the script still doesn't work... With the current version of xsltproc, the script does not cause any error messages, however, the attribute does not change the namespace wither. It appears it now does not apply the template at all. :-( In the result below, note that the result is an exact copy of the input; the namespace on the attribute has not been changed! >xsltproc --version Using libxml 20604, libxslt 10102 and libexslt 802 xsltproc was compiled against libxml 20604, libxslt 10102 and libexslt 802 libxslt 10102 was compiled against libxml 20604 libexslt 802 was compiled against libxml 20604 >xsltproc test.xsl test.xml <?xml version="1.0"?> <office:document xmlns:office="http://openoffice.org/2000/office" xmlns:config=" http://openoffice.org/2001/config"> <config:config-item-set config:name="view-settings"> </config:config-item-set> </office:document>
You were hitting the following error: http://www.w3.org/TR/xslt#creating-attributes "Adding an attribute to an element after children have been added to it; implementations may either signal the error or ignore the attribute." It seems it was a problem with the order in which attributes and element are processed. Running with xsltproc -v and looking at the log on stderr should help diagnose what's actually happening. It looks like a real bug but would need further checking, Daniel
Daniel, thanks for your quick response. I did check the bug list, but didn't recognize the problem. Anyway, since the original problem does not occur in the current version, I suspect we no longer need to look at it? (If you are still interested in the bug, I will re-install the older version and supply you with a log as well.) The output of 'xsltproc -v' with the current version is appended below. It seems to do the right thing, except the result is not correct. An excerpt: [...] Added namespace: config mapped to urn:oasis:names:tc:openoffice:xmlns:config:1.0 [...] xsltProcessOneNode: applying template '@o-config:*' for attribute name [...] xsltEvalAttrValueTemplate: config:{local-name(.)} returns config:name So, it appears that: 1) it correctly got the config: namespace 2) it applied the correct template, and 3) if correctly assembled the attribute name. The output is indeed config:name, but for a different config: namespace! > xsltproc -v text.xsl text.xml Added namespace: xsl mapped to http://www.w3.org/1999/XSL/Transform Added namespace: o-config mapped to http://openoffice.org/2001/config Added namespace: config mapped to urn:oasis:names:tc:openoffice:xmlns:config:1.0 xsltPrecomputeStylesheet: removing ignorable blank node xsltParseStylesheetProcess : found stylesheet template has 2 inherited namespaces xsltCompilePattern : parsing '@o-config:*' xsltCompilePattern : parsed @o-config:*, default priority -0.250000 added pattern : '@o-config:*' priority -0.250000 template has 2 inherited namespaces xsltCompilePattern : parsing '@*' xsltCompilePattern : parsed @*, default priority -0.500000 xsltCompilePattern : parsing 'node()' xsltCompilePattern : parsed node(), default priority -0.500000 added pattern : '@*' priority -0.500000 added pattern : 'node()' priority -0.500000 parsed 2 templates Resolving attribute sets references Registered 0 modules Registering global variables Registering global variables from text.xsl xsltProcessOneNode: no template found for / xsltProcessOneNode: applying template '@*|node()' for document xsltCopy: node document xsltApplyTemplates: node: document xsltApplyTemplates: select @*|node() xsltApplyTemplates: list of 3 nodes xsltProcessOneNode: applying template '@*|node()' for text xsltCopy: text xsltCopyText: copy text xsltProcessOneNode: applying template '@*|node()' for config-item-set xsltCopy: node config-item-set xsltApplyTemplates: node: config-item-set xsltApplyTemplates: select @*|node() xsltApplyTemplates: list of 2 nodes xsltProcessOneNode: applying template '@o-config:*' for attribute name xsltEvalXPathString: returns name xsltEvalAttrValueTemplate: config:{local-name(.)} returns config:name xsltValueOf: select . xsltCopyTextString: copy text view-settings xsltValueOf: result view-settings xsltProcessOneNode: applying template '@*|node()' for text xsltCopy: text xsltCopyText: copy text xsltProcessOneNode: applying template '@*|node()' for text xsltCopy: text xsltCopyText: copy text <?xml version="1.0"?> <office:document xmlns:office="http://openoffice.org/2000/office" xmlns:config=" http://openoffice.org/2001/config"> <config:config-item-set config:name="view-settings"> </config:config-item-set> </office:document>
I really don't understand why the namespaces from the stylesheet: xmlns:o-config="http://openoffice.org/2001/config" xmlns:config="urn:oasis:names:tc:openoffice:xmlns:config:1.0" are not propagated as is to the result, that's a bug for sure and maybe the reason of the second problem on the attribute namespace. This is weird...and really looks like a bug, I will try to look over this during the week-end unless William beats me at it :-) Daniel
fixed in CVS (libxslt/namespaces.c). Thanks for the report.
This should be closed by release of libxslt-1.1.5, thanks, Daniel