GNOME Bugzilla – Bug 502960
Entities do not see namespaces in SAX mode
Last modified: 2009-08-26 13:58:48 UTC
Please describe the problem: XML tags contained in internal entities do not see the XML namespace when parsed in SAX. The following file demonstrates the problem: <?xml version="1.0"?> <!DOCTYPE EXAMPLE SYSTEM "example.dtd" [ <!ENTITY test "<element2/>"> ]> <EXAMPLE xmlns="http://www.example.org"> <element1/> &test; </EXAMPLE> Steps to reproduce: 1. Save the above test to a file. 2. Run testSAX.exe with the --sax2 option, feeding it the test file. Actual results: The following output is produced: SAX.setDocumentLocator() SAX.startDocument() SAX.internalSubset(EXAMPLE, , example.dtd) SAX.entityDecl(test, 1, (null), (null), <element2/>) SAX.getEntity(test) SAX.externalSubset(EXAMPLE, , example.dtd) SAX.startElementNs(EXAMPLE, NULL, 'http://www.example.org', 1, xmlns='http://www.example.org', 0, 0) SAX.characters ( , 1) SAX.startElementNs(element1, NULL, 'http://www.example.org', 0, 0, 0) SAX.endElementNs(element1, NULL, 'http://www.example.org' ) SAX.characters( , 1) SAX.getEntity(test) SAX.startElementNs(element2, NULL, NULL, 0, 0, 0) SAX.endElementNs(element2, NULL, NULL) SAX.reference(test) SAX.characters( , 1) SAX.endElementNs(EXAMPLE, NULL, ' http://www.example.org') SAX.endDocument() Note that the call to startElementNs includes the namespace for element1, but omits it for element2. Expected results: All calls to startElementNs should include the root xmlns, whether the element was generated as part of an entity reference or not. Does this happen every time? Yes. Other information: Here's a patch: Index: include/libxml/parser.h =================================================================== --- include/libxml/parser.h (revision 6908) +++ include/libxml/parser.h (working copy) @@ -276,6 +276,7 @@ int nsNr; /* the number of inherited namespaces */ int nsMax; /* the size of the arrays */ const xmlChar * *nsTab; /* the array of prefix/namespace name */ + struct _xmlParserCtxt *nsParent; /* parent context to inherit namespaces from */ int *attallocs; /* which attribute were allocated */ void * *pushTab; /* array of data for push */ xmlHashTablePtr attsDefault; /* defaulted attributes if any */ Index: parser.c =================================================================== --- parser.c (revision 6908) +++ parser.c (working copy) @@ -7395,6 +7395,7 @@ return(NULL); return(ctxt->nsTab[i + 1]); } + if (ctxt->nsParent) return xmlGetNamespace(ctxt->nsParent, prefix); return(NULL); } @@ -11600,6 +11601,8 @@ ctxt->str_xmlns = xmlDictLookup(ctxt->dict, BAD_CAST "xmlns", 5); ctxt->str_xml_ns = xmlDictLookup(ctxt->dict, XML_XML_NAMESPACE, 36); + ctxt->nsParent = oldctxt; + oldsax = ctxt->sax; ctxt->sax = oldctxt->sax; xmlDetectSAX2(ctxt); Alternatively, this could be patched without adding a member to xmlParserCtxt by copying the nsTab array (along with nsMax and nsNr) to the new context created in xmlParseBalancedMemoryString(). The downside there would be additional memory allocation.
I don't think this really fixes the problem but this has the nice side effect to eject a namespace warning about it when building the associated tree: paphio:~/XML -> xmllint entns.xml namespace warning : Namespace default prefix was not found <element2/> ^ <?xml version="1.0"?> <!DOCTYPE EXAMPLE SYSTEM "example.dtd" [ <!ENTITY test "<element2/>"> ]> <EXAMPLE xmlns="http://www.example.org"> <element1/> &test; </EXAMPLE> So I implemented the change but with copy to preserve the API/ABI, thanks, marking as FIXED even if I think think it's a complete fix Daniel