mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-10-24 13:33:01 +03:00
save: Rework text escaping
Stop using xmlOutputBufferWriteEscape except when using deprecated xmlSaveSetEscape. Rewrite xmlOutputBufferWriteEscape to use an extra buffer and call xmlOutputBufferWrite. Introduce xmlSerializeText to serialize both text and attribute content. Don't read encoding from document when serializing and remove all hacks that temporarily changed the document's encoding.
This commit is contained in:
128
xmlIO.c
128
xmlIO.c
@@ -2452,130 +2452,38 @@ xmlEscapeContent(unsigned char* out, int *outlen,
|
||||
int
|
||||
xmlOutputBufferWriteEscape(xmlOutputBufferPtr out, const xmlChar *str,
|
||||
xmlCharEncodingOutputFunc escaping) {
|
||||
int nbchars = 0; /* number of chars to output to I/O */
|
||||
int ret; /* return from function call */
|
||||
int written = 0; /* number of char written to I/O so far */
|
||||
int oldwritten=0;/* loop guard */
|
||||
int chunk; /* number of byte currently processed from str */
|
||||
int len; /* number of bytes in str */
|
||||
int cons; /* byte from str consumed */
|
||||
int ret;
|
||||
int written = 0;
|
||||
int len;
|
||||
|
||||
if ((out == NULL) || (out->error) || (str == NULL) ||
|
||||
(out->buffer == NULL))
|
||||
if ((out == NULL) || (out->error) || (str == NULL))
|
||||
return(-1);
|
||||
len = strlen((const char *)str);
|
||||
if (len < 0) return(0);
|
||||
if (out->error) return(-1);
|
||||
if (escaping == NULL) escaping = xmlEscapeContent;
|
||||
if (escaping == NULL)
|
||||
escaping = xmlEscapeContent;
|
||||
|
||||
do {
|
||||
oldwritten = written;
|
||||
while (len > 0) {
|
||||
xmlChar buf[1024];
|
||||
int c_out;
|
||||
int c_in;
|
||||
|
||||
/*
|
||||
* how many bytes to consume and how many bytes to store.
|
||||
*/
|
||||
cons = len;
|
||||
chunk = xmlBufAvail(out->buffer);
|
||||
c_out = 1024;
|
||||
c_in = len;
|
||||
|
||||
/*
|
||||
* make sure we have enough room to save first, if this is
|
||||
* not the case force a flush, but make sure we stay in the loop
|
||||
*/
|
||||
if (chunk < 40) {
|
||||
if (xmlBufGrow(out->buffer, 100) < 0) {
|
||||
out->error = XML_ERR_NO_MEMORY;
|
||||
return(-1);
|
||||
}
|
||||
oldwritten = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* first handle encoding stuff.
|
||||
*/
|
||||
if (out->encoder != NULL) {
|
||||
/*
|
||||
* Store the data in the incoming raw buffer
|
||||
*/
|
||||
if (out->conv == NULL) {
|
||||
out->conv = xmlBufCreate();
|
||||
if (out->conv == NULL) {
|
||||
out->error = XML_ERR_NO_MEMORY;
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
ret = escaping(xmlBufEnd(out->buffer) ,
|
||||
&chunk, str, &cons);
|
||||
ret = escaping(buf, &c_out, str, &c_in);
|
||||
if (ret < 0) {
|
||||
out->error = XML_ERR_NO_MEMORY;
|
||||
return(-1);
|
||||
}
|
||||
xmlBufAddLen(out->buffer, chunk);
|
||||
str += c_in;
|
||||
len -= c_in;
|
||||
|
||||
if ((xmlBufUse(out->buffer) < MINLEN) && (cons == len))
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* convert as much as possible to the output buffer.
|
||||
*/
|
||||
ret = xmlCharEncOutput(out, 0);
|
||||
ret = xmlOutputBufferWrite(out, c_out, (char *) buf);
|
||||
if (ret < 0)
|
||||
return(-1);
|
||||
if (out->writecallback)
|
||||
nbchars = xmlBufUse(out->conv);
|
||||
else
|
||||
nbchars = ret >= 0 ? ret : 0;
|
||||
} else {
|
||||
ret = escaping(xmlBufEnd(out->buffer), &chunk, str, &cons);
|
||||
if (ret < 0) {
|
||||
out->error = XML_ERR_NO_MEMORY;
|
||||
return(-1);
|
||||
return(ret);
|
||||
written += ret;
|
||||
}
|
||||
xmlBufAddLen(out->buffer, chunk);
|
||||
if (out->writecallback)
|
||||
nbchars = xmlBufUse(out->buffer);
|
||||
else
|
||||
nbchars = chunk;
|
||||
}
|
||||
str += cons;
|
||||
len -= cons;
|
||||
|
||||
if (out->writecallback) {
|
||||
if ((nbchars < MINLEN) && (len <= 0))
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* second write the stuff to the I/O channel
|
||||
*/
|
||||
if (out->encoder != NULL) {
|
||||
ret = out->writecallback(out->context,
|
||||
(const char *)xmlBufContent(out->conv), nbchars);
|
||||
if (ret >= 0)
|
||||
xmlBufShrink(out->conv, ret);
|
||||
} else {
|
||||
ret = out->writecallback(out->context,
|
||||
(const char *)xmlBufContent(out->buffer), nbchars);
|
||||
if (ret >= 0)
|
||||
xmlBufShrink(out->buffer, ret);
|
||||
}
|
||||
if (ret < 0) {
|
||||
out->error = (ret == -1) ? XML_IO_WRITE : -ret;
|
||||
return(-1);
|
||||
}
|
||||
if (out->written > INT_MAX - ret)
|
||||
out->written = INT_MAX;
|
||||
else
|
||||
out->written += ret;
|
||||
} else if (xmlBufAvail(out->buffer) < MINLEN) {
|
||||
if (xmlBufGrow(out->buffer, MINLEN) < 0) {
|
||||
out->error = XML_ERR_NO_MEMORY;
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
written += nbchars;
|
||||
} while ((len > 0) && (oldwritten != written));
|
||||
|
||||
done:
|
||||
return(written);
|
||||
}
|
||||
|
||||
|
||||
377
xmlsave.c
377
xmlsave.c
@@ -31,6 +31,9 @@
|
||||
|
||||
#define XHTML_NS_NAME BAD_CAST "http://www.w3.org/1999/xhtml"
|
||||
|
||||
#define XML_ESCAPE_ATTR (1u << 0)
|
||||
#define XML_ESCAPE_NON_ASCII (1u << 1)
|
||||
|
||||
struct _xmlSaveCtxt {
|
||||
void *_private;
|
||||
int type;
|
||||
@@ -124,9 +127,9 @@ xmlSaveErr(xmlOutputBufferPtr out, int code, xmlNodePtr node,
|
||||
* Special escaping routines *
|
||||
* *
|
||||
************************************************************************/
|
||||
static unsigned char *
|
||||
xmlSerializeHexCharRef(unsigned char *out, int val) {
|
||||
unsigned char *ptr;
|
||||
static char *
|
||||
xmlSerializeHexCharRef(char *out, int val) {
|
||||
char *ptr;
|
||||
|
||||
*out++ = '&';
|
||||
*out++ = '#';
|
||||
@@ -165,104 +168,112 @@ xmlSerializeHexCharRef(unsigned char *out, int val) {
|
||||
return(out);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlEscapeEntities:
|
||||
* @out: a pointer to an array of bytes to store the result
|
||||
* @outlen: the length of @out
|
||||
* @in: a pointer to an array of unescaped UTF-8 bytes
|
||||
* @inlen: the length of @in
|
||||
*
|
||||
* Take a block of UTF-8 chars in and escape them. Used when there is no
|
||||
* encoding specified.
|
||||
*
|
||||
* Returns 0 if success, or -1 otherwise
|
||||
* The value of @inlen after return is the number of octets consumed
|
||||
* if the return value is positive, else unpredictable.
|
||||
* The value of @outlen after return is the number of octets consumed.
|
||||
*/
|
||||
static int
|
||||
xmlEscapeEntities(unsigned char* out, int *outlen,
|
||||
const xmlChar* in, int *inlen) {
|
||||
unsigned char* outstart = out;
|
||||
const unsigned char* base = in;
|
||||
unsigned char* outend = out + *outlen;
|
||||
const unsigned char* inend;
|
||||
int val;
|
||||
static void
|
||||
xmlSerializeText(xmlOutputBufferPtr buf, const xmlChar *string,
|
||||
unsigned flags) {
|
||||
char tmp[12];
|
||||
const char *base, *cur;
|
||||
|
||||
inend = in + (*inlen);
|
||||
if (string == NULL)
|
||||
return;
|
||||
|
||||
while ((in < inend) && (out < outend)) {
|
||||
if (*in == '<') {
|
||||
if (outend - out < 4) break;
|
||||
*out++ = '&';
|
||||
*out++ = 'l';
|
||||
*out++ = 't';
|
||||
*out++ = ';';
|
||||
in++;
|
||||
continue;
|
||||
} else if (*in == '>') {
|
||||
if (outend - out < 4) break;
|
||||
*out++ = '&';
|
||||
*out++ = 'g';
|
||||
*out++ = 't';
|
||||
*out++ = ';';
|
||||
in++;
|
||||
continue;
|
||||
} else if (*in == '&') {
|
||||
if (outend - out < 5) break;
|
||||
*out++ = '&';
|
||||
*out++ = 'a';
|
||||
*out++ = 'm';
|
||||
*out++ = 'p';
|
||||
*out++ = ';';
|
||||
in++;
|
||||
continue;
|
||||
} else if (*in == 0xD) {
|
||||
if (outend - out < 5) break;
|
||||
*out++ = '&';
|
||||
*out++ = '#';
|
||||
*out++ = 'x';
|
||||
*out++ = 'D';
|
||||
*out++ = ';';
|
||||
in++;
|
||||
} else if (((*in >= 0x20) && (*in < 0x80)) ||
|
||||
(*in == 0xA) || (*in == 0x9)) {
|
||||
/*
|
||||
* default case, just copy !
|
||||
*/
|
||||
*out++ = *in++;
|
||||
continue;
|
||||
} else if (*in < 0x80) {
|
||||
/* invalid control char */
|
||||
if (outend - out < 8) break;
|
||||
out = xmlSerializeHexCharRef(out, 0xFFFD);
|
||||
in++;
|
||||
} else {
|
||||
int len;
|
||||
base = cur = (const char *) string;
|
||||
|
||||
if (outend - out < 11) break;
|
||||
while (*cur != 0) {
|
||||
const char *repl = NULL;
|
||||
int replSize = 0;
|
||||
int c = (unsigned char) *cur;
|
||||
|
||||
len = inend - in;
|
||||
val = xmlGetUTF8Char(in, &len);
|
||||
if ((c >= 0x80) && (flags & XML_ESCAPE_NON_ASCII)) {
|
||||
int val = 0, l = 4;
|
||||
|
||||
if (base != cur)
|
||||
xmlOutputBufferWrite(buf, cur - base, base);
|
||||
|
||||
val = xmlGetUTF8Char((const xmlChar *) cur, &l);
|
||||
if (val < 0) {
|
||||
val = 0xFFFD;
|
||||
in++;
|
||||
cur++;
|
||||
} else {
|
||||
if (!IS_CHAR(val))
|
||||
val = 0xFFFD;
|
||||
in += len;
|
||||
cur += l;
|
||||
}
|
||||
|
||||
/*
|
||||
* We could do multiple things here. Just save as a char ref
|
||||
*/
|
||||
out = xmlSerializeHexCharRef(out, val);
|
||||
xmlSerializeHexCharRef(tmp, val);
|
||||
xmlOutputBufferWriteString(buf, tmp);
|
||||
base = cur;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case '\t':
|
||||
if (flags & XML_ESCAPE_ATTR) {
|
||||
repl = "	";
|
||||
replSize = 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
if (flags & XML_ESCAPE_ATTR) {
|
||||
repl = " ";
|
||||
replSize = 5;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
if ((flags & XML_ESCAPE_NON_ASCII) &&
|
||||
((flags & XML_ESCAPE_ATTR) == 0))
|
||||
repl = "
";
|
||||
else
|
||||
repl = " ";
|
||||
replSize = 5;
|
||||
break;
|
||||
|
||||
case '"':
|
||||
if (flags & XML_ESCAPE_ATTR) {
|
||||
repl = "&#quot;";
|
||||
replSize = 6;
|
||||
}
|
||||
break;
|
||||
|
||||
case '<':
|
||||
repl = "<";
|
||||
replSize = 4;
|
||||
break;
|
||||
|
||||
case '>':
|
||||
repl = ">";
|
||||
replSize = 4;
|
||||
break;
|
||||
|
||||
case '&':
|
||||
repl = "&";
|
||||
replSize = 5;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (c < 0x20) {
|
||||
repl = "�";
|
||||
replSize = 8;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (repl == NULL) {
|
||||
cur++;
|
||||
} else {
|
||||
if (base != cur)
|
||||
xmlOutputBufferWrite(buf, cur - base, base);
|
||||
xmlOutputBufferWrite(buf, replSize, repl);
|
||||
cur++;
|
||||
base = cur;
|
||||
}
|
||||
}
|
||||
*outlen = out - outstart;
|
||||
*inlen = in - base;
|
||||
return(0);
|
||||
|
||||
if (base != cur)
|
||||
xmlOutputBufferWrite(buf, cur - base, base);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
@@ -313,9 +324,6 @@ xmlSaveCtxtInit(xmlSaveCtxtPtr ctxt, int options)
|
||||
{
|
||||
if (ctxt == NULL) return;
|
||||
|
||||
if ((ctxt->encoding == NULL) && (ctxt->escape == NULL))
|
||||
ctxt->escape = xmlEscapeEntities;
|
||||
|
||||
xmlSaveSetIndentString(ctxt, xmlTreeIndentString);
|
||||
|
||||
if (options & XML_SAVE_FORMAT)
|
||||
@@ -376,7 +384,6 @@ xmlNewSaveCtxt(const char *encoding, int options)
|
||||
return(NULL);
|
||||
}
|
||||
ret->encoding = xmlStrdup((const xmlChar *)encoding);
|
||||
ret->escape = NULL;
|
||||
}
|
||||
|
||||
xmlSaveCtxtInit(ret, options);
|
||||
@@ -389,25 +396,33 @@ xmlNewSaveCtxt(const char *encoding, int options)
|
||||
* Dumping XML tree content to a simple buffer *
|
||||
* *
|
||||
************************************************************************/
|
||||
|
||||
static void
|
||||
xmlSaveWriteText(xmlSaveCtxt *ctxt, const xmlChar *text, unsigned flags) {
|
||||
if (ctxt->encoding == NULL)
|
||||
flags |= XML_ESCAPE_NON_ASCII;
|
||||
|
||||
xmlSerializeText(ctxt->buf, text, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlAttrSerializeContent:
|
||||
* @buf: the XML buffer output
|
||||
* @doc: the document
|
||||
* xmlSaveWriteAttrContent:
|
||||
* @ctxt: save context
|
||||
* @attr: the attribute pointer
|
||||
*
|
||||
* Serialize the attribute in the buffer
|
||||
*/
|
||||
static void
|
||||
xmlAttrSerializeContent(xmlOutputBufferPtr buf, xmlAttrPtr attr)
|
||||
xmlSaveWriteAttrContent(xmlSaveCtxt *ctxt, xmlAttrPtr attr)
|
||||
{
|
||||
xmlNodePtr children;
|
||||
xmlOutputBufferPtr buf = ctxt->buf;
|
||||
|
||||
children = attr->children;
|
||||
while (children != NULL) {
|
||||
switch (children->type) {
|
||||
case XML_TEXT_NODE:
|
||||
xmlBufAttrSerializeTxtContent(buf, attr->doc,
|
||||
children->content);
|
||||
xmlSaveWriteText(ctxt, children->content, XML_ESCAPE_ATTR);
|
||||
break;
|
||||
case XML_ENTITY_REF_NODE:
|
||||
xmlOutputBufferWrite(buf, 1, "&");
|
||||
@@ -899,9 +914,14 @@ xmlOutputBufferWriteWSNonSig(xmlSaveCtxtPtr ctxt, int extra)
|
||||
* If @ctxt is supplied, @buf should be its buffer.
|
||||
*/
|
||||
static void
|
||||
xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNsPtr cur,
|
||||
xmlSaveCtxtPtr ctxt) {
|
||||
xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur, xmlSaveCtxtPtr ctxt) {
|
||||
unsigned escapeFlags = XML_ESCAPE_ATTR;
|
||||
|
||||
if ((cur == NULL) || (buf == NULL)) return;
|
||||
|
||||
if ((ctxt == NULL) || (ctxt->encoding == NULL))
|
||||
escapeFlags |= XML_ESCAPE_NON_ASCII;
|
||||
|
||||
if ((cur->type == XML_LOCAL_NAMESPACE) && (cur->href != NULL)) {
|
||||
if (xmlStrEqual(cur->prefix, BAD_CAST "xml"))
|
||||
return;
|
||||
@@ -918,7 +938,7 @@ xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNsPtr cur,
|
||||
} else
|
||||
xmlOutputBufferWrite(buf, 5, "xmlns");
|
||||
xmlOutputBufferWrite(buf, 2, "=\"");
|
||||
xmlBufAttrSerializeTxtContent(buf, doc, cur->href);
|
||||
xmlSerializeText(buf, cur->href, escapeFlags);
|
||||
xmlOutputBufferWrite(buf, 1, "\"");
|
||||
}
|
||||
}
|
||||
@@ -932,9 +952,9 @@ xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNsPtr cur,
|
||||
* Should be called in the context of attribute dumps.
|
||||
*/
|
||||
static void
|
||||
xmlNsListDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlDocPtr doc, xmlNsPtr cur) {
|
||||
xmlNsListDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlNsPtr cur) {
|
||||
while (cur != NULL) {
|
||||
xmlNsDumpOutput(ctxt->buf, doc, cur, ctxt);
|
||||
xmlNsDumpOutput(ctxt->buf, cur, ctxt);
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
@@ -950,7 +970,7 @@ xmlNsListDumpOutputCtxt(xmlSaveCtxtPtr ctxt, xmlDocPtr doc, xmlNsPtr cur) {
|
||||
void
|
||||
xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
|
||||
while (cur != NULL) {
|
||||
xmlNsDumpOutput(buf, NULL, cur, NULL);
|
||||
xmlNsDumpOutput(buf, cur, NULL);
|
||||
cur = cur->next;
|
||||
}
|
||||
}
|
||||
@@ -1045,7 +1065,7 @@ xmlAttrDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
xmlAttrSerializeContent(buf, cur);
|
||||
xmlSaveWriteAttrContent(ctxt, cur);
|
||||
}
|
||||
xmlOutputBufferWrite(buf, 1, "\"");
|
||||
}
|
||||
@@ -1059,7 +1079,6 @@ xmlAttrDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
|
||||
*/
|
||||
static int
|
||||
htmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
|
||||
const xmlChar *oldenc = NULL;
|
||||
const xmlChar *oldctxtenc = ctxt->encoding;
|
||||
const xmlChar *encoding = ctxt->encoding;
|
||||
xmlOutputBufferPtr buf = ctxt->buf;
|
||||
@@ -1069,14 +1088,8 @@ htmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
|
||||
xmlInitParser();
|
||||
|
||||
doc = cur->doc;
|
||||
if (doc != NULL) {
|
||||
oldenc = doc->encoding;
|
||||
if (ctxt->encoding != NULL) {
|
||||
doc->encoding = BAD_CAST ctxt->encoding;
|
||||
} else if (doc->encoding != NULL) {
|
||||
if ((encoding == NULL) && (doc != NULL))
|
||||
encoding = doc->encoding;
|
||||
}
|
||||
}
|
||||
|
||||
if ((encoding != NULL) && (doc != NULL))
|
||||
htmlSetMetaEncoding(doc, (const xmlChar *) encoding);
|
||||
@@ -1086,10 +1099,8 @@ htmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
|
||||
encoding = BAD_CAST "HTML";
|
||||
if ((encoding != NULL) && (oldctxtenc == NULL) &&
|
||||
(buf->encoder == NULL) && (buf->conv == NULL)) {
|
||||
if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
|
||||
doc->encoding = oldenc;
|
||||
if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0)
|
||||
return(-1);
|
||||
}
|
||||
switched_encoding = 1;
|
||||
}
|
||||
if (ctxt->options & XML_SAVE_FORMAT)
|
||||
@@ -1104,8 +1115,6 @@ htmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
|
||||
if ((switched_encoding) && (oldctxtenc == NULL)) {
|
||||
xmlSaveClearEncoding(ctxt);
|
||||
}
|
||||
if (doc != NULL)
|
||||
doc->encoding = oldenc;
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
@@ -1182,7 +1191,7 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
|
||||
}
|
||||
xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
||||
if (cur->nsDef)
|
||||
xmlNsListDumpOutputCtxt(ctxt, cur->doc, cur->nsDef);
|
||||
xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
|
||||
for (attr = cur->properties; attr != NULL; attr = attr->next)
|
||||
xmlAttrDumpOutput(ctxt, attr);
|
||||
|
||||
@@ -1235,7 +1244,15 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
|
||||
if (cur->content == NULL)
|
||||
break;
|
||||
if (cur->name != xmlStringTextNoenc) {
|
||||
xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
|
||||
if (ctxt->escape)
|
||||
xmlOutputBufferWriteEscape(buf, cur->content,
|
||||
ctxt->escape);
|
||||
#ifdef TEST_OUTPUT_BUFFER_WRITE_ESCAPE
|
||||
else if (ctxt->encoding)
|
||||
xmlOutputBufferWriteEscape(buf, cur->content, NULL);
|
||||
#endif
|
||||
else
|
||||
xmlSaveWriteText(ctxt, cur->content, /* flags */ 0);
|
||||
} else {
|
||||
/*
|
||||
* Disable escaping, needed for XSLT
|
||||
@@ -1316,7 +1333,7 @@ xmlNodeDumpOutputInternal(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
|
||||
break;
|
||||
|
||||
case XML_NAMESPACE_DECL:
|
||||
xmlNsDumpOutput(buf, NULL, (xmlNsPtr) cur, ctxt);
|
||||
xmlNsDumpOutput(buf, (xmlNsPtr) cur, ctxt);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1377,10 +1394,8 @@ xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) {
|
||||
xmlDtdPtr dtd;
|
||||
int is_xhtml = 0;
|
||||
#endif
|
||||
const xmlChar *oldenc = cur->encoding;
|
||||
const xmlChar *oldctxtenc = ctxt->encoding;
|
||||
const xmlChar *encoding = ctxt->encoding;
|
||||
xmlCharEncodingOutputFunc oldescape = ctxt->escape;
|
||||
xmlOutputBufferPtr buf = ctxt->buf;
|
||||
xmlCharEncoding enc;
|
||||
int switched_encoding = 0;
|
||||
@@ -1391,11 +1406,8 @@ xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) {
|
||||
(cur->type != XML_DOCUMENT_NODE))
|
||||
return(-1);
|
||||
|
||||
if (ctxt->encoding != NULL) {
|
||||
cur->encoding = BAD_CAST ctxt->encoding;
|
||||
} else if (cur->encoding != NULL) {
|
||||
if (ctxt->encoding == NULL)
|
||||
encoding = cur->encoding;
|
||||
}
|
||||
|
||||
if (((cur->type == XML_HTML_DOCUMENT_NODE) &&
|
||||
((ctxt->options & XML_SAVE_AS_XML) == 0) &&
|
||||
@@ -1411,7 +1423,6 @@ xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) {
|
||||
if ((encoding != NULL) && (oldctxtenc == NULL) &&
|
||||
(buf->encoder == NULL) && (buf->conv == NULL)) {
|
||||
if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
|
||||
cur->encoding = oldenc;
|
||||
return(-1);
|
||||
}
|
||||
}
|
||||
@@ -1421,8 +1432,6 @@ xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) {
|
||||
else
|
||||
htmlDocContentDumpFormatOutput(buf, cur,
|
||||
(const char *)encoding, 0);
|
||||
if (ctxt->encoding != NULL)
|
||||
cur->encoding = oldenc;
|
||||
return(0);
|
||||
#else
|
||||
return(-1);
|
||||
@@ -1442,14 +1451,10 @@ xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) {
|
||||
* document since we output the XMLDecl the conversion
|
||||
* must be done to not generate not well formed documents.
|
||||
*/
|
||||
if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0) {
|
||||
cur->encoding = oldenc;
|
||||
if (xmlSaveSwitchEncoding(ctxt, (const char*) encoding) < 0)
|
||||
return(-1);
|
||||
}
|
||||
switched_encoding = 1;
|
||||
}
|
||||
if (ctxt->escape == xmlEscapeEntities)
|
||||
ctxt->escape = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -1512,9 +1517,7 @@ xmlDocContentDumpOutput(xmlSaveCtxtPtr ctxt, xmlDocPtr cur) {
|
||||
*/
|
||||
if ((switched_encoding) && (oldctxtenc == NULL)) {
|
||||
xmlSaveClearEncoding(ctxt);
|
||||
ctxt->escape = oldescape;
|
||||
}
|
||||
cur->encoding = oldenc;
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -1641,7 +1644,7 @@ xhtmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
|
||||
(xmlStrEqual(parent->name, BAD_CAST "frame")) ||
|
||||
(xmlStrEqual(parent->name, BAD_CAST "iframe")))) {
|
||||
xmlOutputBufferWrite(buf, 5, " id=\"");
|
||||
xmlAttrSerializeContent(buf, name);
|
||||
xmlSaveWriteAttrContent(ctxt, name);
|
||||
xmlOutputBufferWrite(buf, 1, "\"");
|
||||
}
|
||||
}
|
||||
@@ -1650,12 +1653,12 @@ xhtmlAttrListDumpOutput(xmlSaveCtxtPtr ctxt, xmlAttrPtr cur) {
|
||||
*/
|
||||
if ((lang != NULL) && (xml_lang == NULL)) {
|
||||
xmlOutputBufferWrite(buf, 11, " xml:lang=\"");
|
||||
xmlAttrSerializeContent(buf, lang);
|
||||
xmlSaveWriteAttrContent(ctxt, lang);
|
||||
xmlOutputBufferWrite(buf, 1, "\"");
|
||||
} else
|
||||
if ((xml_lang != NULL) && (lang == NULL)) {
|
||||
xmlOutputBufferWrite(buf, 7, " lang=\"");
|
||||
xmlAttrSerializeContent(buf, xml_lang);
|
||||
xmlSaveWriteAttrContent(ctxt, xml_lang);
|
||||
xmlOutputBufferWrite(buf, 1, "\"");
|
||||
}
|
||||
}
|
||||
@@ -1693,7 +1696,7 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
|
||||
break;
|
||||
|
||||
case XML_NAMESPACE_DECL:
|
||||
xmlNsDumpOutput(buf, NULL, (xmlNsPtr) cur, ctxt);
|
||||
xmlNsDumpOutput(buf, (xmlNsPtr) cur, ctxt);
|
||||
break;
|
||||
|
||||
case XML_DTD_NODE:
|
||||
@@ -1745,7 +1748,7 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
|
||||
|
||||
xmlOutputBufferWriteString(buf, (const char *)cur->name);
|
||||
if (cur->nsDef)
|
||||
xmlNsListDumpOutputCtxt(ctxt, cur->doc, cur->nsDef);
|
||||
xmlNsListDumpOutputCtxt(ctxt, cur->nsDef);
|
||||
if ((xmlStrEqual(cur->name, BAD_CAST "html") &&
|
||||
(cur->ns == NULL) && (cur->nsDef == NULL))) {
|
||||
/*
|
||||
@@ -1870,7 +1873,11 @@ xhtmlNodeDumpOutput(xmlSaveCtxtPtr ctxt, xmlNodePtr cur) {
|
||||
break;
|
||||
if ((cur->name == xmlStringText) ||
|
||||
(cur->name != xmlStringTextNoenc)) {
|
||||
xmlOutputBufferWriteEscape(buf, cur->content, ctxt->escape);
|
||||
if (ctxt->escape)
|
||||
xmlOutputBufferWriteEscape(buf, cur->content,
|
||||
ctxt->escape);
|
||||
else
|
||||
xmlSaveWriteText(ctxt, cur->content, /* flags */ 0);
|
||||
} else {
|
||||
/*
|
||||
* Disable escaping, needed for XSLT
|
||||
@@ -2313,88 +2320,11 @@ void
|
||||
xmlBufAttrSerializeTxtContent(xmlOutputBufferPtr buf, xmlDocPtr doc,
|
||||
const xmlChar *string)
|
||||
{
|
||||
const xmlChar *base, *cur;
|
||||
int flags = XML_ESCAPE_ATTR;
|
||||
|
||||
if (string == NULL)
|
||||
return;
|
||||
base = cur = string;
|
||||
while (*cur != 0) {
|
||||
if (*cur == '\n') {
|
||||
if (base != cur)
|
||||
xmlOutputBufferWrite(buf, cur - base, (const char *) base);
|
||||
xmlOutputBufferWrite(buf, 5, " ");
|
||||
cur++;
|
||||
base = cur;
|
||||
} else if (*cur == '\r') {
|
||||
if (base != cur)
|
||||
xmlOutputBufferWrite(buf, cur - base, (const char *) base);
|
||||
xmlOutputBufferWrite(buf, 5, " ");
|
||||
cur++;
|
||||
base = cur;
|
||||
} else if (*cur == '\t') {
|
||||
if (base != cur)
|
||||
xmlOutputBufferWrite(buf, cur - base, (const char *) base);
|
||||
xmlOutputBufferWrite(buf, 4, "	");
|
||||
cur++;
|
||||
base = cur;
|
||||
} else if (*cur == '"') {
|
||||
if (base != cur)
|
||||
xmlOutputBufferWrite(buf, cur - base, (const char *) base);
|
||||
xmlOutputBufferWrite(buf, 6, """);
|
||||
cur++;
|
||||
base = cur;
|
||||
} else if (*cur == '<') {
|
||||
if (base != cur)
|
||||
xmlOutputBufferWrite(buf, cur - base, (const char *) base);
|
||||
xmlOutputBufferWrite(buf, 4, "<");
|
||||
cur++;
|
||||
base = cur;
|
||||
} else if (*cur == '>') {
|
||||
if (base != cur)
|
||||
xmlOutputBufferWrite(buf, cur - base, (const char *) base);
|
||||
xmlOutputBufferWrite(buf, 4, ">");
|
||||
cur++;
|
||||
base = cur;
|
||||
} else if (*cur == '&') {
|
||||
if (base != cur)
|
||||
xmlOutputBufferWrite(buf, cur - base, (const char *) base);
|
||||
xmlOutputBufferWrite(buf, 5, "&");
|
||||
cur++;
|
||||
base = cur;
|
||||
} else if ((*cur >= 0x80) && (cur[1] != 0) &&
|
||||
((doc == NULL) || (doc->encoding == NULL))) {
|
||||
/*
|
||||
* We assume we have UTF-8 content.
|
||||
*/
|
||||
unsigned char tmp[12];
|
||||
int val = 0, l = 4;
|
||||
|
||||
if (base != cur)
|
||||
xmlOutputBufferWrite(buf, cur - base, (const char *) base);
|
||||
|
||||
val = xmlGetUTF8Char(cur, &l);
|
||||
if (val < 0) {
|
||||
val = 0xFFFD;
|
||||
cur++;
|
||||
} else {
|
||||
if (!IS_CHAR(val))
|
||||
val = 0xFFFD;
|
||||
cur += l;
|
||||
}
|
||||
|
||||
/*
|
||||
* We could do multiple things here. Just save
|
||||
* as a char ref
|
||||
*/
|
||||
xmlSerializeHexCharRef(tmp, val);
|
||||
xmlOutputBufferWriteString(buf, (const char *) tmp);
|
||||
base = cur;
|
||||
} else {
|
||||
cur++;
|
||||
}
|
||||
}
|
||||
if (base != cur)
|
||||
xmlOutputBufferWrite(buf, cur - base, (const char *) base);
|
||||
if ((doc == NULL) || (doc->encoding == NULL))
|
||||
flags |= XML_ESCAPE_NON_ASCII;
|
||||
xmlSerializeText(buf, string, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2799,7 +2729,6 @@ xmlDocFormatDump(FILE *f, xmlDocPtr cur, int format) {
|
||||
res = xmlOpenCharEncodingHandler(encoding, /* output */ 1, &handler);
|
||||
if (res != XML_ERR_OK) {
|
||||
xmlFree((char *) cur->encoding);
|
||||
cur->encoding = NULL;
|
||||
encoding = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user