GNOME Bugzilla – Bug 86753
allow multiple identical attribute in the same element
Last modified: 2009-08-15 18:40:50 UTC
I take an xml file with some elements and attributes, and ask a stylesheet to add existing attributes ; the output xml document get thoses attributes twice. ____________________________________ consider todo.xml : ____________________________________ <?xml version="1.0" encoding="ISO-8859-1"?> <todo> <domain id="id2588147" add="task" del="domain"> <name id="id2588150" replace="PCDATA">job</name> <task id="id2588154" replace="PCDATA" add="task">to this</task> <task id="id2589156" replace="PCDATA" add="task">undefined</task> </domain> <domain id="id2588996" add="task" del="domain"> <name id="id2588515" replace="PCDATA">courses</name> <task id="id2588931" replace="PCDATA" add="task">undefined</task> </domain> </todo> _______________________________________ and the following stylesheet (actions.xsl ) ________________________________________ <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > <xsl:output encoding="ISO-8859-1" method="xml"/> <xsl:variable name="targetId"></xsl:variable> <xsl:variable name="action"></xsl:variable> <xsl:template match="/"> <xsl:apply-templates select="*|@*"/> </xsl:template> <xsl:template name="toto"> <toto/> </xsl:template> <xsl:template name="add"> <xsl:param name="type"/> <xsl:choose> <xsl:when test="$type = 'toto'"> <xsl:call-template name="toto"/> </xsl:when> </xsl:choose> </xsl:template> <xsl:template name="copy"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template name="del"> <!-- effacer ! --> </xsl:template> <xsl:template match="*[attribute::id and @id=$targetId]"> <!-- attribute::type pour éviter de confondre l'absence d'attibute et la valeur nulle --> <xsl:choose> <xsl:when test="$action='del'"> <xsl:call-template name="del"/> </xsl:when> <xsl:when test="$action='add'"> <xsl:call-template name="copy"/> <xsl:call-template name="add"> <xsl:with-param name="type">toto</xsl:with-param> </xsl:call-template> </xsl:when> <xsl:when test="$action='repl'"> <xsl:when test="$action='del'"> <xsl:call-template name="del"/> </xsl:when> <xsl:call-template name="add"> <xsl:with-param name="type">toto</xsl:with-param> </xsl:call-template> </xsl:when> </xsl:choose> </xsl:template> <!-- liste des elements qui peuvent être édités, donc attribut id --> <xsl:template match="domain"> <xsl:copy> <xsl:if test="not(@id)"> <xsl:attribute name="id"><xsl:value-of select="generate-id()"/></xsl:attribute> </xsl:if> <xsl:attribute name="add">task</xsl:attribute> <xsl:attribute name="del">domain</xsl:attribute> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="name"> <xsl:copy> <xsl:if test="not(@id)"> <xsl:attribute name="id"><xsl:value-of select="generate-id()"/></xsl:attribute> </xsl:if> <xsl:attribute name="replace">PCDATA</xsl:attribute> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="task"> <xsl:copy> <xsl:if test="not(@id)"> <xsl:attribute name="id"><xsl:value-of select="generate-id()"/></xsl:attribute> </xsl:if> <xsl:attribute name="replace">PCDATA</xsl:attribute> <xsl:attribute name="add">task</xsl:attribute> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="*"> <xsl:copy> <xsl:apply-templates select="node()|@*"/> </xsl:copy> </xsl:template> <xsl:template match="@*"> <xsl:copy/> </xsl:template> </xsl:stylesheet> ___________________________________________________ then xsltproc -v action.xsl todo2.xml outputs : Added namespace: xsl mapped to http://www.w3.org/1999/XSL/Transform xsltPrecomputeStylesheet: removing ignorable blank node xsltParseStylesheetProcess : found stylesheet Registering global variable targetId Defining global variable targetId Registering global variable action Defining global variable action xsltCompilePattern : parsing '/' xsltCompilePattern : parsed /, default priority 0.500000 added pattern : '/' priority 0.500000 xsltCompilePattern : parsing '*[attribute::id and @id=$targetId]' xsltCompilePattern : parsed *[attribute::id and @id=$targetId], default priority 0.500000 added pattern : '*[attribute::id and @id=$targetId]' priority 0.500000 xsltCompilePattern : parsing 'domain' xsltCompilePattern : parsed domain, default priority 0.000000 added pattern : 'domain' priority 0.000000 xsltCompilePattern : parsing 'name' xsltCompilePattern : parsed name, default priority 0.000000 added pattern : 'name' priority 0.000000 xsltCompilePattern : parsing 'task' xsltCompilePattern : parsed task, default priority 0.000000 added pattern : 'task' priority 0.000000 xsltCompilePattern : parsing '*' xsltCompilePattern : parsed *, default priority -0.500000 added pattern : '*' priority -0.500000 xsltCompilePattern : parsing '@*' xsltCompilePattern : parsed @*, default priority -0.500000 added pattern : '@*' priority -0.500000 parsed 11 templates Resolving attribute sets references Initializing keys on todo2.xml Registered 0 modules Registering global variables Registering global variables from action.xsl Evaluating global variable targetId Evaluating global variable action xsltProcessOneNode: applying template '/' for / xsltApplyTemplates: select *|@* xsltApplyTemplates: list of 1 nodes xsltEvalXPathPredicate: returns 0 xsltProcessOneNode: applying template '*' for todo xsltCopy: node todo xsltApplyTemplates: node: todo xsltApplyTemplates: select node()|@* xsltApplyTemplates: list of 5 nodes xsltProcessOneNode: no template found for text xsltDefaultProcessOneNode: copy text Lookup variable targetId found variable targetId xsltEvalXPathPredicate: returns 0 xsltProcessOneNode: applying template 'domain' for domain xsltCopy: node domain xsltIf: test not(@id) xsltIf: test evaluate to 0 xsltApplyOneTemplate: copy text task xsltCopyText: copy text task xsltApplyOneTemplate: copy text domain xsltCopyText: copy text domain xsltApplyTemplates: node: domain xsltApplyTemplates: select node()|@* xsltApplyTemplates: list of 10 nodes xsltProcessOneNode: no template found for text xsltDefaultProcessOneNode: copy text Lookup variable targetId found variable targetId xsltEvalXPathPredicate: returns 0 xsltProcessOneNode: applying template 'name' for name xsltCopy: node name xsltIf: test not(@id) xsltIf: test evaluate to 0 xsltApplyOneTemplate: copy text PCDATA xsltCopyText: copy text PCDATA xsltApplyTemplates: node: name xsltApplyTemplates: select node()|@* xsltApplyTemplates: list of 3 nodes xsltProcessOneNode: applying template '@*' for attribute id xsltCopy: attribute id xsltProcessOneNode: applying template '@*' for attribute replace xsltCopy: attribute replace xsltProcessOneNode: no template found for text xsltDefaultProcessOneNode: copy text job xsltProcessOneNode: no template found for text xsltDefaultProcessOneNode: copy text Lookup variable targetId found variable targetId xsltEvalXPathPredicate: returns 0 xsltProcessOneNode: applying template 'task' for task xsltCopy: node task xsltIf: test not(@id) xsltIf: test evaluate to 0 xsltApplyOneTemplate: copy text PCDATA xsltCopyText: copy text PCDATA xsltApplyOneTemplate: copy text task xsltCopyText: copy text task xsltApplyTemplates: node: task xsltApplyTemplates: select node()|@* xsltApplyTemplates: list of 4 nodes xsltProcessOneNode: no template found for text xsltDefaultProcessOneNode: copy text to this xsltProcessOneNode: applying template '@*' for attribute id xsltCopy: attribute id xsltProcessOneNode: applying template '@*' for attribute replace xsltCopy: attribute replace xsltProcessOneNode: applying template '@*' for attribute add xsltCopy: attribute add xsltProcessOneNode: no template found for text xsltDefaultProcessOneNode: copy text Lookup variable targetId found variable targetId xsltEvalXPathPredicate: returns 0 xsltProcessOneNode: applying template 'task' for task xsltCopy: node task xsltIf: test not(@id) xsltIf: test evaluate to 0 xsltApplyOneTemplate: copy text PCDATA xsltCopyText: copy text PCDATA xsltApplyOneTemplate: copy text task xsltCopyText: copy text task xsltApplyTemplates: node: task xsltApplyTemplates: select node()|@* xsltApplyTemplates: list of 4 nodes xsltProcessOneNode: no template found for text xsltDefaultProcessOneNode: copy text undefined xsltProcessOneNode: applying template '@*' for attribute id xsltCopy: attribute id xsltProcessOneNode: applying template '@*' for attribute replace xsltCopy: attribute replace xsltProcessOneNode: applying template '@*' for attribute add xsltCopy: attribute add xsltProcessOneNode: no template found for text xsltDefaultProcessOneNode: copy text xsltProcessOneNode: applying template '@*' for attribute id xsltCopy: attribute id xsltProcessOneNode: applying template '@*' for attribute add xsltCopy: attribute add xsltProcessOneNode: applying template '@*' for attribute del xsltCopy: attribute del xsltProcessOneNode: no template found for text xsltDefaultProcessOneNode: copy text Lookup variable targetId found variable targetId xsltEvalXPathPredicate: returns 0 xsltProcessOneNode: applying template 'domain' for domain xsltCopy: node domain xsltIf: test not(@id) xsltIf: test evaluate to 0 xsltApplyOneTemplate: copy text task xsltCopyText: copy text task xsltApplyOneTemplate: copy text domain xsltCopyText: copy text domain xsltApplyTemplates: node: domain xsltApplyTemplates: select node()|@* xsltApplyTemplates: list of 8 nodes xsltProcessOneNode: applying template '@*' for attribute id xsltCopy: attribute id xsltProcessOneNode: no template found for text xsltDefaultProcessOneNode: copy text Lookup variable targetId found variable targetId xsltEvalXPathPredicate: returns 0 xsltProcessOneNode: applying template 'name' for name xsltCopy: node name xsltIf: test not(@id) xsltIf: test evaluate to 0 xsltApplyOneTemplate: copy text PCDATA xsltCopyText: copy text PCDATA xsltApplyTemplates: node: name xsltApplyTemplates: select node()|@* xsltApplyTemplates: list of 3 nodes xsltProcessOneNode: applying template '@*' for attribute id xsltCopy: attribute id xsltProcessOneNode: applying template '@*' for attribute replace xsltCopy: attribute replace xsltProcessOneNode: no template found for text xsltDefaultProcessOneNode: copy text courses xsltProcessOneNode: no template found for text xsltDefaultProcessOneNode: copy text Lookup variable targetId found variable targetId xsltEvalXPathPredicate: returns 0 xsltProcessOneNode: applying template 'task' for task xsltCopy: node task xsltIf: test not(@id) xsltIf: test evaluate to 0 xsltApplyOneTemplate: copy text PCDATA xsltCopyText: copy text PCDATA xsltApplyOneTemplate: copy text task xsltCopyText: copy text task xsltApplyTemplates: node: task xsltApplyTemplates: select node()|@* xsltApplyTemplates: list of 4 nodes xsltProcessOneNode: no template found for text xsltDefaultProcessOneNode: copy text undefined xsltProcessOneNode: applying template '@*' for attribute id xsltCopy: attribute id xsltProcessOneNode: applying template '@*' for attribute replace xsltCopy: attribute replace xsltProcessOneNode: applying template '@*' for attribute add xsltCopy: attribute add xsltProcessOneNode: no template found for text xsltDefaultProcessOneNode: copy text xsltProcessOneNode: applying template '@*' for attribute add xsltCopy: attribute add xsltProcessOneNode: applying template '@*' for attribute del xsltCopy: attribute del xsltProcessOneNode: no template found for text xsltDefaultProcessOneNode: copy text and : <?xml version="1.0" encoding="ISO-8859-1"?> <todo> <domain add="task" del="domain" id="id2588147" add="task" del="domain"> ^^^^^^^^^^ ^^^^^^^^^^ <name replace="PCDATA" id="id2588150" replace="PCDATA">job</name> ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^etc. <task replace="PCDATA" add="task" id="id2588154" replace="PCDATA" add="task">to this</task> <task replace="PCDATA" add="task" id="id2589156" replace="PCDATA" add="task">undefined</task> </domain> <domain add="task" del="domain" id="id2588996" add="task" del="domain"> <name replace="PCDATA" id="id2588515" replace="PCDATA">courses</name> <task replace="PCDATA" add="task" id="id2588931" replace="PCDATA" add="task">undefined</task> </domain> </todo> Marc-Olivier Bernard __________________________________________________ xsltproc -V Using libxml 20422, libxslt 10018 and libexslt 709 xsltproc was compiled against libxml 20419, libxslt 10018 and libexslt 709 libxslt 10018 was compiled against libxml 20419 libexslt 709 was compiled against libxml 20419
Hum, right ooops ... the bug was on xsl:copy on an attribute ! This is now fixed in CVS: gnome:~/XSLT/tests/general -> xsltproc bug-89.xsl ../docs/bug-89.xml <?xml version="1.0" encoding="ISO-8859-1"?> <todo> <domain add="task" del="domain" id="id2588147"> <name replace="PCDATA" id="id2588150">job</name> <task replace="PCDATA" add="task" id="id2588154">to this</task> <task replace="PCDATA" add="task" id="id2589156">undefined</task> </domain> <domain add="task" del="domain" id="id2588996"> <name replace="PCDATA" id="id2588515">courses</name> <task replace="PCDATA" add="task" id="id2588931">undefined</task> </domain> </todo> gnome:~/XSLT/tests/general -> thanks for the report and the test case ! Daniel
Okay, this should be fixed in the last releases, Daniel