diff --git a/parser.c b/parser.c index 95f3ed1c..3bc237b8 100644 --- a/parser.c +++ b/parser.c @@ -4280,7 +4280,7 @@ xmlExpandEntitiesInAttValue(xmlParserCtxtPtr ctxt, const xmlChar *str, */ static xmlChar * xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *attlen, int *alloc, - int normalize) { + int normalize, int isNamespace) { unsigned maxLength = (ctxt->options & XML_PARSE_HUGE) ? XML_MAX_HUGE_LENGTH : XML_MAX_TEXT_LENGTH; @@ -4288,6 +4288,10 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *attlen, int *alloc, xmlChar *ret; int c, l, quote, flags, chunkSize; int inSpace = 1; + int replaceEntities; + + /* Always expand namespace URIs */ + replaceEntities = (ctxt->replaceEntities) || (isNamespace); xmlSBufInit(&buf, maxLength); @@ -4400,7 +4404,7 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *attlen, int *alloc, if (val == 0) goto error; - if ((val == '&') && (!ctxt->replaceEntities)) { + if ((val == '&') && (!replaceEntities)) { /* * The reparsing will be done in xmlStringGetNodeList() * called by the attribute() function in SAX.c @@ -4438,12 +4442,12 @@ xmlParseAttValueInternal(xmlParserCtxtPtr ctxt, int *attlen, int *alloc, continue; if (ent->etype == XML_INTERNAL_PREDEFINED_ENTITY) { - if ((ent->content[0] == '&') && (!ctxt->replaceEntities)) + if ((ent->content[0] == '&') && (!replaceEntities)) xmlSBufAddCString(&buf, "&", 5); else xmlSBufAddString(&buf, ent->content, ent->length); inSpace = 0; - } else if (ctxt->replaceEntities) { + } else if (replaceEntities) { xmlExpandEntityInAttValue(ctxt, &buf, ent->content, ent, normalize, &inSpace, ctxt->inputNr, /* check */ 1); @@ -4544,7 +4548,7 @@ error: xmlChar * xmlParseAttValue(xmlParserCtxtPtr ctxt) { if ((ctxt == NULL) || (ctxt->input == NULL)) return(NULL); - return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0)); + return(xmlParseAttValueInternal(ctxt, NULL, NULL, 0, 0)); } /** @@ -8777,6 +8781,7 @@ xmlParseAttribute2(xmlParserCtxtPtr ctxt, const xmlChar *prefix, *name; xmlChar *val = NULL, *internal_val = NULL; int normalize = 0; + int isNamespace; *value = NULL; GROW; @@ -8812,7 +8817,10 @@ xmlParseAttribute2(xmlParserCtxtPtr ctxt, if (RAW == '=') { NEXT; SKIP_BLANKS; - val = xmlParseAttValueInternal(ctxt, len, alloc, normalize); + isNamespace = (((prefix == NULL) && (name == ctxt->str_xmlns)) || + (prefix == ctxt->str_xmlns)); + val = xmlParseAttValueInternal(ctxt, len, alloc, normalize, + isNamespace); if (val == NULL) goto error; } else { diff --git a/result/entity-in-ns-uri.xml b/result/entity-in-ns-uri.xml new file mode 100644 index 00000000..87655b01 --- /dev/null +++ b/result/entity-in-ns-uri.xml @@ -0,0 +1,8 @@ + + +]> + + + + diff --git a/result/entity-in-ns-uri.xml.rde b/result/entity-in-ns-uri.xml.rde new file mode 100644 index 00000000..aa228df6 --- /dev/null +++ b/result/entity-in-ns-uri.xml.rde @@ -0,0 +1,11 @@ +0 10 doc 0 0 +0 1 doc 0 0 +1 14 #text 0 1 + +1 1 e 1 0 +1 14 #text 0 1 + +1 1 e 1 0 +1 14 #text 0 1 + +0 15 doc 0 0 diff --git a/result/entity-in-ns-uri.xml.rdr b/result/entity-in-ns-uri.xml.rdr new file mode 100644 index 00000000..aa228df6 --- /dev/null +++ b/result/entity-in-ns-uri.xml.rdr @@ -0,0 +1,11 @@ +0 10 doc 0 0 +0 1 doc 0 0 +1 14 #text 0 1 + +1 1 e 1 0 +1 14 #text 0 1 + +1 1 e 1 0 +1 14 #text 0 1 + +0 15 doc 0 0 diff --git a/result/entity-in-ns-uri.xml.sax b/result/entity-in-ns-uri.xml.sax new file mode 100644 index 00000000..e06eabd4 --- /dev/null +++ b/result/entity-in-ns-uri.xml.sax @@ -0,0 +1,21 @@ +SAX.setDocumentLocator() +SAX.startDocument() +SAX.internalSubset(doc, , ) +SAX.entityDecl(e, 1, (null), (null), -) +SAX.getEntity(e) +SAX.externalSubset(doc, , ) +SAX.startElement(doc) +SAX.characters( + , 5) +SAX.getEntity(e) +SAX.startElement(e, xmlns='foo:x&x&x'x&e;x') +SAX.endElement(e) +SAX.characters( + , 5) +SAX.getEntity(e) +SAX.startElement(e, xmlns:ns='foo:x&x&x'x&e;x') +SAX.endElement(e) +SAX.characters( +, 1) +SAX.endElement(doc) +SAX.endDocument() diff --git a/result/entity-in-ns-uri.xml.sax2 b/result/entity-in-ns-uri.xml.sax2 new file mode 100644 index 00000000..13b2547e --- /dev/null +++ b/result/entity-in-ns-uri.xml.sax2 @@ -0,0 +1,21 @@ +SAX.setDocumentLocator() +SAX.startDocument() +SAX.internalSubset(doc, , ) +SAX.entityDecl(e, 1, (null), (null), -) +SAX.getEntity(e) +SAX.externalSubset(doc, , ) +SAX.startElementNs(doc, NULL, NULL, 0, 0, 0) +SAX.characters( + , 5) +SAX.getEntity(e) +SAX.startElementNs(e, NULL, 'foo:x&x&x'x-x', 1, xmlns='foo:x&x&x'x-x', 0, 0) +SAX.endElementNs(e, NULL, 'foo:x&x&x'x-x') +SAX.characters( + , 5) +SAX.getEntity(e) +SAX.startElementNs(e, NULL, NULL, 1, xmlns:ns='foo:x&x&x'x-x', 0, 0) +SAX.endElementNs(e, NULL, NULL) +SAX.characters( +, 1) +SAX.endElementNs(doc, NULL, NULL) +SAX.endDocument() diff --git a/result/noent/entity-in-ns-uri.xml b/result/noent/entity-in-ns-uri.xml new file mode 100644 index 00000000..87655b01 --- /dev/null +++ b/result/noent/entity-in-ns-uri.xml @@ -0,0 +1,8 @@ + + +]> + + + + diff --git a/result/noent/entity-in-ns-uri.xml.sax2 b/result/noent/entity-in-ns-uri.xml.sax2 new file mode 100644 index 00000000..13b2547e --- /dev/null +++ b/result/noent/entity-in-ns-uri.xml.sax2 @@ -0,0 +1,21 @@ +SAX.setDocumentLocator() +SAX.startDocument() +SAX.internalSubset(doc, , ) +SAX.entityDecl(e, 1, (null), (null), -) +SAX.getEntity(e) +SAX.externalSubset(doc, , ) +SAX.startElementNs(doc, NULL, NULL, 0, 0, 0) +SAX.characters( + , 5) +SAX.getEntity(e) +SAX.startElementNs(e, NULL, 'foo:x&x&x'x-x', 1, xmlns='foo:x&x&x'x-x', 0, 0) +SAX.endElementNs(e, NULL, 'foo:x&x&x'x-x') +SAX.characters( + , 5) +SAX.getEntity(e) +SAX.startElementNs(e, NULL, NULL, 1, xmlns:ns='foo:x&x&x'x-x', 0, 0) +SAX.endElementNs(e, NULL, NULL) +SAX.characters( +, 1) +SAX.endElementNs(doc, NULL, NULL) +SAX.endDocument() diff --git a/test/entity-in-ns-uri.xml b/test/entity-in-ns-uri.xml new file mode 100644 index 00000000..e00c0217 --- /dev/null +++ b/test/entity-in-ns-uri.xml @@ -0,0 +1,7 @@ + +]> + + + + diff --git a/xmlsave.c b/xmlsave.c index 13b2ed3c..cf4e0583 100644 --- a/xmlsave.c +++ b/xmlsave.c @@ -870,7 +870,8 @@ xmlOutputBufferWriteWSNonSig(xmlSaveCtxtPtr ctxt, int extra) * If @ctxt is supplied, @buf should be its buffer. */ static void -xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur, xmlSaveCtxtPtr ctxt) { +xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNsPtr cur, + xmlSaveCtxtPtr ctxt) { if ((cur == NULL) || (buf == NULL)) return; if ((cur->type == XML_LOCAL_NAMESPACE) && (cur->href != NULL)) { if (xmlStrEqual(cur->prefix, BAD_CAST "xml")) @@ -887,24 +888,12 @@ xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur, xmlSaveCtxtPtr ctxt) { xmlOutputBufferWriteString(buf, (const char *)cur->prefix); } else xmlOutputBufferWrite(buf, 5, "xmlns"); - xmlOutputBufferWrite(buf, 1, "="); - xmlOutputBufferWriteQuotedString(buf, cur->href); + xmlOutputBufferWrite(buf, 2, "=\""); + xmlBufAttrSerializeTxtContent(buf, doc, cur->href); + xmlOutputBufferWrite(buf, 1, "\""); } } -/** - * xmlNsDumpOutputCtxt - * @ctxt: the save context - * @cur: a namespace - * - * Dump a local Namespace definition to a save context. - * Should be called in the context of attribute dumps. - */ -static void -xmlNsDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) { - xmlNsDumpOutput(ctxt->buf, cur, ctxt); -} - /** * xmlNsListDumpOutputCtxt * @ctxt: the save context @@ -914,9 +903,9 @@ xmlNsDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) { * Should be called in the context of attribute dumps. */ static void -xmlNsListDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) { +xmlNsListDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlDocPtr doc, xmlNsPtr cur) { while (cur != NULL) { - xmlNsDumpOutput(ctxt->buf, cur, ctxt); + xmlNsDumpOutput(ctxt->buf, doc, cur, ctxt); cur = cur->next; } } @@ -932,7 +921,7 @@ xmlNsListDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) { void xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) { while (cur != NULL) { - xmlNsDumpOutput(buf, cur, NULL); + xmlNsDumpOutput(buf, NULL, cur, NULL); cur = cur->next; } } @@ -1168,7 +1157,7 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { } xmlOutputBufferWriteString(buf, (const char *)cur->name); if (cur->nsDef) - xmlNsListDumpOutputCtxt(ctxt, cur->nsDef); + xmlNsListDumpOutputCtxt(ctxt, cur->doc, cur->nsDef); for (attr = cur->properties; attr != NULL; attr = attr->next) xmlAttrDumpOutput(ctxt, attr); @@ -1308,7 +1297,7 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { break; case XML_NAMESPACE_DECL: - xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur); + xmlNsDumpOutput(buf, NULL, (xmlNsPtr) cur, ctxt); break; default: @@ -1692,7 +1681,7 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { break; case XML_NAMESPACE_DECL: - xmlNsDumpOutputCtxt(ctxt, (xmlNsPtr) cur); + xmlNsDumpOutput(buf, NULL, (xmlNsPtr) cur, ctxt); break; case XML_DTD_NODE: @@ -1747,7 +1736,7 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) { xmlOutputBufferWriteString(buf, (const char *)cur->name); if (cur->nsDef) - xmlNsListDumpOutputCtxt(ctxt, cur->nsDef); + xmlNsListDumpOutputCtxt(ctxt, cur->doc, cur->nsDef); if ((xmlStrEqual(cur->name, BAD_CAST "html") && (cur->ns == NULL) && (cur->nsDef == NULL))) { /*