Fixing #71342 serializing '\n' in attribute values added a specific test.
* tree.c: Fixing #71342 serializing '\n' in attribute values
* result/noent/att3 result/att3 test/att3: added a specific
test.
Daniel
diff --git a/tree.c b/tree.c
index 19e0601..25108d8 100644
--- a/tree.c
+++ b/tree.c
@@ -5791,6 +5791,147 @@
}
/**
+ * xmlAttrSerializeContent:
+ * @buf: the XML buffer output
+ * @doc: the document
+ * @attr: the attribute pointer
+ *
+ * Serialize the attribute in the buffer
+ */
+static void
+xmlAttrSerializeContent(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr attr) {
+ const xmlChar *cur, *base;
+ xmlNodePtr children;
+
+ children = attr->children;
+ while (children != NULL) {
+ switch (children->type) {
+ case XML_TEXT_NODE:
+ base = cur = children->content;
+ while (*cur != 0) {
+ if (*cur == '\n') {
+ if (base != cur)
+ xmlBufferAdd(buf, base, cur - base);
+ xmlBufferAdd(buf, BAD_CAST " ", 5);
+ cur++;
+ base = cur;
+#if 0
+ } else if (*cur == '\'') {
+ if (base != cur)
+ xmlBufferAdd(buf, base, cur - base);
+ xmlBufferAdd(buf, BAD_CAST "'", 6);
+ cur++;
+ base = cur;
+#endif
+ } else if (*cur == '"') {
+ if (base != cur)
+ xmlBufferAdd(buf, base, cur - base);
+ xmlBufferAdd(buf, BAD_CAST """, 6);
+ cur++;
+ base = cur;
+ } else if (*cur == '<') {
+ if (base != cur)
+ xmlBufferAdd(buf, base, cur - base);
+ xmlBufferAdd(buf, BAD_CAST "<", 4);
+ cur++;
+ base = cur;
+ } else if (*cur == '>') {
+ if (base != cur)
+ xmlBufferAdd(buf, base, cur - base);
+ xmlBufferAdd(buf, BAD_CAST ">", 4);
+ cur++;
+ base = cur;
+ } else if (*cur == '&') {
+ if (base != cur)
+ xmlBufferAdd(buf, base, cur - base);
+ xmlBufferAdd(buf, BAD_CAST "&", 5);
+ cur++;
+ base = cur;
+ } else if ((*cur >= 0x80) && ((doc == NULL) ||
+ (doc->encoding == NULL))) {
+ /*
+ * We assume we have UTF-8 content.
+ */
+ char tmp[10];
+ int val = 0, l = 1;
+
+ if (base != cur)
+ xmlBufferAdd(buf, base, cur - base);
+ if (*cur < 0xC0) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlAttrSerializeContent : input not UTF-8\n");
+ if (doc != NULL)
+ doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
+ snprintf(tmp, sizeof(tmp), "&#%d;", *cur);
+ tmp[sizeof(tmp) - 1] = 0;
+ xmlBufferAdd(buf, (xmlChar *) tmp, -1);
+ cur++;
+ base = cur;
+ continue;
+ } else if (*cur < 0xE0) {
+ val = (cur[0]) & 0x1F;
+ val <<= 6;
+ val |= (cur[1]) & 0x3F;
+ l = 2;
+ } else if (*cur < 0xF0) {
+ val = (cur[0]) & 0x0F;
+ val <<= 6;
+ val |= (cur[1]) & 0x3F;
+ val <<= 6;
+ val |= (cur[2]) & 0x3F;
+ l = 3;
+ } else if (*cur < 0xF8) {
+ val = (cur[0]) & 0x07;
+ val <<= 6;
+ val |= (cur[1]) & 0x3F;
+ val <<= 6;
+ val |= (cur[2]) & 0x3F;
+ val <<= 6;
+ val |= (cur[3]) & 0x3F;
+ l = 4;
+ }
+ if ((l == 1) || (!IS_CHAR(val))) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlAttrSerializeContent : char out of range\n");
+ if (doc != NULL)
+ doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
+ snprintf(tmp, sizeof(tmp), "&#%d;", *cur);
+ tmp[sizeof(tmp) - 1] = 0;
+ xmlBufferAdd(buf, (xmlChar *) tmp, -1);
+ cur++;
+ base = cur;
+ continue;
+ }
+ /*
+ * We could do multiple things here. Just save
+ * as a char ref
+ */
+ snprintf(tmp, sizeof(tmp), "&#x%X;", val);
+ tmp[sizeof(tmp) - 1] = 0;
+ xmlBufferAdd(buf, (xmlChar *) tmp, -1);
+ cur += l;
+ base = cur;
+ } else {
+ cur++;
+ }
+ }
+ if (base != cur)
+ xmlBufferAdd(buf, base, cur - base);
+ break;
+ case XML_ENTITY_REF_NODE:
+ xmlBufferAdd(buf, BAD_CAST "&", 1);
+ xmlBufferAdd(buf, children->name, xmlStrlen(children->name));
+ xmlBufferAdd(buf, BAD_CAST ";", 1);
+ break;
+ default:
+ /* should not happen unless we have a badly built tree */
+ break;
+ }
+ children = children->next;
+ }
+}
+
+/**
* xmlAttrDump:
* @buf: the XML buffer output
* @doc: the document
@@ -5800,8 +5941,6 @@
*/
static void
xmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
- xmlChar *value;
-
if (cur == NULL) {
#ifdef DEBUG_TREE
xmlGenericError(xmlGenericErrorContext,
@@ -5815,14 +5954,9 @@
xmlBufferWriteChar(buf, ":");
}
xmlBufferWriteCHAR(buf, cur->name);
- value = xmlNodeListGetString(doc, cur->children, 0);
- if (value != NULL) {
- xmlBufferWriteChar(buf, "=");
- xmlBufferWriteQuotedString(buf, value);
- xmlFree(value);
- } else {
- xmlBufferWriteChar(buf, "=\"\"");
- }
+ xmlBufferWriteChar(buf, "=\"");
+ xmlAttrSerializeContent(buf, doc, cur);
+ xmlBufferWriteChar(buf, "\"");
}
/**
@@ -6213,8 +6347,6 @@
static void
xmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur,
const char *encoding ATTRIBUTE_UNUSED) {
- xmlChar *value;
-
if (cur == NULL) {
#ifdef DEBUG_TREE
xmlGenericError(xmlGenericErrorContext,
@@ -6228,14 +6360,9 @@
xmlOutputBufferWriteString(buf, ":");
}
xmlOutputBufferWriteString(buf, (const char *)cur->name);
- value = xmlNodeListGetString(doc, cur->children, 0);
- if (value) {
- xmlOutputBufferWriteString(buf, "=");
- xmlBufferWriteQuotedString(buf->buffer, value);
- xmlFree(value);
- } else {
- xmlOutputBufferWriteString(buf, "=\"\"");
- }
+ xmlOutputBufferWriteString(buf, "=\"");
+ xmlAttrSerializeContent(buf->buffer, doc, cur);
+ xmlOutputBufferWriteString(buf, "\"");
}
/**