- Large resync between W3C and Gnome tree
- configure.in: 2.1.0 prerelease
- example/Makefile.am example/gjobread.c tree.h: work on
libxml1 libxml2 convergence.
- nanoftp, nanohttp.c: fixed stalled connections probs
- HTMLtree.c SAX.c : support for attribute without values in
HTML for andersca
- valid.c: Fixed most validation + namespace problems
- HTMLparser.c: start document callback for andersca
- debugXML.c xpath.c: lots of XPath fixups from Picdar Technology
- parser.h, SAX.c: serious speed improvement for large
CDATA blocks
- encoding.[ch] xmlIO.[ch]: Improved seriously saving to
different encoding
- config.h.in parser.c xmllint.c: added xmlCheckVersion()
and the LIBXML_TEST_VERSION macro
Daniel
diff --git a/ChangeLog b/ChangeLog
index cc6b43c..37094c4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+Wed Jun 28 23:10:26 MEST 2000 Daniel Veillard <Daniel.Veillard@w3.org>
+
+ * configure.in: 2.1.0 prerelease
+ * Large resync between W3C and Gnome tree
+ * nanoftp, nanohttp.c: fixed stalled connections probs
+ * HTMLtree.c SAX.c : support for attribute without values in
+ HTML for andersca
+ * valid.c: Fixed most validation + namespace problems
+ * HTMLparser.c: start document callback for andersca
+ * debugXML.c xpath.c: lots of XPath fixups from Picdar Technology
+ * parser.h, SAX.c: serious speed improvement for large
+ CDATA blocks
+ * encoding.[ch] xmlIO.[ch]: Improved seriously saving to
+ different encoding
+ * example/Makefile.am example/gjobread.c tree.h: work on
+ libxml1 libxml2 convergence.
+ * config.h.in parser.c xmllint.c: added xmlCheckVersion()
+ and the LIBXML_TEST_VERSION macro
+
Fri Jun 23 22:26:07 CEST 2000 Daniel Veillard <Daniel.Veillard@w3.org>
* doc/xml.html: various patches and improvements typo fixed by
diff --git a/HTMLparser.c b/HTMLparser.c
index 5c1cfae..cfd65bd 100644
--- a/HTMLparser.c
+++ b/HTMLparser.c
@@ -388,6 +388,7 @@
NULL
};
+
static char** htmlStartCloseIndex[100];
static int htmlStartCloseIndexinitialized = 0;
@@ -604,6 +605,54 @@
}
}
+/**
+ * htmlCheckImplied:
+ * @ctxt: an HTML parser context
+ * @new: The new tag name
+ *
+ * The HTmL DtD allows a tag to exists only implicitely
+ * called when a new tag has been detected and generates the
+ * appropriates implicit tags if missing
+ */
+void
+htmlCheckImplied(htmlParserCtxtPtr ctxt, const xmlChar *new) {
+ if (!strcmp(new, "html"))
+ return;
+ if (ctxt->nameNr <= 0) {
+#ifdef DEBUG
+ fprintf(stderr,"Implied element html: pushed html\n");
+#endif
+ htmlnamePush(ctxt, xmlStrdup(BAD_CAST"html"));
+ if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
+ ctxt->sax->startElement(ctxt->userData, BAD_CAST"html", NULL);
+ }
+ if ((!strcmp(new, "body")) || (!strcmp(new, "head")))
+ return;
+ if (ctxt->nameNr <= 1) {
+ if ((!strcmp(new, "script")) || (!strcmp(new, "style")) ||
+ (!strcmp(new, "meta")) || (!strcmp(new, "link")) ||
+ (!strcmp(new, "title")) || (!strcmp(new, "base"))) {
+ /*
+ * dropped OBJECT ... i you put it first BODY will be
+ * assumed !
+ */
+#ifdef DEBUG
+ fprintf(stderr,"Implied element head: pushed head\n");
+#endif
+ htmlnamePush(ctxt, xmlStrdup(BAD_CAST"head"));
+ if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
+ ctxt->sax->startElement(ctxt->userData, BAD_CAST"head", NULL);
+ } else {
+#ifdef DEBUG
+ fprintf(stderr,"Implied element body: pushed body\n");
+#endif
+ htmlnamePush(ctxt, xmlStrdup(BAD_CAST"body"));
+ if ((ctxt->sax != NULL) && (ctxt->sax->startElement != NULL))
+ ctxt->sax->startElement(ctxt->userData, BAD_CAST"body", NULL);
+ }
+ }
+}
+
/************************************************************************
* *
* The list of HTML predefined entities *
@@ -1322,6 +1371,7 @@
BAD_CAST "http://www.w3.org/TR/REC-html40/loose.dtd");
else
xmlCreateIntSubset(cur, BAD_CAST "HTML", ExternalID, URI);
+ cur->doc = cur;
cur->name = NULL;
cur->children = NULL;
cur->extSubset = NULL;
@@ -2161,11 +2211,12 @@
NEXT;
SKIP_BLANKS;
val = htmlParseAttValue(ctxt);
+ /******
} else {
- /* TODO : some attribute must have values, some may not */
+ * TODO : some attribute must have values, some may not
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->warning(ctxt->userData,
- "No value for attribute %s\n", name);
+ "No value for attribute %s\n", name); */
}
*value = val;
@@ -2220,6 +2271,11 @@
htmlAutoClose(ctxt, name);
/*
+ * Check for implied HTML elements.
+ */
+ htmlCheckImplied(ctxt, name);
+
+ /*
* Now parse the attributes, it ends up with the ending
*
* (S Attribute)* S?
@@ -2759,6 +2815,10 @@
ctxt->wellFormed = 0;
}
+ if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
+ ctxt->sax->startDocument(ctxt->userData);
+
+
/*
* Parse possible comments before any content
*/
diff --git a/HTMLtree.c b/HTMLtree.c
index e4a955c..24a90ba 100644
--- a/HTMLtree.c
+++ b/HTMLtree.c
@@ -84,13 +84,15 @@
}
xmlBufferWriteChar(buf, " ");
xmlBufferWriteCHAR(buf, cur->name);
- value = xmlNodeListGetString(doc, cur->children, 0);
- if (value) {
- xmlBufferWriteChar(buf, "=");
- xmlBufferWriteQuotedString(buf, value);
- xmlFree(value);
- } else {
- xmlBufferWriteChar(buf, "=\"\"");
+ if (cur->children != NULL) {
+ value = xmlNodeListGetString(doc, cur->children, 0);
+ if (value) {
+ xmlBufferWriteChar(buf, "=");
+ xmlBufferWriteQuotedString(buf, value);
+ xmlFree(value);
+ } else {
+ xmlBufferWriteChar(buf, "=\"\"");
+ }
}
}
diff --git a/Makefile.am b/Makefile.am
index 74624da..3f4b003 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -86,12 +86,14 @@
check-local: tests
-install-data: $(srcdir)/libxml
-
$(srcdir)/libxml:
-$(RM) $(srcdir)/libxml
ln -s $(srcdir)/. $(srcdir)/libxml
+install-data: $(srcdir)/libxml
+
+$(libxml_la_SOURCES): $(srcdir)/libxml
+
testall : tests SVGtests SAXtests XPathtests XMLenttests
tests: XMLtests HTMLtests Validtests
diff --git a/README b/README
index 2746bfe..cad4d77 100644
--- a/README
+++ b/README
@@ -4,6 +4,8 @@
Full documentation is available on-line at
http://xmlsoft.org/
+This code is released under the LGPL and the W3C IPR
+
A mailing-list is available, to subscribe:
echo "subscribe xml" | mail majordomo@rufus.w3.org
diff --git a/SAX.c b/SAX.c
index dace305..ee3af39 100644
--- a/SAX.c
+++ b/SAX.c
@@ -24,6 +24,7 @@
#include <libxml/debugXML.h>
#include <libxml/xmlIO.h>
#include <libxml/SAX.h>
+#include <libxml/uri.h>
/* #define DEBUG_SAX */
/* #define DEBUG_SAX_TREE */
@@ -193,6 +194,7 @@
int oldwellFormed;
xmlParserInputPtr input = NULL;
xmlCharEncoding enc;
+ xmlCharEncoding oldcharset;
/*
* Ask the Entity resolver to load the damn thing
@@ -214,6 +216,7 @@
oldinputMax = ctxt->inputMax;
oldinputTab = ctxt->inputTab;
oldwellFormed = ctxt->wellFormed;
+ oldcharset = ctxt->charset;
ctxt->inputTab = (xmlParserInputPtr *)
xmlMalloc(5 * sizeof(xmlParserInputPtr));
@@ -227,6 +230,7 @@
ctxt->inputNr = oldinputNr;
ctxt->inputMax = oldinputMax;
ctxt->inputTab = oldinputTab;
+ ctxt->charset = oldcharset;
return;
}
ctxt->inputNr = 0;
@@ -269,6 +273,7 @@
ctxt->inputNr = oldinputNr;
ctxt->inputMax = oldinputMax;
ctxt->inputTab = oldinputTab;
+ ctxt->charset = oldcharset;
/* ctxt->wellFormed = oldwellFormed; */
}
}
@@ -604,6 +609,14 @@
ctxt->myDoc->encoding = ctxt->encoding;
ctxt->encoding = NULL;
}
+ if ((ctxt->inputTab[0]->encoding != NULL) && (ctxt->myDoc != NULL) &&
+ (ctxt->myDoc->encoding == NULL)) {
+ ctxt->myDoc->encoding = xmlStrdup(ctxt->inputTab[0]->encoding);
+ }
+ if ((ctxt->charset != XML_CHAR_ENCODING_NONE) && (ctxt->myDoc != NULL) &&
+ (ctxt->myDoc->charset == XML_CHAR_ENCODING_NONE)) {
+ ctxt->myDoc->charset = ctxt->charset;
+ }
}
/**
@@ -640,7 +653,10 @@
/*
* Do the last stave of the attribute normalization
*/
- nval = xmlValidNormalizeAttributeValue(ctxt->myDoc,
+ if (ctxt->html)
+ nval = NULL;
+ else
+ nval = xmlValidNormalizeAttributeValue(ctxt->myDoc,
ctxt->node, fullname, value);
if (nval != NULL)
value = nval;
@@ -648,9 +664,25 @@
/*
* Check whether it's a namespace definition
*/
- if ((ns == NULL) &&
+ if ((!ctxt->html) && (ns == NULL) &&
(name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
(name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
+ xmlURIPtr uri;
+
+ uri = xmlParseURI((const char *)value);
+ if (uri == NULL) {
+ if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+ ctxt->sax->warning(ctxt->userData,
+ "nmlns: %s not a valid URI\n", value);
+ } else {
+ if (uri->scheme == NULL) {
+ if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
+ ctxt->sax->warning(ctxt->userData,
+ "nmlns: URI %s is not absolute\n", value);
+ }
+ xmlFreeURI(uri);
+ }
+
/* a default namespace definition */
xmlNewNs(ctxt->node, value, NULL);
if (name != NULL)
@@ -659,7 +691,8 @@
xmlFree(nval);
return;
}
- if ((ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
+ if ((!ctxt->html) &&
+ (ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
(ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
/*
* Validate also for namespace decls, they are attributes from
@@ -701,7 +734,7 @@
ret->last = tmp;
tmp = tmp->next;
}
- } else {
+ } else if (value != NULL) {
ret->children = xmlNewDocText(ctxt->myDoc, value);
ret->last = ret->children;
if (ret->children != NULL)
@@ -709,7 +742,7 @@
}
}
- if (ctxt->validate && ctxt->wellFormed &&
+ if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
ctxt->myDoc && ctxt->myDoc->intSubset) {
/*
@@ -817,6 +850,7 @@
} else if (parent == NULL) {
parent = ctxt->myDoc->children;
}
+ ctxt->nodemem = -1;
/*
* We are parsing a new node.
@@ -845,46 +879,20 @@
}
/*
- * If it's the Document root, finish the Dtd validation and
- * check the document root element for validity
- */
- if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
- ctxt->valid &= xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
- ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
- ctxt->vctxt.finishDtd = 1;
- }
- /*
* process all the attributes whose name start with "xml"
*/
if (atts != NULL) {
i = 0;
att = atts[i++];
value = atts[i++];
- while ((att != NULL) && (value != NULL)) {
- if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
- attribute(ctxt, att, value);
+ if (!ctxt->html) {
+ while ((att != NULL) && (value != NULL)) {
+ if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l'))
+ attribute(ctxt, att, value);
- att = atts[i++];
- value = atts[i++];
- }
- }
-
- /*
- * process all the other attributes
- */
- if (atts != NULL) {
- i = 0;
- att = atts[i++];
- value = atts[i++];
- while ((att != NULL) && (value != NULL)) {
- if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
- attribute(ctxt, att, value);
-
- /*
- * Next ones
- */
- att = atts[i++];
- value = atts[i++];
+ att = atts[i++];
+ value = atts[i++];
+ }
}
}
@@ -897,6 +905,43 @@
ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
xmlSetNs(ret, ns);
+ /*
+ * process all the other attributes
+ */
+ if (atts != NULL) {
+ i = 0;
+ att = atts[i++];
+ value = atts[i++];
+ if (ctxt->html) {
+ while (att != NULL) {
+ attribute(ctxt, att, value);
+ att = atts[i++];
+ value = atts[i++];
+ }
+ } else {
+ while ((att != NULL) && (value != NULL)) {
+ if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l'))
+ attribute(ctxt, att, value);
+
+ /*
+ * Next ones
+ */
+ att = atts[i++];
+ value = atts[i++];
+ }
+ }
+ }
+
+ /*
+ * If it's the Document root, finish the Dtd validation and
+ * check the document root element for validity
+ */
+ if ((ctxt->validate) && (ctxt->vctxt.finishDtd == 0)) {
+ ctxt->valid &= xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
+ ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
+ ctxt->vctxt.finishDtd = 1;
+ }
+
if (prefix != NULL)
xmlFree(prefix);
if (name != NULL)
@@ -932,6 +977,7 @@
node_info.node = cur;
xmlParserAddNodeInfo(ctxt, &node_info);
}
+ ctxt->nodemem = -1;
if (ctxt->validate && ctxt->wellFormed &&
ctxt->myDoc && ctxt->myDoc->intSubset)
@@ -1008,14 +1054,62 @@
#ifdef DEBUG_SAX_TREE
fprintf(stderr, "add chars to %s \n", ctxt->node->name);
#endif
- if (lastChild == NULL)
+
+ /*
+ * Here we needed an accelerator mechanism in case of very large
+ * elements. Use an attribute in the structure !!!
+ */
+ if (lastChild == NULL) {
+ /* first node, first time */
xmlNodeAddContentLen(ctxt->node, ch, len);
- else {
- if (xmlNodeIsText(lastChild))
+#ifndef XML_USE_BUFFER_CONTENT
+ if (ctxt->node->children != NULL) {
+ ctxt->nodelen = len;
+ ctxt->nodemem = len + 1;
+ }
+#endif
+ } else {
+ if (xmlNodeIsText(lastChild)) {
+#ifndef XML_USE_BUFFER_CONTENT
+ /*
+ * The whole point of maintaining nodelen and nodemem,
+ * xmlTextConcat is too costly, i.e. compute lenght,
+ * reallocate a new buffer, move data, append ch. Here
+ * We try to minimaze realloc() uses and avoid copying
+ * and recomputing lenght over and over.
+ */
+ if (ctxt->nodelen + len >= ctxt->nodemem) {
+ xmlChar *newbuf;
+ int size;
+
+ size = ctxt->nodemem + len;
+ size *= 2;
+ newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
+ if (newbuf == NULL) {
+ if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+ ctxt->sax->error(ctxt->userData,
+ "SAX.characters(): out of memory\n");
+ return;
+ }
+ ctxt->nodemem = size;
+ lastChild->content = newbuf;
+ }
+ memcpy(&lastChild->content[ctxt->nodelen], ch, len);
+ ctxt->nodelen += len;
+ lastChild->content[ctxt->nodelen] = 0;
+#else
xmlTextConcat(lastChild, ch, len);
- else {
+#endif
+ } else {
+ /* Mixed content, first time */
lastChild = xmlNewTextLen(ch, len);
xmlAddChild(ctxt->node, lastChild);
+#ifndef XML_USE_BUFFER_CONTENT
+ if (ctxt->node->children != NULL) {
+ ctxt->nodelen = len;
+ ctxt->nodemem = len + 1;
+ }
+#endif
}
}
}
diff --git a/TODO b/TODO
index 2b4ae5e..8545e1a 100644
--- a/TODO
+++ b/TODO
@@ -6,14 +6,17 @@
TODO:
=====
-- xmlSwitchToEncoding() need a rewrite for correct handling of conversion
- error code conditions.
+- If the internal encoding is not UTF8 saving to a given encoding doesn't
+ work
+- problem when parsing hrefs with & with the HTML parser (IRC ac)
- DOM needs
xmlAttrPtr xmlNewDocProp(xmlDocPtr doc, const xmlChar *name, const xmlChar *value)
int xmlPruneProp(xmlNodePtr node, xmlAtttrPtr attr);
+- General checking of DTD validation in presence of namespaces ... hairy
+ mostly done
- Fix DTD + namespace validity problem
"Not valid: root and DtD name do not match 'ROOT' and 'prefix:ROOT'"
-- add support for the trick from Henry conf/sun/valid/empty.xml
+ mostly done
- Correct standalone checking/emitting (hard)
2.9 Standalone Document Declaration
- Better checking of external parsed entities TAG 1234
@@ -24,9 +27,10 @@
- Handle undefined namespaces in entity contents better ... at least
issue a warning
- Issue warning when using non-absolute namespaces URI.
-- General checking of DTD validation in presence of namespaces ... hairy
- fix --disable-corba configure switch handling, and use XML_WITHOUT_CORBA
not WITHOUT_CORBA flag
+- the html parser should add <head> and <body> if they don't exist
+- Command to force the parser to stop parsing and ignore the rest of the file.
TODO:
=====
@@ -92,6 +96,9 @@
Done:
=====
+- support for HTML empty attributes like <hr noshade>
+- plugged iconv() in for support of a large set of encodings.
+- xmlSwitchToEncoding() rewrite done
- URI checkings (no fragments) rfc2396.txt
- Added a clean mechanism for overload or added input methods:
xmlRegisterInputCallbacks()
diff --git a/debugXML.c b/debugXML.c
index 6a271b8..88158d8 100644
--- a/debugXML.c
+++ b/debugXML.c
@@ -1326,7 +1326,7 @@
if ((node->type == XML_DOCUMENT_NODE) ||
(node->type == XML_HTML_DOCUMENT_NODE)) {
node = ((xmlDocPtr) node)->children;
- } else if (node->children != NULL) {
+ } else if ((node->children != NULL) && (node->type != XML_ENTITY_REF_NODE)) {
/* deep first */
node = node->children;
indent++;
diff --git a/doc/html/gnome-xml-tree.html b/doc/html/gnome-xml-tree.html
index e334988..c1a4e98 100644
--- a/doc/html/gnome-xml-tree.html
+++ b/doc/html/gnome-xml-tree.html
@@ -8137,1314 +8137,4 @@
>xmlChar</A
>* xmlNodeGetContent (<A
HREF="gnome-xml-tree.html#XMLNODEPTR"
->xmlNodePtr</A
-> cur);</PRE
-></TD
-></TR
-></TABLE
-><P
->Read the value of a node, this can be either the text carried
-directly by this node if it's a TEXT node or the aggregate string
-of the values carried by this node child's (TEXT and ENTITY_REF).
-Entity references are substitued.</P
-><P
-></P
-><DIV
-CLASS="INFORMALTABLE"
-><P
-></P
-><TABLE
-BORDER="0"
-WIDTH="100%"
-BGCOLOR="#FFD0D0"
-CELLSPACING="0"
-CELLPADDING="4"
-CLASS="CALSTABLE"
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->cur</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><I
-CLASS="EMPHASIS"
->Returns</I
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-></TABLE
-><P
-></P
-></DIV
-></DIV
-><HR><DIV
-CLASS="REFSECT2"
-><A
-NAME="AEN4780"
-></A
-><H3
-><A
-NAME="XMLNODEGETLANG"
-></A
->xmlNodeGetLang ()</H3
-><TABLE
-BORDER="0"
-BGCOLOR="#D6E8FF"
-WIDTH="100%"
-CELLPADDING="6"
-><TR
-><TD
-><PRE
-CLASS="PROGRAMLISTING"
-><A
-HREF="gnome-xml-tree.html#XMLCHAR"
->xmlChar</A
->* xmlNodeGetLang (<A
-HREF="gnome-xml-tree.html#XMLNODEPTR"
->xmlNodePtr</A
-> cur);</PRE
-></TD
-></TR
-></TABLE
-><P
->Searches the language of a node, i.e. the values of the xml:lang
-attribute or the one carried by the nearest ancestor.</P
-><P
-></P
-><DIV
-CLASS="INFORMALTABLE"
-><P
-></P
-><TABLE
-BORDER="0"
-WIDTH="100%"
-BGCOLOR="#FFD0D0"
-CELLSPACING="0"
-CELLPADDING="4"
-CLASS="CALSTABLE"
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->cur</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><I
-CLASS="EMPHASIS"
->Returns</I
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-></TABLE
-><P
-></P
-></DIV
-></DIV
-><HR><DIV
-CLASS="REFSECT2"
-><A
-NAME="AEN4801"
-></A
-><H3
-><A
-NAME="XMLNODESETLANG"
-></A
->xmlNodeSetLang ()</H3
-><TABLE
-BORDER="0"
-BGCOLOR="#D6E8FF"
-WIDTH="100%"
-CELLPADDING="6"
-><TR
-><TD
-><PRE
-CLASS="PROGRAMLISTING"
->void xmlNodeSetLang (<A
-HREF="gnome-xml-tree.html#XMLNODEPTR"
->xmlNodePtr</A
-> cur,
- const <A
-HREF="gnome-xml-tree.html#XMLCHAR"
->xmlChar</A
-> *lang);</PRE
-></TD
-></TR
-></TABLE
-><P
->Set the language of a node, i.e. the values of the xml:lang
-attribute.</P
-><P
-></P
-><DIV
-CLASS="INFORMALTABLE"
-><P
-></P
-><TABLE
-BORDER="0"
-WIDTH="100%"
-BGCOLOR="#FFD0D0"
-CELLSPACING="0"
-CELLPADDING="4"
-CLASS="CALSTABLE"
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->cur</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->lang</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-></TABLE
-><P
-></P
-></DIV
-></DIV
-><HR><DIV
-CLASS="REFSECT2"
-><A
-NAME="AEN4822"
-></A
-><H3
-><A
-NAME="XMLREMOVEPROP"
-></A
->xmlRemoveProp ()</H3
-><TABLE
-BORDER="0"
-BGCOLOR="#D6E8FF"
-WIDTH="100%"
-CELLPADDING="6"
-><TR
-><TD
-><PRE
-CLASS="PROGRAMLISTING"
->int xmlRemoveProp (<A
-HREF="gnome-xml-tree.html#XMLATTRPTR"
->xmlAttrPtr</A
-> attr);</PRE
-></TD
-></TR
-></TABLE
-><P
->Unlink and free one attribute, all the content is freed too
-Note this doesn't work for namespace definition attributes</P
-><P
-></P
-><DIV
-CLASS="INFORMALTABLE"
-><P
-></P
-><TABLE
-BORDER="0"
-WIDTH="100%"
-BGCOLOR="#FFD0D0"
-CELLSPACING="0"
-CELLPADDING="4"
-CLASS="CALSTABLE"
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->attr</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><I
-CLASS="EMPHASIS"
->Returns</I
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-></TABLE
-><P
-></P
-></DIV
-></DIV
-><HR><DIV
-CLASS="REFSECT2"
-><A
-NAME="AEN4842"
-></A
-><H3
-><A
-NAME="XMLREMOVENODE"
-></A
->xmlRemoveNode ()</H3
-><TABLE
-BORDER="0"
-BGCOLOR="#D6E8FF"
-WIDTH="100%"
-CELLPADDING="6"
-><TR
-><TD
-><PRE
-CLASS="PROGRAMLISTING"
->int xmlRemoveNode (<A
-HREF="gnome-xml-tree.html#XMLNODEPTR"
->xmlNodePtr</A
-> node);</PRE
-></TD
-></TR
-></TABLE
-><P
-></P
-><DIV
-CLASS="INFORMALTABLE"
-><P
-></P
-><TABLE
-BORDER="0"
-WIDTH="100%"
-BGCOLOR="#FFD0D0"
-CELLSPACING="0"
-CELLPADDING="4"
-CLASS="CALSTABLE"
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->node</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><I
-CLASS="EMPHASIS"
->Returns</I
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-></TABLE
-><P
-></P
-></DIV
-></DIV
-><HR><DIV
-CLASS="REFSECT2"
-><A
-NAME="AEN4861"
-></A
-><H3
-><A
-NAME="XMLBUFFERWRITECHAR"
-></A
->xmlBufferWriteCHAR ()</H3
-><TABLE
-BORDER="0"
-BGCOLOR="#D6E8FF"
-WIDTH="100%"
-CELLPADDING="6"
-><TR
-><TD
-><PRE
-CLASS="PROGRAMLISTING"
->void xmlBufferWriteCHAR (<A
-HREF="gnome-xml-tree.html#XMLBUFFERPTR"
->xmlBufferPtr</A
-> buf,
- const <A
-HREF="gnome-xml-tree.html#XMLCHAR"
->xmlChar</A
-> *string);</PRE
-></TD
-></TR
-></TABLE
-><P
->routine which manage and grows an output buffer. This one add
-xmlChars at the end of the buffer.</P
-><P
-></P
-><DIV
-CLASS="INFORMALTABLE"
-><P
-></P
-><TABLE
-BORDER="0"
-WIDTH="100%"
-BGCOLOR="#FFD0D0"
-CELLSPACING="0"
-CELLPADDING="4"
-CLASS="CALSTABLE"
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->buf</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->string</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-></TABLE
-><P
-></P
-></DIV
-></DIV
-><HR><DIV
-CLASS="REFSECT2"
-><A
-NAME="AEN4882"
-></A
-><H3
-><A
-NAME="XMLBUFFERWRITECHAR"
-></A
->xmlBufferWriteChar ()</H3
-><TABLE
-BORDER="0"
-BGCOLOR="#D6E8FF"
-WIDTH="100%"
-CELLPADDING="6"
-><TR
-><TD
-><PRE
-CLASS="PROGRAMLISTING"
->void xmlBufferWriteChar (<A
-HREF="gnome-xml-tree.html#XMLBUFFERPTR"
->xmlBufferPtr</A
-> buf,
- const char *string);</PRE
-></TD
-></TR
-></TABLE
-><P
->routine which manage and grows an output buffer. This one add
-C chars at the end of the array.</P
-><P
-></P
-><DIV
-CLASS="INFORMALTABLE"
-><P
-></P
-><TABLE
-BORDER="0"
-WIDTH="100%"
-BGCOLOR="#FFD0D0"
-CELLSPACING="0"
-CELLPADDING="4"
-CLASS="CALSTABLE"
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->buf</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->string</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-></TABLE
-><P
-></P
-></DIV
-></DIV
-><HR><DIV
-CLASS="REFSECT2"
-><A
-NAME="AEN4902"
-></A
-><H3
-><A
-NAME="XMLBUFFERWRITEQUOTEDSTRING"
-></A
->xmlBufferWriteQuotedString ()</H3
-><TABLE
-BORDER="0"
-BGCOLOR="#D6E8FF"
-WIDTH="100%"
-CELLPADDING="6"
-><TR
-><TD
-><PRE
-CLASS="PROGRAMLISTING"
->void xmlBufferWriteQuotedString (<A
-HREF="gnome-xml-tree.html#XMLBUFFERPTR"
->xmlBufferPtr</A
-> buf,
- const <A
-HREF="gnome-xml-tree.html#XMLCHAR"
->xmlChar</A
-> *string);</PRE
-></TD
-></TR
-></TABLE
-><P
->routine which manage and grows an output buffer. This one writes
-a quoted or double quoted xmlChar string, checking first if it holds
-quote or double-quotes internally</P
-><P
-></P
-><DIV
-CLASS="INFORMALTABLE"
-><P
-></P
-><TABLE
-BORDER="0"
-WIDTH="100%"
-BGCOLOR="#FFD0D0"
-CELLSPACING="0"
-CELLPADDING="4"
-CLASS="CALSTABLE"
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->buf</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->string</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-></TABLE
-><P
-></P
-></DIV
-></DIV
-><HR><DIV
-CLASS="REFSECT2"
-><A
-NAME="AEN4923"
-></A
-><H3
-><A
-NAME="XMLDOCDUMPMEMORY"
-></A
->xmlDocDumpMemory ()</H3
-><TABLE
-BORDER="0"
-BGCOLOR="#D6E8FF"
-WIDTH="100%"
-CELLPADDING="6"
-><TR
-><TD
-><PRE
-CLASS="PROGRAMLISTING"
->void xmlDocDumpMemory (<A
-HREF="gnome-xml-tree.html#XMLDOCPTR"
->xmlDocPtr</A
-> cur,
- <A
-HREF="gnome-xml-tree.html#XMLCHAR"
->xmlChar</A
-> **mem,
- int *size);</PRE
-></TD
-></TR
-></TABLE
-><P
->Dump an XML document in memory and return the xmlChar * and it's size.
-It's up to the caller to free the memory.</P
-><P
-></P
-><DIV
-CLASS="INFORMALTABLE"
-><P
-></P
-><TABLE
-BORDER="0"
-WIDTH="100%"
-BGCOLOR="#FFD0D0"
-CELLSPACING="0"
-CELLPADDING="4"
-CLASS="CALSTABLE"
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->cur</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->mem</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->size</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-></TABLE
-><P
-></P
-></DIV
-></DIV
-><HR><DIV
-CLASS="REFSECT2"
-><A
-NAME="AEN4948"
-></A
-><H3
-><A
-NAME="XMLDOCDUMP"
-></A
->xmlDocDump ()</H3
-><TABLE
-BORDER="0"
-BGCOLOR="#D6E8FF"
-WIDTH="100%"
-CELLPADDING="6"
-><TR
-><TD
-><PRE
-CLASS="PROGRAMLISTING"
->void xmlDocDump (<GTKDOCLINK
-HREF="FILE"
->FILE</GTKDOCLINK
-> *f,
- <A
-HREF="gnome-xml-tree.html#XMLDOCPTR"
->xmlDocPtr</A
-> cur);</PRE
-></TD
-></TR
-></TABLE
-><P
->Dump an XML document to an open FILE.</P
-><P
-></P
-><DIV
-CLASS="INFORMALTABLE"
-><P
-></P
-><TABLE
-BORDER="0"
-WIDTH="100%"
-BGCOLOR="#FFD0D0"
-CELLSPACING="0"
-CELLPADDING="4"
-CLASS="CALSTABLE"
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->f</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->cur</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-></TABLE
-><P
-></P
-></DIV
-></DIV
-><HR><DIV
-CLASS="REFSECT2"
-><A
-NAME="AEN4969"
-></A
-><H3
-><A
-NAME="XMLSAVEFILE"
-></A
->xmlSaveFile ()</H3
-><TABLE
-BORDER="0"
-BGCOLOR="#D6E8FF"
-WIDTH="100%"
-CELLPADDING="6"
-><TR
-><TD
-><PRE
-CLASS="PROGRAMLISTING"
->int xmlSaveFile (const char *filename,
- <A
-HREF="gnome-xml-tree.html#XMLDOCPTR"
->xmlDocPtr</A
-> cur);</PRE
-></TD
-></TR
-></TABLE
-><P
->Dump an XML document to a file. Will use compression if
-compiled in and enabled. If <TT
-CLASS="PARAMETER"
-><I
->filename</I
-></TT
-> is "-" the stdout file is
-used.</P
-><P
-></P
-><DIV
-CLASS="INFORMALTABLE"
-><P
-></P
-><TABLE
-BORDER="0"
-WIDTH="100%"
-BGCOLOR="#FFD0D0"
-CELLSPACING="0"
-CELLPADDING="4"
-CLASS="CALSTABLE"
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->filename</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->cur</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><I
-CLASS="EMPHASIS"
->Returns</I
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-></TABLE
-><P
-></P
-></DIV
-></DIV
-><HR><DIV
-CLASS="REFSECT2"
-><A
-NAME="AEN4994"
-></A
-><H3
-><A
-NAME="XMLGETDOCCOMPRESSMODE"
-></A
->xmlGetDocCompressMode ()</H3
-><TABLE
-BORDER="0"
-BGCOLOR="#D6E8FF"
-WIDTH="100%"
-CELLPADDING="6"
-><TR
-><TD
-><PRE
-CLASS="PROGRAMLISTING"
->int xmlGetDocCompressMode (<A
-HREF="gnome-xml-tree.html#XMLDOCPTR"
->xmlDocPtr</A
-> doc);</PRE
-></TD
-></TR
-></TABLE
-><P
->get the compression ratio for a document, ZLIB based</P
-><P
-></P
-><DIV
-CLASS="INFORMALTABLE"
-><P
-></P
-><TABLE
-BORDER="0"
-WIDTH="100%"
-BGCOLOR="#FFD0D0"
-CELLSPACING="0"
-CELLPADDING="4"
-CLASS="CALSTABLE"
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->doc</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><I
-CLASS="EMPHASIS"
->Returns</I
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-></TABLE
-><P
-></P
-></DIV
-></DIV
-><HR><DIV
-CLASS="REFSECT2"
-><A
-NAME="AEN5014"
-></A
-><H3
-><A
-NAME="XMLSETDOCCOMPRESSMODE"
-></A
->xmlSetDocCompressMode ()</H3
-><TABLE
-BORDER="0"
-BGCOLOR="#D6E8FF"
-WIDTH="100%"
-CELLPADDING="6"
-><TR
-><TD
-><PRE
-CLASS="PROGRAMLISTING"
->void xmlSetDocCompressMode (<A
-HREF="gnome-xml-tree.html#XMLDOCPTR"
->xmlDocPtr</A
-> doc,
- int mode);</PRE
-></TD
-></TR
-></TABLE
-><P
->set the compression ratio for a document, ZLIB based
-Correct values: 0 (uncompressed) to 9 (max compression)</P
-><P
-></P
-><DIV
-CLASS="INFORMALTABLE"
-><P
-></P
-><TABLE
-BORDER="0"
-WIDTH="100%"
-BGCOLOR="#FFD0D0"
-CELLSPACING="0"
-CELLPADDING="4"
-CLASS="CALSTABLE"
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->doc</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->mode</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-></TABLE
-><P
-></P
-></DIV
-></DIV
-><HR><DIV
-CLASS="REFSECT2"
-><A
-NAME="AEN5034"
-></A
-><H3
-><A
-NAME="XMLGETCOMPRESSMODE"
-></A
->xmlGetCompressMode ()</H3
-><TABLE
-BORDER="0"
-BGCOLOR="#D6E8FF"
-WIDTH="100%"
-CELLPADDING="6"
-><TR
-><TD
-><PRE
-CLASS="PROGRAMLISTING"
->int xmlGetCompressMode (void);</PRE
-></TD
-></TR
-></TABLE
-><P
->get the default compression mode used, ZLIB based.</P
-><P
-></P
-><DIV
-CLASS="INFORMALTABLE"
-><P
-></P
-><TABLE
-BORDER="0"
-WIDTH="100%"
-BGCOLOR="#FFD0D0"
-CELLSPACING="0"
-CELLPADDING="4"
-CLASS="CALSTABLE"
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><I
-CLASS="EMPHASIS"
->Returns</I
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-></TABLE
-><P
-></P
-></DIV
-></DIV
-><HR><DIV
-CLASS="REFSECT2"
-><A
-NAME="AEN5049"
-></A
-><H3
-><A
-NAME="XMLSETCOMPRESSMODE"
-></A
->xmlSetCompressMode ()</H3
-><TABLE
-BORDER="0"
-BGCOLOR="#D6E8FF"
-WIDTH="100%"
-CELLPADDING="6"
-><TR
-><TD
-><PRE
-CLASS="PROGRAMLISTING"
->void xmlSetCompressMode (int mode);</PRE
-></TD
-></TR
-></TABLE
-><P
->set the default compression mode used, ZLIB based
-Correct values: 0 (uncompressed) to 9 (max compression)</P
-><P
-></P
-><DIV
-CLASS="INFORMALTABLE"
-><P
-></P
-><TABLE
-BORDER="0"
-WIDTH="100%"
-BGCOLOR="#FFD0D0"
-CELLSPACING="0"
-CELLPADDING="4"
-CLASS="CALSTABLE"
-><TR
-><TD
-WIDTH="20%"
-ALIGN="RIGHT"
-VALIGN="TOP"
-><TT
-CLASS="PARAMETER"
-><I
->mode</I
-></TT
-> :</TD
-><TD
-WIDTH="80%"
-ALIGN="LEFT"
-VALIGN="TOP"
-> </TD
-></TR
-></TABLE
-><P
-></P
-></DIV
-></DIV
-></DIV
-><DIV
-CLASS="NAVFOOTER"
-><BR
-CLEAR="all"><BR><TABLE
-WIDTH="100%"
-BORDER="0"
-BGCOLOR="#000000"
-CELLPADDING="1"
-CELLSPACING="0"
-><TR
-><TD
-WIDTH="25%"
-BGCOLOR="#C00000"
-ALIGN="left"
-><A
-HREF="gnome-xml-sax.html"
-><FONT
-COLOR="#FFFFFF"
-SIZE="3"
-><B
-><<< Previous Page</B
-></FONT
-></A
-></TD
-><TD
-WIDTH="25%"
-BGCOLOR="#0000C0"
-ALIGN="center"
-><FONT
-COLOR="#FFFFFF"
-SIZE="3"
-><B
-><A
-HREF="book1.html"
-><FONT
-COLOR="#FFFFFF"
-SIZE="3"
-><B
->Home</B
-></FONT
-></A
-></B
-></FONT
-></TD
-><TD
-WIDTH="25%"
-BGCOLOR="#00C000"
-ALIGN="center"
-><FONT
-COLOR="#FFFFFF"
-SIZE="3"
-><B
-><A
-HREF="libxml-lib.html"
-><FONT
-COLOR="#FFFFFF"
-SIZE="3"
-><B
->Up</B
-></FONT
-></A
-></B
-></FONT
-></TD
-><TD
-WIDTH="25%"
-BGCOLOR="#C00000"
-ALIGN="right"
-><A
-HREF="gnome-xml-entities.html"
-><FONT
-COLOR="#FFFFFF"
-SIZE="3"
-><B
->Next Page >>></B
-></FONT
-></A
-></TD
-></TR
-><TR
-><TD
-COLSPAN="2"
-ALIGN="left"
-><FONT
-COLOR="#FFFFFF"
-SIZE="3"
-><B
->SAX</B
-></FONT
-></TD
-><TD
-COLSPAN="2"
-ALIGN="right"
-><FONT
-COLOR="#FFFFFF"
-SIZE="3"
-><B
->entities</B
-></FONT
-></TD
-></TR
-></TABLE
-></DIV
-></BODY
-></HTML
>
\ No newline at end of file
diff --git a/encoding.c b/encoding.c
index 1a4c157..627f468 100644
--- a/encoding.c
+++ b/encoding.c
@@ -3,6 +3,7 @@
*
* Related specs:
* rfc2044 (UTF-8 and UTF-16) F. Yergeau Alis Technologies
+ * rfc2781 UTF-16, an encoding of ISO 10646, P. Hoffman, F. Yergeau
* [ISO-10646] UTF-8 and UTF-16 in Annexes
* [ISO-8859-1] ISO Latin-1 characters codes.
* [UNICODE] The Unicode Consortium, "The Unicode Standard --
@@ -66,6 +67,73 @@
*/
/**
+ * xmlGetUTF8Char:
+ * @utf: a sequence of UTF-8 encoded bytes
+ * @len: a pointer to @bytes len
+ *
+ * Read one UTF8 Char from @utf
+ *
+ * Returns the char value or -1 in case of error and update @len with the
+ * number of bytes used
+ */
+int
+xmlGetUTF8Char(const unsigned char *utf, int *len) {
+ unsigned int c;
+
+ if (utf == NULL)
+ goto error;
+ if (len == NULL)
+ goto error;
+ if (*len < 1)
+ goto error;
+
+ c = utf[0];
+ if (c & 0x80) {
+ if (*len < 2)
+ goto error;
+ if ((utf[1] & 0xc0) != 0x80)
+ goto error;
+ if ((c & 0xe0) == 0xe0) {
+ if (*len < 3)
+ goto error;
+ if ((utf[2] & 0xc0) != 0x80)
+ goto error;
+ if ((c & 0xf0) == 0xf0) {
+ if (*len < 4)
+ goto error;
+ if ((c & 0xf8) != 0xf0 || (utf[3] & 0xc0) != 0x80)
+ goto error;
+ *len = 4;
+ /* 4-byte code */
+ c = (utf[0] & 0x7) << 18;
+ c |= (utf[1] & 0x3f) << 12;
+ c |= (utf[2] & 0x3f) << 6;
+ c |= utf[3] & 0x3f;
+ } else {
+ /* 3-byte code */
+ *len = 3;
+ c = (utf[0] & 0xf) << 12;
+ c |= (utf[1] & 0x3f) << 6;
+ c |= utf[2] & 0x3f;
+ }
+ } else {
+ /* 2-byte code */
+ *len = 2;
+ c = (utf[0] & 0x1f) << 6;
+ c |= utf[1] & 0x3f;
+ }
+ } else {
+ /* 1-byte code */
+ *len = 1;
+ }
+ return(c);
+
+error:
+ *len = 0;
+ return(-1);
+}
+
+/**
* xmlCheckUTF8: Check utf-8 string for legality.
* @utf: Pointer to putative utf-8 encoded string.
*
@@ -236,7 +304,7 @@
(*inlenb)--;
inlen = *inlenb / 2;
inend = in + inlen;
- while (in < inend) {
+ while ((in < inend) && (out - outstart + 5 < *outlen)) {
if (xmlLittleEndian) {
c= *in++;
} else {
@@ -246,9 +314,9 @@
in++;
}
if ((c & 0xFC00) == 0xD800) { /* surrogates */
- if (in >= inend) { /* (in > inend) shouldn't happens */
- break;
- }
+ if (in >= inend) { /* (in > inend) shouldn't happens */
+ break;
+ }
if (xmlLittleEndian) {
d = *in++;
} else {
@@ -317,6 +385,24 @@
unsigned char *tmp;
unsigned short tmp1, tmp2;
+ if (in == NULL) {
+ /*
+ * initialization, add the Byte Order Mark
+ */
+ if (*outlen >= 2) {
+ outb[0] = 0xFF;
+ outb[1] = 0xFE;
+ *outlen = 2;
+ *inlen = 0;
+#ifdef DEBUG_ENCODING
+ fprintf(stderr, "Added FFFE Byte Order Mark\n");
+#endif
+ return(2);
+ }
+ *outlen = 0;
+ *inlen = 0;
+ return(0);
+ }
outend = out + (*outlen / 2);
while (in < inend) {
d= *in++;
@@ -385,7 +471,7 @@
break;
processed = in;
}
- *outlen = out - outstart;
+ *outlen = (out - outstart) * 2;
*inlen = processed - in;
return(0);
}
@@ -509,6 +595,24 @@
unsigned char *tmp;
unsigned short tmp1, tmp2;
+ if (in == NULL) {
+ /*
+ * initialization, add the Byte Order Mark
+ */
+ if (*outlen >= 2) {
+ outb[0] = 0xFE;
+ outb[1] = 0xFF;
+ *outlen = 2;
+ *inlen = 0;
+#ifdef DEBUG_ENCODING
+ fprintf(stderr, "Added FEFF Byte Order Mark\n");
+#endif
+ return(2);
+ }
+ *outlen = 0;
+ *inlen = 0;
+ return(0);
+ }
outend = out + (*outlen / 2);
while (in < inend) {
d= *in++;
@@ -574,7 +678,7 @@
break;
processed = in;
}
- *outlen = out - outstart;
+ *outlen = (out - outstart) * 2;
*inlen = processed - in;
return(0);
}
@@ -695,6 +799,70 @@
return(XML_CHAR_ENCODING_ERROR);
}
+/**
+ * xmlGetCharEncodingName:
+ * @enc: the encoding
+ *
+ * The "canonical" name for XML encoding.
+ * C.f. http://www.w3.org/TR/REC-xml#charencoding
+ * Section 4.3.3 Character Encoding in Entities
+ *
+ * Returns the canonical name for the given encoding
+ */
+
+const char*
+xmlGetCharEncodingName(xmlCharEncoding enc) {
+ switch (enc) {
+ case XML_CHAR_ENCODING_ERROR:
+ return(NULL);
+ case XML_CHAR_ENCODING_NONE:
+ return(NULL);
+ case XML_CHAR_ENCODING_UTF8:
+ return("UTF-8");
+ case XML_CHAR_ENCODING_UTF16LE:
+ return("UTF-16");
+ case XML_CHAR_ENCODING_UTF16BE:
+ return("UTF-16");
+ case XML_CHAR_ENCODING_EBCDIC:
+ return("EBCDIC");
+ case XML_CHAR_ENCODING_UCS4LE:
+ return("ISO-10646-UCS-4");
+ case XML_CHAR_ENCODING_UCS4BE:
+ return("ISO-10646-UCS-4");
+ case XML_CHAR_ENCODING_UCS4_2143:
+ return("ISO-10646-UCS-4");
+ case XML_CHAR_ENCODING_UCS4_3412:
+ return("ISO-10646-UCS-4");
+ case XML_CHAR_ENCODING_UCS2:
+ return("ISO-10646-UCS-2");
+ case XML_CHAR_ENCODING_8859_1:
+ return("ISO-8859-1");
+ case XML_CHAR_ENCODING_8859_2:
+ return("ISO-8859-2");
+ case XML_CHAR_ENCODING_8859_3:
+ return("ISO-8859-3");
+ case XML_CHAR_ENCODING_8859_4:
+ return("ISO-8859-4");
+ case XML_CHAR_ENCODING_8859_5:
+ return("ISO-8859-5");
+ case XML_CHAR_ENCODING_8859_6:
+ return("ISO-8859-6");
+ case XML_CHAR_ENCODING_8859_7:
+ return("ISO-8859-7");
+ case XML_CHAR_ENCODING_8859_8:
+ return("ISO-8859-8");
+ case XML_CHAR_ENCODING_8859_9:
+ return("ISO-8859-9");
+ case XML_CHAR_ENCODING_2022_JP:
+ return("ISO-2022-JP");
+ case XML_CHAR_ENCODING_SHIFT_JIS:
+ return("Shift-JIS");
+ case XML_CHAR_ENCODING_EUC_JP:
+ return("EUC-JP");
+ }
+ return(NULL);
+}
+
/****************************************************************
* *
* Char encoding handlers *
@@ -883,7 +1051,7 @@
handler = xmlFindCharEncodingHandler("ebcdic");
if (handler != NULL) return(handler);
break;
- case XML_CHAR_ENCODING_UCS4LE:
+ case XML_CHAR_ENCODING_UCS4BE:
handler = xmlFindCharEncodingHandler("ISO-10646-UCS-4");
if (handler != NULL) return(handler);
handler = xmlFindCharEncodingHandler("UCS-4");
@@ -891,8 +1059,12 @@
handler = xmlFindCharEncodingHandler("UCS4");
if (handler != NULL) return(handler);
break;
- case XML_CHAR_ENCODING_UCS4BE:
- handler = xmlFindCharEncodingHandler("UCS4BE");
+ case XML_CHAR_ENCODING_UCS4LE:
+ handler = xmlFindCharEncodingHandler("ISO-10646-UCS-4");
+ if (handler != NULL) return(handler);
+ handler = xmlFindCharEncodingHandler("UCS-4");
+ if (handler != NULL) return(handler);
+ handler = xmlFindCharEncodingHandler("UCS4");
if (handler != NULL) return(handler);
break;
case XML_CHAR_ENCODING_UCS4_2143:
@@ -953,9 +1125,10 @@
*/
xmlCharEncodingHandlerPtr
xmlFindCharEncodingHandler(const char *name) {
+ xmlCharEncodingHandlerPtr enc;
+ xmlCharEncoding alias;
#ifdef LIBXML_ICONV_ENABLED
iconv_t icv_in, icv_out;
- xmlCharEncodingHandlerPtr enc;
#endif /* LIBXML_ICONV_ENABLED */
char upper[100];
int i;
@@ -964,6 +1137,9 @@
if (name == NULL) return(xmlDefaultCharEncodingHandler);
if (name[0] == 0) return(xmlDefaultCharEncodingHandler);
+ /*
+ * Check first for directly registered encoding names
+ */
for (i = 0;i < 99;i++) {
upper[i] = toupper(name[i]);
if (upper[i] == 0) break;
@@ -1002,9 +1178,23 @@
fprintf(stderr, "iconv : problems with filters for '%s'\n", name);
}
#endif /* LIBXML_ICONV_ENABLED */
+
#ifdef DEBUG_ENCODING
fprintf(stderr, "No handler found for encoding %s\n", name);
#endif
+
+ /*
+ * Fallback using the canonical names
+ */
+ alias = xmlParseCharEncoding(name);
+ if (alias != XML_CHAR_ENCODING_ERROR) {
+ const char* canon;
+ canon = xmlGetCharEncodingName(alias);
+ if ((canon != NULL) && (strcmp(name, canon))) {
+ return(xmlFindCharEncodingHandler(canon));
+ }
+ }
+
return(NULL);
}
@@ -1040,8 +1230,13 @@
ret = iconv(cd,
&icv_in, &icv_inlen,
&icv_out, &icv_outlen);
- *inlen -= icv_inlen;
- *outlen -= icv_outlen;
+ if (in != NULL) {
+ *inlen -= icv_inlen;
+ *outlen -= icv_outlen;
+ } else {
+ *inlen = 0;
+ *outlen = 0;
+ }
if (icv_inlen != 0 || ret == (size_t) -1) {
#ifdef EILSEQ
if (errno == EILSEQ) {
@@ -1067,6 +1262,91 @@
#endif /* LIBXML_ICONV_ENABLED */
/**
+ * xmlCharEncFirstLine:
+ * @handler: char enconding transformation data structure
+ * @out: an xmlBuffer for the output.
+ * @in: an xmlBuffer for the input
+ *
+ * Front-end for the encoding handler input function, but handle only
+ * the very first line, i.e. limit itself to 45 chars.
+ *
+ * Returns the number of byte written if success, or
+ * -1 general error
+ * -2 if the transcoding fails (for *in is not valid utf8 string or
+ * the result of transformation can't fit into the encoding we want), or
+ */
+int
+xmlCharEncFirstLine(xmlCharEncodingHandler *handler, xmlBufferPtr out,
+ xmlBufferPtr in) {
+ int ret = -2;
+ int written;
+ int toconv;
+
+ if (handler == NULL) return(-1);
+ if (out == NULL) return(-1);
+ if (in == NULL) return(-1);
+
+ written = out->size - out->use;
+ toconv = in->use;
+ if (toconv * 2 >= written) {
+ xmlBufferGrow(out, toconv);
+ written = out->size - out->use - 1;
+ }
+
+ /*
+ * echo '<?xml version="1.0" encoding="UCS4"?>' | wc -c => 38
+ * 45 chars should be sufficient to reach the end of the encoding
+ * decalration without going too far inside the document content.
+ */
+ written = 45;
+
+ if (handler->input != NULL) {
+ ret = handler->input(&out->content[out->use], &written,
+ in->content, &toconv);
+ xmlBufferShrink(in, toconv);
+ out->use += written;
+ out->content[out->use] = 0;
+ }
+#ifdef LIBXML_ICONV_ENABLED
+ else if (handler->iconv_in != NULL) {
+ ret = xmlIconvWrapper(handler->iconv_in, &out->content[out->use],
+ &written, in->content, &toconv);
+ xmlBufferShrink(in, toconv);
+ out->use += written;
+ out->content[out->use] = 0;
+ if (ret == -1) ret = -3;
+ }
+#endif /* LIBXML_ICONV_ENABLED */
+#ifdef DEBUG_ENCODING
+ switch (ret) {
+ case 0:
+ fprintf(stderr, "converted %d bytes to %d bytes of input\n",
+ toconv, written);
+ break;
+ case -1:
+ fprintf(stderr,"converted %d bytes to %d bytes of input, %d left\n",
+ toconv, written, in->use);
+ break;
+ case -2:
+ fprintf(stderr, "input conversion failed due to input error\n");
+ break;
+ case -3:
+ fprintf(stderr,"converted %d bytes to %d bytes of input, %d left\n",
+ toconv, written, in->use);
+ break;
+ default:
+ fprintf(stderr,"Unknown input conversion failed %d\n", ret);
+ }
+#endif
+ /*
+ * Ignore when input buffer is not on a boundary
+ */
+ if (ret == -3) ret = 0;
+ if (ret == -1) ret = 0;
+ return(ret);
+}
+
+/**
* xmlCharEncInFunc:
* @handler: char enconding transformation data structure
* @out: an xmlBuffer for the output.
@@ -1113,8 +1393,8 @@
if (ret == -1) ret = -3;
}
#endif /* LIBXML_ICONV_ENABLED */
-#ifdef DEBUG_ENCODING
switch (ret) {
+#ifdef DEBUG_ENCODING
case 0:
fprintf(stderr, "converted %d bytes to %d bytes of input\n",
toconv, written);
@@ -1123,17 +1403,17 @@
fprintf(stderr,"converted %d bytes to %d bytes of input, %d left\n",
toconv, written, in->use);
break;
- case -2:
- fprintf(stderr, "input conversion failed due to input error\n");
- break;
case -3:
fprintf(stderr,"converted %d bytes to %d bytes of input, %d left\n",
toconv, written, in->use);
break;
- default:
- fprintf(stderr,"Unknown input conversion failed %d\n", ret);
- }
#endif
+ case -2:
+ fprintf(stderr, "input conversion failed due to input error\n");
+ fprintf(stderr, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
+ in->content[0], in->content[1],
+ in->content[2], in->content[3]);
+ }
/*
* Ignore when input buffer is not on a boundary
*/
@@ -1148,6 +1428,11 @@
* @in: an xmlBuffer for the input
*
* Generic front-end for the encoding handler output function
+ * a first call with @in == NULL has to be made firs to initiate the
+ * output in case of non-stateless encoding needing to initiate their
+ * state or the output (like the BOM in UTF16).
+ * In case of UTF8 sequence conversion errors for the given encoder,
+ * the content will be automatically remapped to a CharRef sequence.
*
* Returns the number of byte written if success, or
* -1 general error
@@ -1160,12 +1445,43 @@
int ret = -2;
int written;
int toconv;
+ int output = 0;
if (handler == NULL) return(-1);
if (out == NULL) return(-1);
- if (in == NULL) return(-1);
+retry:
+
written = out->size - out->use;
+
+ /*
+ * First specific handling of in = NULL, i.e. the initialization call
+ */
+ if (in == NULL) {
+ toconv = 0;
+ if (handler->output != NULL) {
+ ret = handler->output(&out->content[out->use], &written,
+ NULL, &toconv);
+ out->use += written;
+ out->content[out->use] = 0;
+ }
+#ifdef LIBXML_ICONV_ENABLED
+ else if (handler->iconv_out != NULL) {
+ ret = xmlIconvWrapper(handler->iconv_out, &out->content[out->use],
+ &written, NULL, &toconv);
+ out->use += written;
+ out->content[out->use] = 0;
+ }
+#endif /* LIBXML_ICONV_ENABLED */
+#ifdef DEBUG_ENCODING
+ fprintf(stderr, "initialized encoder\n");
+#endif
+ return(0);
+ }
+
+ /*
+ * Convertion itself.
+ */
toconv = in->use;
if (toconv * 2 >= written) {
xmlBufferGrow(out, toconv * 2);
@@ -1173,7 +1489,7 @@
}
if (handler->output != NULL) {
ret = handler->output(&out->content[out->use], &written,
- in->content, &toconv);
+ in->content, &toconv);
xmlBufferShrink(in, toconv);
out->use += written;
out->content[out->use] = 0;
@@ -1188,8 +1504,14 @@
if (ret == -1) ret = -3;
}
#endif /* LIBXML_ICONV_ENABLED */
-#ifdef DEBUG_ENCODING
+
+ if (ret >= 0) output += ret;
+
+ /*
+ * Attempt to handle error cases
+ */
switch (ret) {
+#ifdef DEBUG_ENCODING
case 0:
fprintf(stderr, "converted %d bytes to %d bytes of output\n",
toconv, written);
@@ -1197,17 +1519,45 @@
case -1:
fprintf(stderr, "output conversion failed by lack of space\n");
break;
- case -2:
- fprintf(stderr, "output conversion failed due to output error\n");
- break;
case -3:
fprintf(stderr,"converted %d bytes to %d bytes of output %d left\n",
toconv, written, in->use);
break;
- default:
- fprintf(stderr,"Unknown output conversion failed %d\n", ret);
- }
#endif
+ case -2: {
+ int len = in->use;
+ const char *utf = (const char *) in->content;
+ int cur;
+
+ cur = xmlGetUTF8Char(utf, &len);
+ if (cur > 0) {
+ xmlChar charref[20];
+
+#ifdef DEBUG_ENCODING
+ fprintf(stderr, "handling output conversion error\n");
+ fprintf(stderr, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
+ in->content[0], in->content[1],
+ in->content[2], in->content[3]);
+#endif
+ /*
+ * Removes the UTF8 sequence, and replace it by a charref
+ * and continue the transcoding phase, hoping the error
+ * did not mangle the encoder state.
+ */
+ sprintf(charref, "&#x%X;", cur);
+ xmlBufferShrink(in, len);
+ xmlBufferAddHead(in, charref, -1);
+
+ goto retry;
+ } else {
+ fprintf(stderr, "output conversion failed due to conv error\n");
+ fprintf(stderr, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
+ in->content[0], in->content[1],
+ in->content[2], in->content[3]);
+ }
+ break;
+ }
+ }
return(ret);
}
diff --git a/encoding.h b/encoding.h
index f6edbf2..ce0ab75 100644
--- a/encoding.h
+++ b/encoding.h
@@ -102,6 +102,8 @@
*
* Take a block of UTF-8 chars in and try to convert it to an other
* encoding.
+ * Note: a first call designed to produce heading info is called with
+ * in = NULL. If stateful this should also initialize the encoder state
*
* Returns the number of byte written, or -1 by lack of space, or -2
* if the transcoding failed.
@@ -136,6 +138,7 @@
xmlCharEncoding xmlDetectCharEncoding (const unsigned char* in,
int len);
xmlCharEncoding xmlParseCharEncoding (const char* name);
+const char* xmlGetCharEncodingName (xmlCharEncoding enc);
xmlCharEncodingHandlerPtr xmlGetCharEncodingHandler(xmlCharEncoding enc);
xmlCharEncodingHandlerPtr xmlFindCharEncodingHandler(const char *name);
int xmlCheckUTF8 (const unsigned char *utf);
@@ -147,6 +150,9 @@
int xmlCharEncInFunc (xmlCharEncodingHandler *handler,
xmlBufferPtr out,
xmlBufferPtr in);
+int xmlCharEncFirstLine (xmlCharEncodingHandler *handler,
+ xmlBufferPtr out,
+ xmlBufferPtr in);
int xmlCharEncCloseFunc (xmlCharEncodingHandler *handler);
#ifdef __cplusplus
diff --git a/entities.c b/entities.c
index 15247a2..c541d67 100644
--- a/entities.c
+++ b/entities.c
@@ -946,6 +946,86 @@
}
/**
+ * xmlEncodeSpecialChars:
+ * @doc: the document containing the string
+ * @input: A string to convert to XML.
+ *
+ * Do a global encoding of a string, replacing the predefined entities
+ * this routine is reentrant, and result must be deallocated.
+ *
+ * Returns A newly allocated string with the substitution done.
+ */
+xmlChar *
+xmlEncodeSpecialChars(xmlDocPtr doc, const xmlChar *input) {
+ const xmlChar *cur = input;
+ xmlChar *buffer = NULL;
+ xmlChar *out = NULL;
+ int buffer_size = 0;
+ int html = 0;
+
+ if (input == NULL) return(NULL);
+ if (doc != NULL)
+ html = (doc->type == XML_HTML_DOCUMENT_NODE);
+
+ /*
+ * allocate an translation buffer.
+ */
+ buffer_size = 1000;
+ buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
+ if (buffer == NULL) {
+ perror("malloc failed");
+ return(NULL);
+ }
+ out = buffer;
+
+ while (*cur != '\0') {
+ if (out - buffer > buffer_size - 10) {
+ int index = out - buffer;
+
+ growBufferReentrant();
+ out = &buffer[index];
+ }
+
+ /*
+ * By default one have to encode at least '<', '>', '"' and '&' !
+ */
+ if (*cur == '<') {
+ *out++ = '&';
+ *out++ = 'l';
+ *out++ = 't';
+ *out++ = ';';
+ } else if (*cur == '>') {
+ *out++ = '&';
+ *out++ = 'g';
+ *out++ = 't';
+ *out++ = ';';
+ } else if (*cur == '&') {
+ *out++ = '&';
+ *out++ = 'a';
+ *out++ = 'm';
+ *out++ = 'p';
+ *out++ = ';';
+ } else if (*cur == '"') {
+ *out++ = '&';
+ *out++ = 'q';
+ *out++ = 'u';
+ *out++ = 'o';
+ *out++ = 't';
+ *out++ = ';';
+ } else {
+ /*
+ * Works because on UTF-8, all extended sequences cannot
+ * result in bytes in the ASCII range.
+ */
+ *out++ = *cur;
+ }
+ cur++;
+ }
+ *out++ = 0;
+ return(buffer);
+}
+
+/**
* xmlCreateEntitiesTable:
*
* create and initialize an empty entities hash table.
diff --git a/entities.h b/entities.h
index f0ec731..c9bd003 100644
--- a/entities.h
+++ b/entities.h
@@ -106,6 +106,8 @@
const xmlChar *input);
xmlChar * xmlEncodeEntitiesReentrant(xmlDocPtr doc,
const xmlChar *input);
+xmlChar * xmlEncodeSpecialChars (xmlDocPtr doc,
+ const xmlChar *input);
xmlEntitiesTablePtr xmlCreateEntitiesTable (void);
xmlEntitiesTablePtr xmlCopyEntitiesTable (xmlEntitiesTablePtr table);
void xmlFreeEntitiesTable (xmlEntitiesTablePtr table);
diff --git a/example/Makefile.am b/example/Makefile.am
index 0978f95..ce7a8da 100644
--- a/example/Makefile.am
+++ b/example/Makefile.am
@@ -6,5 +6,9 @@
LDADD = $(top_builddir)/libxml.la @Z_LIBS@
-$(top_builddir)/libxml.la:
+$(srcdir)/libxml:
+ -$(RM) $(srcdir)/libxml
+ ln -s $(srcdir)/. $(srcdir)/libxml
+
+$(top_builddir)/libxml.la: $(srcdir)/libxml
(cd .. ; $(MAKE))
diff --git a/example/gjobread.c b/example/gjobread.c
index ca38671..916fa53 100644
--- a/example/gjobread.c
+++ b/example/gjobread.c
@@ -10,12 +10,18 @@
#include <string.h>
#include <stdlib.h>
-#include <xmlmemory.h>
-#if defined(LIBXML_VERSION) && LIBXML_VERSION >= 20000
+/*
+ * This example should compile and run indifferently with libxml-1.8.8 +
+ * and libxml2-2.1.0 +
+ * Check the COMPAT comments below
+ */
+
+/*
+ * COMPAT using xml-config --cflags to get the include path this will
+ * work with both
+ */
+#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
-#else
-#include <gnome-xml/parser.h>
-#endif
#define DEBUG(x) printf(x)
@@ -50,12 +56,13 @@
memset(ret, 0, sizeof(person));
/* We don't care what the top level element name is */
- cur = cur->children;
+ /* COMPAT xmlChildrenNode is a macro unifying libxml1 and libxml2 names */
+ cur = cur->xmlChildrenNode;
while (cur != NULL) {
if ((!strcmp(cur->name, "Person")) && (cur->ns == ns))
- ret->name = xmlNodeListGetString(doc, cur->children, 1);
+ ret->name = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
if ((!strcmp(cur->name, "Email")) && (cur->ns == ns))
- ret->email = xmlNodeListGetString(doc, cur->children, 1);
+ ret->email = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
cur = cur->next;
}
@@ -108,7 +115,7 @@
memset(ret, 0, sizeof(job));
/* We don't care what the top level element name is */
- cur = cur->children;
+ cur = cur->xmlChildrenNode;
while (cur != NULL) {
if ((!strcmp(cur->name, "Project")) && (cur->ns == ns)) {
@@ -118,9 +125,9 @@
}
}
if ((!strcmp(cur->name, "Application")) && (cur->ns == ns))
- ret->application = xmlNodeListGetString(doc, cur->children, 1);
+ ret->application = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
if ((!strcmp(cur->name, "Category")) && (cur->ns == ns))
- ret->category = xmlNodeListGetString(doc, cur->children, 1);
+ ret->category = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
if ((!strcmp(cur->name, "Contact")) && (cur->ns == ns))
ret->contact = parsePerson(doc, ns, cur);
cur = cur->next;
@@ -173,8 +180,6 @@
* Check the document is of the right kind
*/
- // cur = doc->root;
- // cur = doc->children;
cur = xmlDocGetRootElement(doc);
if (cur == NULL) {
fprintf(stderr,"empty document\n");
@@ -209,8 +214,7 @@
* Now, walk the tree.
*/
/* First level we expect just Jobs */
- // cur = cur->children;
- cur = cur -> children;
+ cur = cur->xmlChildrenNode;
while ( cur && xmlIsBlankNode ( cur ) )
{
cur = cur -> next;
@@ -229,7 +233,7 @@
}
/* Second level is a list of Job, but be laxist */
- cur = cur->children;
+ cur = cur->xmlChildrenNode;
while (cur != NULL) {
if ((!strcmp(cur->name, "Job")) && (cur->ns == ns)) {
job = parseJob(doc, ns, cur);
@@ -257,6 +261,9 @@
int i;
gJobPtr cur;
+ /* COMPAT: Do not genrate nodes for formatting spaces */
+ xmlKeepBlanksDefault(0);
+
for (i = 1; i < argc ; i++) {
cur = parseGjobFile(argv[i]);
if ( cur )
diff --git a/include/libxml/encoding.h b/include/libxml/encoding.h
index f6edbf2..ce0ab75 100644
--- a/include/libxml/encoding.h
+++ b/include/libxml/encoding.h
@@ -102,6 +102,8 @@
*
* Take a block of UTF-8 chars in and try to convert it to an other
* encoding.
+ * Note: a first call designed to produce heading info is called with
+ * in = NULL. If stateful this should also initialize the encoder state
*
* Returns the number of byte written, or -1 by lack of space, or -2
* if the transcoding failed.
@@ -136,6 +138,7 @@
xmlCharEncoding xmlDetectCharEncoding (const unsigned char* in,
int len);
xmlCharEncoding xmlParseCharEncoding (const char* name);
+const char* xmlGetCharEncodingName (xmlCharEncoding enc);
xmlCharEncodingHandlerPtr xmlGetCharEncodingHandler(xmlCharEncoding enc);
xmlCharEncodingHandlerPtr xmlFindCharEncodingHandler(const char *name);
int xmlCheckUTF8 (const unsigned char *utf);
@@ -147,6 +150,9 @@
int xmlCharEncInFunc (xmlCharEncodingHandler *handler,
xmlBufferPtr out,
xmlBufferPtr in);
+int xmlCharEncFirstLine (xmlCharEncodingHandler *handler,
+ xmlBufferPtr out,
+ xmlBufferPtr in);
int xmlCharEncCloseFunc (xmlCharEncodingHandler *handler);
#ifdef __cplusplus
diff --git a/include/libxml/entities.h b/include/libxml/entities.h
index f0ec731..c9bd003 100644
--- a/include/libxml/entities.h
+++ b/include/libxml/entities.h
@@ -106,6 +106,8 @@
const xmlChar *input);
xmlChar * xmlEncodeEntitiesReentrant(xmlDocPtr doc,
const xmlChar *input);
+xmlChar * xmlEncodeSpecialChars (xmlDocPtr doc,
+ const xmlChar *input);
xmlEntitiesTablePtr xmlCreateEntitiesTable (void);
xmlEntitiesTablePtr xmlCopyEntitiesTable (xmlEntitiesTablePtr table);
void xmlFreeEntitiesTable (xmlEntitiesTablePtr table);
diff --git a/include/libxml/parser.h b/include/libxml/parser.h
index aa7e273..9cb73bd 100644
--- a/include/libxml/parser.h
+++ b/include/libxml/parser.h
@@ -120,8 +120,8 @@
xmlDocPtr myDoc; /* the document being built */
int wellFormed; /* is the document well formed */
int replaceEntities; /* shall we replace entities ? */
- const xmlChar *version; /* the XML version string */
- const xmlChar *encoding; /* encoding, if any */
+ const xmlChar *version; /* the XML version string */
+ const xmlChar *encoding; /* the declared encoding, if any */
int standalone; /* standalone document */
int html; /* are we parsing an HTML document */
@@ -177,7 +177,11 @@
int * spaceTab; /* array of space infos */
int depth; /* to prevent entity substitution loops */
- xmlParserInputPtr entity; /* used to check entities boundaries */
+ xmlParserInputPtr entity; /* used to check entities boundaries */
+ int charset; /* encoding of the in-memory content
+ actually an xmlCharEncoding */
+ int nodelen; /* Those two fields are there to */
+ int nodemem; /* Speed up large node parsing */
};
/**
diff --git a/include/libxml/tree.h b/include/libxml/tree.h
index 35ea525..9c5b280 100644
--- a/include/libxml/tree.h
+++ b/include/libxml/tree.h
@@ -181,6 +181,7 @@
xmlElementTypeVal etype; /* The type */
xmlElementContentPtr content; /* the allowed element content */
xmlAttributePtr attributes; /* List of the declared attributes */
+ const xmlChar *prefix; /* the namespace prefix if any */
};
/*
@@ -347,13 +348,23 @@
struct _xmlDtd *extSubset; /* the document external subset */
struct _xmlNs *oldNs; /* Global namespace, the old way */
const xmlChar *version; /* the XML version string */
- const xmlChar *encoding; /* encoding, if any */
+ const xmlChar *encoding; /* external initial encoding, if any */
void *ids; /* Hash table for ID attributes if any */
void *refs; /* Hash table for IDREFs attributes if any */
const xmlChar *URL; /* The URI for that document */
+ int charset; /* encoding of the in-memory content
+ actually an xmlCharEncoding */
};
/*
+ * Compatibility naming layer with libxml1
+ */
+#ifndef xmlChildrenNode
+#define xmlChildrenNode children
+#define xmlRootNode children
+#endif
+
+/*
* Variables.
*/
extern xmlNsPtr baseDTD;
@@ -374,6 +385,9 @@
void xmlBufferAdd (xmlBufferPtr buf,
const xmlChar *str,
int len);
+void xmlBufferAddHead (xmlBufferPtr buf,
+ const xmlChar *str,
+ int len);
void xmlBufferCat (xmlBufferPtr buf,
const xmlChar *str);
void xmlBufferCCat (xmlBufferPtr buf,
@@ -545,6 +559,9 @@
xmlChar * xmlNodeListGetString (xmlDocPtr doc,
xmlNodePtr list,
int inLine);
+xmlChar * xmlNodeListGetRawString (xmlDocPtr doc,
+ xmlNodePtr list,
+ int inLine);
void xmlNodeSetContent (xmlNodePtr cur,
const xmlChar *content);
void xmlNodeSetContentLen (xmlNodePtr cur,
@@ -591,7 +608,7 @@
void xmlDocDumpMemory (xmlDocPtr cur,
xmlChar**mem,
int *size);
-void xmlDocDump (FILE *f,
+int xmlDocDump (FILE *f,
xmlDocPtr cur);
void xmlElemDump (FILE *f,
xmlDocPtr doc,
@@ -599,6 +616,17 @@
int xmlSaveFile (const char *filename,
xmlDocPtr cur);
+/* This one is exported from xmlIO.h
+
+int xmlSaveFileTo (xmlOutputBuffer *buf,
+ xmlDocPtr cur,
+ const char *encoding);
+ */
+
+int xmlSaveFileEnc (const char *filename,
+ xmlDocPtr cur,
+ const char *encoding);
+
/*
* Compression
*/
diff --git a/include/libxml/uri.h b/include/libxml/uri.h
index 59c4467..705e385 100644
--- a/include/libxml/uri.h
+++ b/include/libxml/uri.h
@@ -43,6 +43,8 @@
xmlChar * xmlBuildURI (const xmlChar *URI,
const xmlChar *base);
xmlURIPtr xmlParseURI (const char *URI);
+int xmlParseURIReference (xmlURIPtr uri,
+ const char *str);
xmlChar * xmlSaveUri (xmlURIPtr uri);
void xmlPrintURI (FILE *stream,
xmlURIPtr uri);
diff --git a/include/libxml/xmlIO.h b/include/libxml/xmlIO.h
index 2d14ebe..5289367 100644
--- a/include/libxml/xmlIO.h
+++ b/include/libxml/xmlIO.h
@@ -18,6 +18,11 @@
extern "C" {
#endif
+/*
+ * Those are the functions and datatypes for the parser input
+ * I/O structures.
+ */
+
typedef int (*xmlInputMatchCallback) (char const *filename);
typedef void * (*xmlInputOpenCallback) (char const *filename);
typedef int (*xmlInputReadCallback) (void * context, char * buffer, int len);
@@ -32,13 +37,38 @@
xmlCharEncodingHandlerPtr encoder; /* I18N conversions to UTF-8 */
- xmlBufferPtr buffer; /* Local buffer encoded in UTF-8 */
+ xmlBufferPtr buffer; /* Local buffer encoded in UTF-8 or ISOLatin */
xmlBufferPtr raw; /* if encoder != NULL buffer for raw input */
};
/*
- * Interfaces
+ * Those are the functions and datatypes for the library output
+ * I/O structures.
+ */
+
+typedef int (*xmlOutputMatchCallback) (char const *filename);
+typedef void * (*xmlOutputOpenCallback) (char const *filename);
+typedef int (*xmlOutputWriteCallback) (void * context, const char * buffer,
+ int len);
+typedef void (*xmlOutputCloseCallback) (void * context);
+
+typedef struct _xmlOutputBuffer xmlOutputBuffer;
+typedef xmlOutputBuffer *xmlOutputBufferPtr;
+struct _xmlOutputBuffer {
+ void* context;
+ xmlOutputWriteCallback writecallback;
+ xmlOutputCloseCallback closecallback;
+
+ xmlCharEncodingHandlerPtr encoder; /* I18N conversions to UTF-8 */
+
+ xmlBufferPtr buffer; /* Local buffer encoded in UTF-8 or ISOLatin */
+ xmlBufferPtr conv; /* if encoder != NULL buffer for output */
+ int written; /* total number of byte written */
+};
+
+/*
+ * Interfaces for input
*/
xmlParserInputBufferPtr
@@ -72,6 +102,51 @@
xmlInputOpenCallback open,
xmlInputReadCallback read,
xmlInputCloseCallback close);
+/*
+ * Interfaces for output
+ */
+xmlOutputBufferPtr
+ xmlAllocOutputBuffer (xmlCharEncodingHandlerPtr encoder);
+
+xmlOutputBufferPtr
+ xmlOutputBufferCreateFilename (const char *URI,
+ xmlCharEncodingHandlerPtr encoder,
+ int compression);
+
+xmlOutputBufferPtr
+ xmlOutputBufferCreateFile (FILE *file,
+ xmlCharEncodingHandlerPtr encoder);
+
+xmlOutputBufferPtr
+ xmlOutputBufferCreateFd (int fd,
+ xmlCharEncodingHandlerPtr encoder);
+
+xmlOutputBufferPtr
+ xmlOutputBufferCreateIO (xmlOutputWriteCallback iowrite,
+ xmlOutputCloseCallback ioclose,
+ void *ioctx,
+ xmlCharEncodingHandlerPtr encoder);
+
+int xmlOutputBufferWrite (xmlOutputBufferPtr out,
+ int len,
+ const char *buf);
+int xmlOutputBufferWriteString (xmlOutputBufferPtr out,
+ const char *str);
+
+int xmlOutputBufferFlush (xmlOutputBufferPtr out);
+int xmlOutputBufferClose (xmlOutputBufferPtr out);
+
+int xmlRegisterOutputCallbacks (xmlOutputMatchCallback match,
+ xmlOutputOpenCallback open,
+ xmlOutputWriteCallback write,
+ xmlOutputCloseCallback close);
+
+/*
+ * This save function is part of tree.h actually
+ */
+int xmlSaveFileTo (xmlOutputBuffer *buf,
+ xmlDocPtr cur,
+ const char *encoding);
#ifdef __cplusplus
}
#endif
diff --git a/include/libxml/xmlversion.h.in b/include/libxml/xmlversion.h.in
index 5a62c27..b5edc09 100644
--- a/include/libxml/xmlversion.h.in
+++ b/include/libxml/xmlversion.h.in
@@ -9,8 +9,14 @@
#ifndef __XML_VERSION_H__
#define __XML_VERSION_H__
+/*
+ * use those to be sure nothing nasty will happen if
+ * your library and includes mismatch
+ */
+extern void xmlCheckVersion(int version);
#define LIBXML_VERSION @LIBXML_VERSION_NUMBER@
#define LIBXML_VERSION_STRING "@LIBXML_VERSION_NUMBER@"
+#define LIBXML_TEST_VERSION xmlCheckVersion(@LIBXML_VERSION_NUMBER@);
/*
* Whether the FTP support is configured in
diff --git a/include/libxml/xpath.h b/include/libxml/xpath.h
index 73e3f65..fc567fd 100644
--- a/include/libxml/xpath.h
+++ b/include/libxml/xpath.h
@@ -29,8 +29,8 @@
typedef struct _xmlNodeSet xmlNodeSet;
typedef xmlNodeSet *xmlNodeSetPtr;
struct _xmlNodeSet {
- int nodeNr; /* # of node in the set */
- int nodeMax; /* allocated space */
+ int nodeNr; /* number of nodes in the set */
+ int nodeMax; /* size of the array as allocated */
xmlNodePtr *nodeTab; /* array of nodes in no particular order */
};
@@ -41,6 +41,8 @@
* - boolean
* - number
* - string
+ *
+ * @@ XPointer will add more types !
*/
#define XPATH_UNDEFINED 0
diff --git a/nanoftp.c b/nanoftp.c
index 6ca3701..9ebe015 100644
--- a/nanoftp.c
+++ b/nanoftp.c
@@ -1193,7 +1193,9 @@
if (sscanf(cur, "%d,%d,%d,%d,%d,%d", &temp[0], &temp[1], &temp[2],
&temp[3], &temp[4], &temp[5]) != 6) {
fprintf(stderr, "Invalid answer to PASV\n");
- close(ctxt->dataFd); ctxt->dataFd = -1;
+ if (ctxt->dataFd != -1) {
+ close(ctxt->dataFd); ctxt->dataFd = -1;
+ }
return(-1);
}
for (i=0; i<6; i++) ad[i] = (unsigned char) (temp[i] & 0xff);
@@ -1448,6 +1450,8 @@
if (xmlNanoFTPCwd(ctxt, ctxt->path) < 1)
return(-1);
ctxt->dataFd = xmlNanoFTPGetConnection(ctxt);
+ if (ctxt->dataFd == -1)
+ return(-1);
#ifndef HAVE_SNPRINTF
len = sprintf(buf, "LIST -L\r\n");
#else /* HAVE_SNPRINTF */
@@ -1459,6 +1463,8 @@
return(-1);
}
ctxt->dataFd = xmlNanoFTPGetConnection(ctxt);
+ if (ctxt->dataFd == -1)
+ return(-1);
#ifndef HAVE_SNPRINTF
len = sprintf(buf, "LIST -L %s\r\n", filename);
#else /* HAVE_SNPRINTF */
@@ -1554,6 +1560,8 @@
if ((filename == NULL) && (ctxt->path == NULL))
return(-1);
ctxt->dataFd = xmlNanoFTPGetConnection(ctxt);
+ if (ctxt->dataFd == -1)
+ return(-1);
#ifndef HAVE_SNPRINTF
len = sprintf(buf, "TYPE I\r\n");
diff --git a/nanohttp.c b/nanohttp.c
index a94d6bb..33d0b7a 100644
--- a/nanohttp.c
+++ b/nanohttp.c
@@ -654,6 +654,23 @@
close(s);
return(-1);
}
+
+ if ( FD_ISSET(s, &wfd) ) {
+ socklen_t len;
+ len = sizeof(status);
+ if (getsockopt(s, SOL_SOCKET, SO_ERROR, &status, &len) < 0 ) {
+ /* Solaris error code */
+ return (-1);
+ }
+ if ( status ) {
+ close (s);
+ errno = status;
+ return (-1);
+ }
+ } else {
+ /* pbm */
+ return (-1);
+ }
return(s);
}
diff --git a/parser.c b/parser.c
index 6714d3c..6667106 100644
--- a/parser.c
+++ b/parser.c
@@ -47,7 +47,6 @@
#define XML_PARSER_BIG_BUFFER_SIZE 1000
#define XML_PARSER_BUFFER_SIZE 100
-const char *xmlParserVersion = LIBXML_VERSION_STRING;
int xmlGetWarningsDefaultValue = 1;
/*
@@ -63,6 +62,37 @@
void xmlParserHandlePEReference(xmlParserCtxtPtr ctxt);
xmlEntityPtr xmlParseStringPEReference(xmlParserCtxtPtr ctxt,
const xmlChar **str);
+
+/*
+ * Version handling
+ */
+const char *xmlParserVersion = LIBXML_VERSION_STRING;
+
+/*
+ * xmlCheckVersion:
+ * @version: the include version number
+ *
+ * check the compiled lib version against the include one.
+ * This can warn or immediately kill the application
+ */
+void
+xmlCheckVersion(int version) {
+ int myversion = LIBXML_VERSION;
+
+ if ((myversion / 10000) != (version / 10000)) {
+ fprintf(stderr,
+ "Fatal: program compiled against libxml %d using libxml %d\n",
+ (version / 10000), (myversion / 10000));
+ exit(1);
+ }
+ if ((myversion / 100) < (version / 100)) {
+ fprintf(stderr,
+ "Warning: program compiled against libxml %d using older %d\n",
+ (version / 100), (myversion / 100));
+ }
+}
+
+
/************************************************************************
* *
* Input handling functions for progressive parsing *
@@ -431,7 +461,7 @@
if (*(ctxt->input->cur) == '\n') {
ctxt->input->line++; ctxt->input->col = 1;
} else ctxt->input->col++;
- if (ctxt->encoding == NULL) {
+ if (ctxt->charset == XML_CHAR_ENCODING_UTF8) {
/*
* We are supposed to handle UTF8, check it's valid
* From rfc2044: encoding of the Unicode values on UTF-8:
@@ -522,12 +552,16 @@
* to ISO-Latin-1 (if you don't like this policy, just declare the
* encoding !)
*/
- if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+ if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) {
ctxt->sax->error(ctxt->userData,
"Input is not proper UTF-8, indicate encoding !\n");
+ ctxt->sax->error(ctxt->userData, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
+ ctxt->input->cur[0], ctxt->input->cur[1],
+ ctxt->input->cur[2], ctxt->input->cur[3]);
+ }
ctxt->errNo = XML_ERR_INVALID_ENCODING;
- ctxt->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
+ ctxt->charset = XML_CHAR_ENCODING_8859_1;
ctxt->input->cur++;
return;
}
@@ -556,7 +590,7 @@
*len = 0;
return(ctxt->token);
}
- if (ctxt->encoding == NULL) {
+ if (ctxt->charset == XML_CHAR_ENCODING_UTF8) {
/*
* We are supposed to handle UTF8, check it's valid
* From rfc2044: encoding of the Unicode values on UTF-8:
@@ -654,12 +688,16 @@
* to ISO-Latin-1 (if you don't like this policy, just declare the
* encoding !)
*/
- if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+ if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) {
ctxt->sax->error(ctxt->userData,
"Input is not proper UTF-8, indicate encoding !\n");
+ ctxt->sax->error(ctxt->userData, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
+ ctxt->input->cur[0], ctxt->input->cur[1],
+ ctxt->input->cur[2], ctxt->input->cur[3]);
+ }
ctxt->errNo = XML_ERR_INVALID_ENCODING;
- ctxt->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
+ ctxt->charset = XML_CHAR_ENCODING_8859_1;
*len = 1;
return((int) *ctxt->input->cur);
}
@@ -678,7 +716,7 @@
int
xmlStringCurrentChar(xmlParserCtxtPtr ctxt, const xmlChar *cur, int *len) {
- if (ctxt->encoding == NULL) {
+ if (ctxt->charset == XML_CHAR_ENCODING_UTF8) {
/*
* We are supposed to handle UTF8, check it's valid
* From rfc2044: encoding of the Unicode values on UTF-8:
@@ -755,9 +793,13 @@
* to ISO-Latin-1 (if you don't like this policy, just declare the
* encoding !)
*/
- if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
+ if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) {
ctxt->sax->error(ctxt->userData,
"Input is not proper UTF-8, indicate encoding !\n");
+ ctxt->sax->error(ctxt->userData, "Bytes: 0x%02X 0x%02X 0x%02X 0x%02X\n",
+ ctxt->input->cur[0], ctxt->input->cur[1],
+ ctxt->input->cur[2], ctxt->input->cur[3]);
+ }
ctxt->errNo = XML_ERR_INVALID_ENCODING;
*len = 1;
@@ -1224,6 +1266,7 @@
ctxt->inSubset = 0;
ctxt->errNo = XML_ERR_OK;
ctxt->depth = 0;
+ ctxt->charset = XML_CHAR_ENCODING_UTF8;
xmlInitNodeInfoSeq(&ctxt->node_seq);
}
@@ -1463,7 +1506,7 @@
ctxt->errNo = XML_ERR_INVALID_HEX_CHARREF;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
- "xmlParseCharRef: invalid hexadecimal value\n");
+ "xmlParseStringCharRef: invalid hexadecimal value\n");
ctxt->wellFormed = 0;
ctxt->disableSAX = 1;
val = 0;
@@ -1484,7 +1527,7 @@
ctxt->errNo = XML_ERR_INVALID_DEC_CHARREF;
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
- "xmlParseCharRef: invalid decimal value\n");
+ "xmlParseStringCharRef: invalid decimal value\n");
ctxt->wellFormed = 0;
ctxt->disableSAX = 1;
val = 0;
@@ -2297,9 +2340,11 @@
break;
case XML_CHAR_ENCODING_NONE:
/* let's assume it's UTF-8 without the XML decl */
+ ctxt->charset = XML_CHAR_ENCODING_UTF8;
return(0);
case XML_CHAR_ENCODING_UTF8:
/* default encoding, no conversion should be needed */
+ ctxt->charset = XML_CHAR_ENCODING_UTF8;
return(0);
default:
break;
@@ -2316,12 +2361,15 @@
ctxt->sax->error(ctxt->userData, "encoding unknown\n");
ctxt->wellFormed = 0;
ctxt->disableSAX = 1;
+ ctxt->charset = XML_CHAR_ENCODING_UTF8;
break;
case XML_CHAR_ENCODING_NONE:
/* let's assume it's UTF-8 without the XML decl */
+ ctxt->charset = XML_CHAR_ENCODING_UTF8;
return(0);
case XML_CHAR_ENCODING_UTF8:
/* default encoding, no conversion should be needed */
+ ctxt->charset = XML_CHAR_ENCODING_UTF8;
return(0);
case XML_CHAR_ENCODING_UTF16LE:
break;
@@ -2380,6 +2428,7 @@
(ctxt->input->encoding != NULL)) {
ctxt->encoding = xmlStrdup(ctxt->input->encoding);
}
+ ctxt->charset = enc;
return(0);
case XML_CHAR_ENCODING_2022_JP:
ctxt->errNo = XML_ERR_UNSUPPORTED_ENCODING;
@@ -2403,6 +2452,7 @@
}
if (handler == NULL)
return(-1);
+ ctxt->charset = XML_CHAR_ENCODING_UTF8;
return(xmlSwitchToEncoding(ctxt, handler));
}
@@ -2427,10 +2477,14 @@
if (ctxt->input->buf->encoder != NULL) {
if (ctxt->input->buf->encoder == handler)
return(0);
- if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
- ctxt->sax->error(ctxt->userData,
- "xmlSwitchEncoding : encoder already regitered\n");
- return(-1);
+ /*
+ * Note: this is a bit dangerous, but that's what it
+ * takes to use nearly compatible signature for different
+ * encodings.
+ */
+ xmlCharEncCloseFunc(ctxt->input->buf->encoder);
+ ctxt->input->buf->encoder = handler;
+ return(0);
}
ctxt->input->buf->encoder = handler;
@@ -2468,12 +2522,14 @@
ctxt->input->buf->buffer = xmlBufferCreate();
/*
- * convert as much as possible of the raw input
- * to the parser reading buffer.
+ * convert just enough to get
+ * '<?xml version="1.0" encoding="xxx"?>'
+ * parsed with the autodetected encoding
+ * into the parser reading buffer.
*/
- nbchars = xmlCharEncInFunc(ctxt->input->buf->encoder,
- ctxt->input->buf->buffer,
- ctxt->input->buf->raw);
+ nbchars = xmlCharEncFirstLine(ctxt->input->buf->encoder,
+ ctxt->input->buf->buffer,
+ ctxt->input->buf->raw);
if (nbchars < 0) {
fprintf(stderr, "xmlSwitchToEncoding: encoder error\n");
return(-1);
@@ -2536,10 +2592,7 @@
/*
* The parsing is now done in UTF8 natively
*/
- if (ctxt->encoding != NULL) {
- xmlFree((xmlChar *) ctxt->encoding);
- ctxt->encoding = NULL;
- }
+ ctxt->charset = XML_CHAR_ENCODING_UTF8;
} else
return(-1);
return(0);
@@ -3740,13 +3793,12 @@
xmlChar *
xmlParseAttValue(xmlParserCtxtPtr ctxt) {
xmlChar limit = 0;
- xmlChar *buffer = NULL;
- int buffer_size = 0;
- xmlChar *out = NULL;
-
+ xmlChar *buf = NULL;
+ int len = 0;
+ int buf_size = 0;
+ int c, l;
xmlChar *current = NULL;
xmlEntityPtr ent;
- xmlChar cur;
SHRINK;
@@ -3770,24 +3822,24 @@
/*
* allocate a translation buffer.
*/
- buffer_size = XML_PARSER_BUFFER_SIZE;
- buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
- if (buffer == NULL) {
+ buf_size = XML_PARSER_BUFFER_SIZE;
+ buf = (xmlChar *) xmlMalloc(buf_size * sizeof(xmlChar));
+ if (buf == NULL) {
perror("xmlParseAttValue: malloc failed");
return(NULL);
}
- out = buffer;
/*
* Ok loop until we reach one of the ending char or a size limit.
*/
- cur = CUR;
- while (((NXT(0) != limit) && (cur != '<')) || (ctxt->token != 0)) {
- if (cur == 0) break;
- if ((cur == '&') && (NXT(1) == '#')) {
+ c = CUR_CHAR(l);
+ while (((NXT(0) != limit) && (c != '<')) || (ctxt->token != 0)) {
+ if (c == 0) break;
+ if ((c == '&') && (NXT(1) == '#')) {
int val = xmlParseCharRef(ctxt);
- *out++ = val;
- } else if (cur == '&') {
+ COPY_BUF(l,buf,len,val);
+ NEXTL(l);
+ } else if (c == '&') {
ent = xmlParseEntityRef(ctxt);
if ((ent != NULL) &&
(ctxt->replaceEntities != 0)) {
@@ -3799,19 +3851,16 @@
if (rep != NULL) {
current = rep;
while (*current != 0) {
- *out++ = *current++;
- if (out - buffer > buffer_size - 10) {
- int index = out - buffer;
-
- growBuffer(buffer);
- out = &buffer[index];
+ buf[len++] = *current++;
+ if (len > buf_size - 10) {
+ growBuffer(buf);
}
}
xmlFree(rep);
}
} else {
if (ent->content != NULL)
- *out++ = ent->content[0];
+ buf[len++] = ent->content[0];
}
} else if (ent != NULL) {
int i = xmlStrlen(ent->name);
@@ -3832,41 +3881,32 @@
/*
* Just output the reference
*/
- *out++ = '&';
- if (out - buffer > buffer_size - i - 10) {
- int index = out - buffer;
-
- growBuffer(buffer);
- out = &buffer[index];
+ buf[len++] = '&';
+ if (len > buf_size - i - 10) {
+ growBuffer(buf);
}
for (;i > 0;i--)
- *out++ = *cur++;
- *out++ = ';';
+ buf[len++] = *cur++;
+ buf[len++] = ';';
}
} else {
- /* invalid for UTF-8 , use COPY(out); !!! */
- if ((cur == 0x20) || (cur == 0xD) || (cur == 0xA) || (cur == 0x9)) {
- *out++ = 0x20;
- if (out - buffer > buffer_size - 10) {
- int index = out - buffer;
-
- growBuffer(buffer);
- out = &buffer[index];
+ if ((c == 0x20) || (c == 0xD) || (c == 0xA) || (c == 0x9)) {
+ COPY_BUF(l,buf,len,0x20);
+ if (len > buf_size - 10) {
+ growBuffer(buf);
}
} else {
- *out++ = cur;
- if (out - buffer > buffer_size - 10) {
- int index = out - buffer;
-
- growBuffer(buffer);
- out = &buffer[index];
+ COPY_BUF(l,buf,len,c);
+ if (len > buf_size - 10) {
+ growBuffer(buf);
}
}
- NEXT;
+ NEXTL(l);
}
- cur = CUR;
+ GROW;
+ c = CUR_CHAR(l);
}
- *out++ = 0;
+ buf[len++] = 0;
if (RAW == '<') {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
@@ -3882,7 +3922,7 @@
ctxt->disableSAX = 1;
} else
NEXT;
- return(buffer);
+ return(buf);
}
/**
@@ -6341,7 +6381,7 @@
int hex = NXT(2);
int val = xmlParseCharRef(ctxt);
- if (ctxt->encoding != NULL) {
+ if (ctxt->charset != XML_CHAR_ENCODING_UTF8) {
/*
* So we are using non-UTF-8 buffers
* Check that the char fit on 8bits, if not
@@ -6507,7 +6547,7 @@
ctxt->instate = XML_PARSER_EOF;
return;
}
- if (input->standalone) {
+ if (input->standalone == 1) {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"external parsed entities cannot be standalone\n");
@@ -9558,15 +9598,6 @@
xmlParseTryOrFinish(ctxt, terminate);
if (terminate) {
/*
- * Grab the encoding if it was added on-the-fly
- */
- if ((ctxt->encoding != NULL) && (ctxt->myDoc != NULL) &&
- (ctxt->myDoc->encoding == NULL)) {
- ctxt->myDoc->encoding = ctxt->encoding;
- ctxt->encoding = NULL;
- }
-
- /*
* Check for termination
*/
if ((ctxt->instate != XML_PARSER_EOF) &&
diff --git a/parser.h b/parser.h
index aa7e273..9cb73bd 100644
--- a/parser.h
+++ b/parser.h
@@ -120,8 +120,8 @@
xmlDocPtr myDoc; /* the document being built */
int wellFormed; /* is the document well formed */
int replaceEntities; /* shall we replace entities ? */
- const xmlChar *version; /* the XML version string */
- const xmlChar *encoding; /* encoding, if any */
+ const xmlChar *version; /* the XML version string */
+ const xmlChar *encoding; /* the declared encoding, if any */
int standalone; /* standalone document */
int html; /* are we parsing an HTML document */
@@ -177,7 +177,11 @@
int * spaceTab; /* array of space infos */
int depth; /* to prevent entity substitution loops */
- xmlParserInputPtr entity; /* used to check entities boundaries */
+ xmlParserInputPtr entity; /* used to check entities boundaries */
+ int charset; /* encoding of the in-memory content
+ actually an xmlCharEncoding */
+ int nodelen; /* Those two fields are there to */
+ int nodemem; /* Speed up large node parsing */
};
/**
diff --git a/result/HTML/test3.html b/result/HTML/test3.html
index ad97957..597a1a4 100644
--- a/result/HTML/test3.html
+++ b/result/HTML/test3.html
@@ -1,6 +1,7 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head><base target="contents"></head>
+<body>
<a name="ProblemDomain.Package"><h2>Component Package diagram ProblemDomain</h2></a>
<p>
<hr>
@@ -53,4 +54,5 @@
<a href="DataManagement.Package.html#DataManagement.Package">DataManagement</a>
</li></ul>
<dir></dir>
+</body>
</html>
diff --git a/result/HTML/wired.html b/result/HTML/wired.html
index 509bc1b..d4439bb 100644
--- a/result/HTML/wired.html
+++ b/result/HTML/wired.html
@@ -9,7 +9,7 @@
<td ROWSPAN="2" ALIGN="LEFT" BGCOLOR="FFFFFF"><input TYPE="IMAGE" SRC="http://static.wired.com/advertising/blipverts/allapartments/990625jpa_ssthome.gif" WIDTH="375" HEIGHT="60" BORDER="0" VALUE="search" HSPACE="0" alt="Search over 6,000,000 Apts with SpringStreet"></td>
</tr>
<tr><td BGCOLOR="#330099">
-<select NAME="state"><option VALUE="WA">WA
+<select NAME="state"><option VALUE="WA" SELECTED>WA
<option VALUE="AL">AL</option>
<option VALUE="AK">AK</option>
<option VALUE="AZ">AZ</option>
@@ -89,7 +89,7 @@
<td colspan="2" bgcolor="#999999"><table border="0" cellspacing="0" cellpadding="5"><form name="RedirectSearch" action="http://redirect.wired.com/search"><tr>
<td><font face="courier" size="1"><input type="TEXT" name="query" size="20" value=""></font></td>
<td><select name="url">
-<option value="http://search.hotwired.com/search97/s97.vts?Action=FilterSearch&Filter=docs_filter.hts&ResultTemplate=vignette.hts&Collection=vignette&QueryMode=Internet&Query=">Wired News</option>
+<option value="http://search.hotwired.com/search97/s97.vts?Action=FilterSearch&Filter=docs_filter.hts&ResultTemplate=vignette.hts&Collection=vignette&QueryMode=Internet&Query=" selected>Wired News</option>
<option value="http://search.hotwired.com/search97/s97.vts?Action=FilterSearch&Filter=docs_filter.hts&ResultTemplate=webmonkey.hts&Collection=webmonkey&QueryMode=Internet&Query=">Webmonkey</option>
<option value="http://search.hotwired.com/search97/s97.vts?collection=webmonkey_guides&Action=FilterSearch&filter=docs_filter.hts&ResultTemplate=webmonkey_guides.hts&QueryMode=Internet&Query=">Webmonkey Guides</option>
<option value="http://search.hotwired.com/search97/s97.vts?collection=hotwired&Action=FilterSearch&filter=docs_filter.hts&ResultTemplate=hotwired_archive.hts&QueryMode=Internet&Query=">HotWired Archives</option>
diff --git a/testURI.c b/testURI.c
index 6712119..0cb904c 100644
--- a/testURI.c
+++ b/testURI.c
@@ -17,6 +17,8 @@
#include <stdio.h>
#include <stdarg.h>
+#include <libxml/xmlversion.h>
+#include <libxml/xmlmemory.h>
#include <libxml/uri.h>
int main(int argc, char **argv) {
diff --git a/tree.c b/tree.c
index 74b5321..b81b7a6 100644
--- a/tree.c
+++ b/tree.c
@@ -847,6 +847,80 @@
}
/**
+ * xmlNodeListGetRawString:
+ * @doc: the document
+ * @list: a Node list
+ * @inLine: should we replace entity contents or show their external form
+ *
+ * Returns the string equivalent to the text contained in the Node list
+ * made of TEXTs and ENTITY_REFs, contrary to xmlNodeListGetString()
+ * this function doesn't do any character encoding handling.
+ *
+ * Returns a pointer to the string copy, the calller must free it.
+ */
+xmlChar *
+xmlNodeListGetRawString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
+ xmlNodePtr node = list;
+ xmlChar *ret = NULL;
+ xmlEntityPtr ent;
+
+ if (list == NULL) return(NULL);
+
+ while (node != NULL) {
+ if (node->type == XML_TEXT_NODE) {
+ if (inLine) {
+#ifndef XML_USE_BUFFER_CONTENT
+ ret = xmlStrcat(ret, node->content);
+#else
+ ret = xmlStrcat(ret, xmlBufferContent(node->content));
+#endif
+ } else {
+ xmlChar *buffer;
+
+#ifndef XML_USE_BUFFER_CONTENT
+ buffer = xmlEncodeSpecialChars(doc, node->content);
+#else
+ buffer = xmlEncodeSpecialChars(doc,
+ xmlBufferContent(node->content));
+#endif
+ if (buffer != NULL) {
+ ret = xmlStrcat(ret, buffer);
+ xmlFree(buffer);
+ }
+ }
+ } else if (node->type == XML_ENTITY_REF_NODE) {
+ if (inLine) {
+ ent = xmlGetDocEntity(doc, node->name);
+ if (ent != NULL)
+ ret = xmlStrcat(ret, ent->content);
+ else {
+#ifndef XML_USE_BUFFER_CONTENT
+ ret = xmlStrcat(ret, node->content);
+#else
+ ret = xmlStrcat(ret, xmlBufferContent(node->content));
+#endif
+ }
+ } else {
+ xmlChar buf[2];
+ buf[0] = '&'; buf[1] = 0;
+ ret = xmlStrncat(ret, buf, 1);
+ ret = xmlStrcat(ret, node->name);
+ buf[0] = ';'; buf[1] = 0;
+ ret = xmlStrncat(ret, buf, 1);
+ }
+ }
+#if 0
+ else {
+ fprintf(stderr, "xmlGetNodeListString : invalide node type %d\n",
+ node->type);
+ }
+#endif
+ node = node->next;
+ }
+ return(ret);
+}
+
+/**
* xmlNewProp:
* @node: the holding node
* @name: the name of the attribute
@@ -3787,7 +3861,7 @@
if (len <= buf->use) return(0);
- size = buf->size + buf->use + len + 100;
+ size = buf->use + len + 100;
newbuf = xmlRealloc(buf->content, size);
if (newbuf == NULL) return(-1);
@@ -3949,6 +4023,52 @@
}
/**
+ * xmlBufferAddHead:
+ * @buf: the buffer
+ * @str: the xmlChar string
+ * @len: the number of xmlChar to add
+ *
+ * Add a string range to the beginning of an XML buffer.
+ * if len == -1, the lenght of @str is recomputed.
+ */
+void
+xmlBufferAddHead(xmlBufferPtr buf, const xmlChar *str, int len) {
+ int needSize;
+
+ if (str == NULL) {
+#ifdef DEBUG_BUFFER
+ fprintf(stderr, "xmlBufferAdd: str == NULL\n");
+#endif
+ return;
+ }
+ if (len < -1) {
+#ifdef DEBUG_BUFFER
+ fprintf(stderr, "xmlBufferAdd: len < 0\n");
+#endif
+ return;
+ }
+ if (len == 0) return;
+
+ if (len < 0)
+ len = xmlStrlen(str);
+
+ if (len <= 0) return;
+
+ needSize = buf->use + len + 2;
+ if(needSize > buf->size){
+ if(!xmlBufferResize(buf, needSize)){
+ fprintf(stderr, "xmlBufferAddHead : out of memory!\n");
+ return;
+ }
+ }
+
+ memmove(&buf->content[len], &buf->content[0], buf->use * sizeof(xmlChar));
+ memmove(&buf->content[0], str, len * sizeof(xmlChar));
+ buf->use += len;
+ buf->content[buf->use] = 0;
+}
+
+/**
* xmlBufferCat:
* @buf: the buffer to dump
* @str: the xmlChar string
@@ -4045,6 +4165,12 @@
}
+/************************************************************************
+ * *
+ * Dumping XML tree content to a simple buffer *
+ * *
+ ************************************************************************/
+
static void
xmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level,
int format);
@@ -4528,6 +4654,489 @@
}
}
+/************************************************************************
+ * *
+ * Dumping XML tree content to an I/O output buffer *
+ * *
+ ************************************************************************/
+
+static void
+xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
+ int level, int format, const char *encoding);
+static void
+xmlNodeListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
+ int level, int format, const char *encoding);
+/**
+ * xmlGlobalNsDumpOutput:
+ * @buf: the XML buffer output
+ * @cur: a namespace
+ *
+ * Dump a global Namespace, this is the old version based on PIs.
+ */
+static void
+xmlGlobalNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
+ if (cur == NULL) {
+#ifdef DEBUG_TREE
+ fprintf(stderr, "xmlGlobalNsDump : Ns == NULL\n");
+#endif
+ return;
+ }
+ if (cur->type == XML_GLOBAL_NAMESPACE) {
+ xmlOutputBufferWriteString(buf, "<?namespace");
+ if (cur->href != NULL) {
+ xmlOutputBufferWriteString(buf, " href=");
+ xmlBufferWriteQuotedString(buf->buffer, cur->href);
+ }
+ if (cur->prefix != NULL) {
+ xmlOutputBufferWriteString(buf, " AS=");
+ xmlBufferWriteQuotedString(buf->buffer, cur->prefix);
+ }
+ xmlOutputBufferWriteString(buf, "?>\n");
+ }
+}
+
+/**
+ * xmlGlobalNsListDumpOutput:
+ * @buf: the XML buffer output
+ * @cur: the first namespace
+ *
+ * Dump a list of global Namespace, this is the old version based on PIs.
+ */
+static void
+xmlGlobalNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
+ while (cur != NULL) {
+ xmlGlobalNsDumpOutput(buf, cur);
+ cur = cur->next;
+ }
+}
+
+/**
+ * xmlNsDumpOutput:
+ * @buf: the XML buffer output
+ * @cur: a namespace
+ *
+ * Dump a local Namespace definition.
+ * Should be called in the context of attributes dumps.
+ */
+static void
+xmlNsDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
+ if (cur == NULL) {
+#ifdef DEBUG_TREE
+ fprintf(stderr, "xmlNsDump : Ns == NULL\n");
+#endif
+ return;
+ }
+ if (cur->type == XML_LOCAL_NAMESPACE) {
+ /* Within the context of an element attributes */
+ if (cur->prefix != NULL) {
+ xmlOutputBufferWriteString(buf, " xmlns:");
+ xmlOutputBufferWriteString(buf, (const char *)cur->prefix);
+ } else
+ xmlOutputBufferWriteString(buf, " xmlns");
+ xmlOutputBufferWriteString(buf, "=");
+ xmlBufferWriteQuotedString(buf->buffer, cur->href);
+ }
+}
+
+/**
+ * xmlNsListDumpOutput:
+ * @buf: the XML buffer output
+ * @cur: the first namespace
+ *
+ * Dump a list of local Namespace definitions.
+ * Should be called in the context of attributes dumps.
+ */
+static void
+xmlNsListDumpOutput(xmlOutputBufferPtr buf, xmlNsPtr cur) {
+ while (cur != NULL) {
+ xmlNsDumpOutput(buf, cur);
+ cur = cur->next;
+ }
+}
+
+/**
+ * xmlDtdDumpOutput:
+ * @buf: the XML buffer output
+ * @doc: the document
+ * @encoding: an optional encoding string
+ *
+ * Dump the XML document DTD, if any.
+ */
+static void
+xmlDtdDumpOutput(xmlOutputBufferPtr buf, xmlDtdPtr dtd, const char *encoding) {
+ if (dtd == NULL) {
+#ifdef DEBUG_TREE
+ fprintf(stderr, "xmlDtdDump : no internal subset\n");
+#endif
+ return;
+ }
+ xmlOutputBufferWriteString(buf, "<!DOCTYPE ");
+ xmlOutputBufferWriteString(buf, (const char *)dtd->name);
+ if (dtd->ExternalID != NULL) {
+ xmlOutputBufferWriteString(buf, " PUBLIC ");
+ xmlBufferWriteQuotedString(buf->buffer, dtd->ExternalID);
+ xmlOutputBufferWriteString(buf, " ");
+ xmlBufferWriteQuotedString(buf->buffer, dtd->SystemID);
+ } else if (dtd->SystemID != NULL) {
+ xmlOutputBufferWriteString(buf, " SYSTEM ");
+ xmlBufferWriteQuotedString(buf->buffer, dtd->SystemID);
+ }
+ if ((dtd->entities == NULL) && (dtd->elements == NULL) &&
+ (dtd->attributes == NULL) && (dtd->notations == NULL)) {
+ xmlOutputBufferWriteString(buf, ">");
+ return;
+ }
+ xmlOutputBufferWriteString(buf, " [\n");
+ xmlNodeListDumpOutput(buf, dtd->doc, dtd->children, -1, 0, encoding);
+#if 0
+ if (dtd->entities != NULL)
+ xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) dtd->entities);
+ if (dtd->notations != NULL)
+ xmlDumpNotationTable(buf, (xmlNotationTablePtr) dtd->notations);
+ if (dtd->elements != NULL)
+ xmlDumpElementTable(buf, (xmlElementTablePtr) dtd->elements);
+ if (dtd->attributes != NULL)
+ xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) dtd->attributes);
+#endif
+ xmlOutputBufferWriteString(buf, "]>");
+}
+
+/**
+ * xmlAttrDumpOutput:
+ * @buf: the XML buffer output
+ * @doc: the document
+ * @cur: the attribute pointer
+ * @encoding: an optional encoding string
+ *
+ * Dump an XML attribute
+ */
+static void
+xmlAttrDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur,
+ const char *encoding) {
+ xmlChar *value;
+
+ if (cur == NULL) {
+#ifdef DEBUG_TREE
+ fprintf(stderr, "xmlAttrDump : property == NULL\n");
+#endif
+ return;
+ }
+ xmlOutputBufferWriteString(buf, " ");
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+ xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
+ 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, "=\"\"");
+ }
+}
+
+/**
+ * xmlAttrListDumpOutput:
+ * @buf: the XML buffer output
+ * @doc: the document
+ * @cur: the first attribute pointer
+ * @encoding: an optional encoding string
+ *
+ * Dump a list of XML attributes
+ */
+static void
+xmlAttrListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
+ xmlAttrPtr cur, const char *encoding) {
+ if (cur == NULL) {
+#ifdef DEBUG_TREE
+ fprintf(stderr, "xmlAttrListDump : property == NULL\n");
+#endif
+ return;
+ }
+ while (cur != NULL) {
+ xmlAttrDumpOutput(buf, doc, cur, encoding);
+ cur = cur->next;
+ }
+}
+
+
+
+/**
+ * xmlNodeListDumpOutput:
+ * @buf: the XML buffer output
+ * @doc: the document
+ * @cur: the first node
+ * @level: the imbrication level for indenting
+ * @format: is formatting allowed
+ * @encoding: an optional encoding string
+ *
+ * Dump an XML node list, recursive behaviour,children are printed too.
+ */
+static void
+xmlNodeListDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc,
+ xmlNodePtr cur, int level, int format, const char *encoding) {
+ int i;
+
+ if (cur == NULL) {
+#ifdef DEBUG_TREE
+ fprintf(stderr, "xmlNodeListDump : node == NULL\n");
+#endif
+ return;
+ }
+ while (cur != NULL) {
+ if ((format) && (xmlIndentTreeOutput) &&
+ (cur->type == XML_ELEMENT_NODE))
+ for (i = 0;i < level;i++)
+ xmlOutputBufferWriteString(buf, " ");
+ xmlNodeDumpOutput(buf, doc, cur, level, format, encoding);
+ if (format) {
+ xmlOutputBufferWriteString(buf, "\n");
+ }
+ cur = cur->next;
+ }
+}
+
+/**
+ * xmlNodeDumpOutput:
+ * @buf: the XML buffer output
+ * @doc: the document
+ * @cur: the current node
+ * @level: the imbrication level for indenting
+ * @format: is formatting allowed
+ * @encoding: an optional encoding string
+ *
+ * Dump an XML node, recursive behaviour,children are printed too.
+ */
+static void
+xmlNodeDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur,
+ int level, int format, const char *encoding) {
+ int i;
+ xmlNodePtr tmp;
+
+ if (cur == NULL) {
+#ifdef DEBUG_TREE
+ fprintf(stderr, "xmlNodeDump : node == NULL\n");
+#endif
+ return;
+ }
+ if (cur->type == XML_DTD_NODE) {
+ xmlDtdDumpOutput(buf, (xmlDtdPtr) cur, encoding);
+ return;
+ }
+ if (cur->type == XML_ELEMENT_DECL) {
+ xmlDumpElementDecl(buf->buffer, (xmlElementPtr) cur);
+ return;
+ }
+ if (cur->type == XML_ATTRIBUTE_DECL) {
+ xmlDumpAttributeDecl(buf->buffer, (xmlAttributePtr) cur);
+ return;
+ }
+ if (cur->type == XML_ENTITY_DECL) {
+ xmlDumpEntityDecl(buf->buffer, (xmlEntityPtr) cur);
+ return;
+ }
+ if (cur->type == XML_TEXT_NODE) {
+ if (cur->content != NULL) {
+ xmlChar *buffer;
+
+#ifndef XML_USE_BUFFER_CONTENT
+ if (encoding == NULL)
+ buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
+ else
+ buffer = xmlEncodeSpecialChars(doc, cur->content);
+#else
+ if (encoding == NULL)
+ buffer = xmlEncodeEntitiesReentrant(doc,
+ xmlBufferContent(cur->content));
+ else
+ buffer = xmlEncodeSpecialChars(doc,
+ xmlBufferContent(cur->content));
+#endif
+ if (buffer != NULL) {
+ xmlOutputBufferWriteString(buf, (const char *)buffer);
+ xmlFree(buffer);
+ }
+ }
+ return;
+ }
+ if (cur->type == XML_PI_NODE) {
+ if (cur->content != NULL) {
+ xmlOutputBufferWriteString(buf, "<?");
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ if (cur->content != NULL) {
+ xmlOutputBufferWriteString(buf, " ");
+#ifndef XML_USE_BUFFER_CONTENT
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
+#else
+ xmlOutputBufferWriteString(buf, (const char *)xmlBufferContent(cur->content));
+#endif
+ }
+ xmlOutputBufferWriteString(buf, "?>");
+ } else {
+ xmlOutputBufferWriteString(buf, "<?");
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ xmlOutputBufferWriteString(buf, "?>");
+ }
+ return;
+ }
+ if (cur->type == XML_COMMENT_NODE) {
+ if (cur->content != NULL) {
+ xmlOutputBufferWriteString(buf, "<!--");
+#ifndef XML_USE_BUFFER_CONTENT
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
+#else
+ xmlOutputBufferWriteString(buf, (const char *)xmlBufferContent(cur->content));
+#endif
+ xmlOutputBufferWriteString(buf, "-->");
+ }
+ return;
+ }
+ if (cur->type == XML_ENTITY_REF_NODE) {
+ xmlOutputBufferWriteString(buf, "&");
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ xmlOutputBufferWriteString(buf, ";");
+ return;
+ }
+ if (cur->type == XML_CDATA_SECTION_NODE) {
+ xmlOutputBufferWriteString(buf, "<![CDATA[");
+ if (cur->content != NULL)
+#ifndef XML_USE_BUFFER_CONTENT
+ xmlOutputBufferWriteString(buf, (const char *)cur->content);
+#else
+ xmlOutputBufferWriteString(buf, (const char *)xmlBufferContent(cur->content));
+#endif
+ xmlOutputBufferWriteString(buf, "]]>");
+ return;
+ }
+
+ if (format == 1) {
+ tmp = cur->children;
+ while (tmp != NULL) {
+ if ((tmp->type == XML_TEXT_NODE) ||
+ (tmp->type == XML_ENTITY_REF_NODE)) {
+ format = 0;
+ break;
+ }
+ tmp = tmp->next;
+ }
+ }
+ xmlOutputBufferWriteString(buf, "<");
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+ xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
+ xmlOutputBufferWriteString(buf, ":");
+ }
+
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ if (cur->nsDef)
+ xmlNsListDumpOutput(buf, cur->nsDef);
+ if (cur->properties != NULL)
+ xmlAttrListDumpOutput(buf, doc, cur->properties, encoding);
+
+ if ((cur->content == NULL) && (cur->children == NULL) &&
+ (!xmlSaveNoEmptyTags)) {
+ xmlOutputBufferWriteString(buf, "/>");
+ return;
+ }
+ xmlOutputBufferWriteString(buf, ">");
+ if (cur->content != NULL) {
+ xmlChar *buffer;
+
+#ifndef XML_USE_BUFFER_CONTENT
+ if (encoding == NULL)
+ buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
+ else
+ buffer = xmlEncodeSpecialChars(doc, cur->content);
+#else
+ if (encoding == NULL)
+ buffer = xmlEncodeEntitiesReentrant(doc,
+ xmlBufferContent(cur->content));
+ else
+ buffer = xmlEncodeSpecialChars(doc,
+ xmlBufferContent(cur->content));
+#endif
+ if (buffer != NULL) {
+ xmlOutputBufferWriteString(buf, (const char *)buffer);
+ xmlFree(buffer);
+ }
+ }
+ if (cur->children != NULL) {
+ if (format) xmlOutputBufferWriteString(buf, "\n");
+ xmlNodeListDumpOutput(buf, doc, cur->children,
+ (level >= 0?level+1:-1), format, encoding);
+ if ((xmlIndentTreeOutput) && (format))
+ for (i = 0;i < level;i++)
+ xmlOutputBufferWriteString(buf, " ");
+ }
+ xmlOutputBufferWriteString(buf, "</");
+ if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
+ xmlOutputBufferWriteString(buf, (const char *)cur->ns->prefix);
+ xmlOutputBufferWriteString(buf, ":");
+ }
+
+ xmlOutputBufferWriteString(buf, (const char *)cur->name);
+ xmlOutputBufferWriteString(buf, ">");
+}
+
+/**
+ * xmlDocContentDumpOutput:
+ * @buf: the XML buffer output
+ * @cur: the document
+ * @encoding: an optional encoding string
+ *
+ * Dump an XML document.
+ */
+static void
+xmlDocContentDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr cur,
+ const char *encoding) {
+ xmlOutputBufferWriteString(buf, "<?xml version=");
+ if (cur->version != NULL)
+ xmlBufferWriteQuotedString(buf->buffer, cur->version);
+ else
+ xmlOutputBufferWriteString(buf, "\"1.0\"");
+ if (encoding == NULL) {
+ if (cur->encoding != NULL)
+ encoding = (const char *) cur->encoding;
+ else if (cur->charset != XML_CHAR_ENCODING_UTF8)
+ encoding = xmlGetCharEncodingName(cur->charset);
+ }
+ if (encoding != NULL) {
+ xmlOutputBufferWriteString(buf, " encoding=");
+ xmlBufferWriteQuotedString(buf->buffer, (xmlChar *) encoding);
+ }
+ switch (cur->standalone) {
+ case 0:
+ xmlOutputBufferWriteString(buf, " standalone=\"no\"");
+ break;
+ case 1:
+ xmlOutputBufferWriteString(buf, " standalone=\"yes\"");
+ break;
+ }
+ xmlOutputBufferWriteString(buf, "?>\n");
+ if (cur->children != NULL) {
+ xmlNodePtr child = cur->children;
+
+ /* global namespace definitions, the old way */
+ if (oldXMLWDcompatibility)
+ xmlGlobalNsListDumpOutput(buf, cur->oldNs);
+ else
+ xmlUpgradeOldNs(cur);
+
+ while (child != NULL) {
+ xmlNodeDumpOutput(buf, cur, child, 0, 1, encoding);
+ xmlOutputBufferWriteString(buf, "\n");
+ child = child->next;
+ }
+ }
+}
+
+/************************************************************************
+ * *
+ * Saving functions front-ends *
+ * *
+ ************************************************************************/
+
/**
* xmlDocDumpMemory:
* @cur: the document
@@ -4615,6 +5224,7 @@
else xmlCompressMode = mode;
}
+#if 0
/**
* xmlDocDump:
* @f: the FILE*
@@ -4698,4 +5308,128 @@
xmlBufferFree(buf);
return(ret * sizeof(xmlChar));
}
+#else
+/**
+ * xmlDocDump:
+ * @f: the FILE*
+ * @cur: the document
+ *
+ * Dump an XML document to an open FILE.
+ *
+ * returns: the number of file written or -1 in case of failure.
+ */
+int
+xmlDocDump(FILE *f, xmlDocPtr cur) {
+ xmlOutputBufferPtr buf;
+ int ret;
+ if (cur == NULL) {
+#ifdef DEBUG_TREE
+ fprintf(stderr, "xmlDocDump : document == NULL\n");
+#endif
+ return(-1);
+ }
+ buf = xmlOutputBufferCreateFile(f, NULL);
+ if (buf == NULL) return(-1);
+ xmlDocContentDumpOutput(buf, cur, NULL);
+
+ ret = xmlOutputBufferClose(buf);
+ return(ret);
+}
+
+/**
+ * xmlSaveFile:
+ * @filename: the filename (or URL)
+ * @cur: the document
+ *
+ * Dump an XML document to a file. Will use compression if
+ * compiled in and enabled. If @filename is "-" the stdout file is
+ * used.
+ * returns: the number of file written or -1 in case of failure.
+ */
+int
+xmlSaveFile(const char *filename, xmlDocPtr cur) {
+ xmlOutputBufferPtr buf;
+ int ret;
+
+ /*
+ * save the content to a temp buffer.
+ */
+#ifdef HAVE_ZLIB_H
+ if (cur->compression < 0) cur->compression = xmlCompressMode;
+#endif
+ buf = xmlOutputBufferCreateFilename(filename, NULL, cur->compression);
+ if (buf == NULL) return(0);
+
+ xmlDocContentDumpOutput(buf, cur, NULL);
+
+ ret = xmlOutputBufferClose(buf);
+ return(ret);
+}
+
+/**
+ * xmlSaveFileTo:
+ * @buf: an output I/O buffer
+ * @cur: the document
+ * @encoding: the encoding if any assuming the i/O layer handles the trancoding
+ *
+ * Dump an XML document to an I/O buffer.
+ *
+ * returns: the number of file written or -1 in case of failure.
+ */
+int
+xmlSaveFileTo(xmlOutputBuffer *buf, xmlDocPtr cur, const char *encoding) {
+ int ret;
+
+ if (buf == NULL) return(0);
+ xmlDocContentDumpOutput(buf, cur, encoding);
+ ret = xmlOutputBufferClose(buf);
+ return(ret);
+}
+
+/**
+ * xmlSaveFileEnc:
+ * @filename: the filename (or URL)
+ * @cur: the document
+ * @encoding: the name of an encoding (or NULL)
+ *
+ * Dump an XML document, converting it to the given encoding
+ *
+ * returns: the number of file written or -1 in case of failure.
+ */
+int
+xmlSaveFileEnc(const char *filename, xmlDocPtr cur, const char *encoding) {
+ xmlOutputBufferPtr buf;
+ xmlCharEncodingHandlerPtr handler = NULL;
+ int ret;
+
+ if (encoding != NULL) {
+ xmlCharEncoding enc;
+
+ enc = xmlParseCharEncoding(encoding);
+ if (enc != cur->charset) {
+ if (cur->charset != XML_CHAR_ENCODING_UTF8) {
+ /*
+ * Not supported yet
+ */
+ return(-1);
+ }
+
+ handler = xmlFindCharEncodingHandler(encoding);
+ if (handler == NULL)
+ return(-1);
+ }
+ }
+
+ /*
+ * save the content to a temp buffer.
+ */
+ buf = xmlOutputBufferCreateFilename(filename, handler, 0);
+ if (buf == NULL) return(0);
+
+ xmlDocContentDumpOutput(buf, cur, encoding);
+
+ ret = xmlOutputBufferClose(buf);
+ return(ret);
+}
+#endif
diff --git a/tree.h b/tree.h
index 35ea525..9c5b280 100644
--- a/tree.h
+++ b/tree.h
@@ -181,6 +181,7 @@
xmlElementTypeVal etype; /* The type */
xmlElementContentPtr content; /* the allowed element content */
xmlAttributePtr attributes; /* List of the declared attributes */
+ const xmlChar *prefix; /* the namespace prefix if any */
};
/*
@@ -347,13 +348,23 @@
struct _xmlDtd *extSubset; /* the document external subset */
struct _xmlNs *oldNs; /* Global namespace, the old way */
const xmlChar *version; /* the XML version string */
- const xmlChar *encoding; /* encoding, if any */
+ const xmlChar *encoding; /* external initial encoding, if any */
void *ids; /* Hash table for ID attributes if any */
void *refs; /* Hash table for IDREFs attributes if any */
const xmlChar *URL; /* The URI for that document */
+ int charset; /* encoding of the in-memory content
+ actually an xmlCharEncoding */
};
/*
+ * Compatibility naming layer with libxml1
+ */
+#ifndef xmlChildrenNode
+#define xmlChildrenNode children
+#define xmlRootNode children
+#endif
+
+/*
* Variables.
*/
extern xmlNsPtr baseDTD;
@@ -374,6 +385,9 @@
void xmlBufferAdd (xmlBufferPtr buf,
const xmlChar *str,
int len);
+void xmlBufferAddHead (xmlBufferPtr buf,
+ const xmlChar *str,
+ int len);
void xmlBufferCat (xmlBufferPtr buf,
const xmlChar *str);
void xmlBufferCCat (xmlBufferPtr buf,
@@ -545,6 +559,9 @@
xmlChar * xmlNodeListGetString (xmlDocPtr doc,
xmlNodePtr list,
int inLine);
+xmlChar * xmlNodeListGetRawString (xmlDocPtr doc,
+ xmlNodePtr list,
+ int inLine);
void xmlNodeSetContent (xmlNodePtr cur,
const xmlChar *content);
void xmlNodeSetContentLen (xmlNodePtr cur,
@@ -591,7 +608,7 @@
void xmlDocDumpMemory (xmlDocPtr cur,
xmlChar**mem,
int *size);
-void xmlDocDump (FILE *f,
+int xmlDocDump (FILE *f,
xmlDocPtr cur);
void xmlElemDump (FILE *f,
xmlDocPtr doc,
@@ -599,6 +616,17 @@
int xmlSaveFile (const char *filename,
xmlDocPtr cur);
+/* This one is exported from xmlIO.h
+
+int xmlSaveFileTo (xmlOutputBuffer *buf,
+ xmlDocPtr cur,
+ const char *encoding);
+ */
+
+int xmlSaveFileEnc (const char *filename,
+ xmlDocPtr cur,
+ const char *encoding);
+
/*
* Compression
*/
diff --git a/uri.c b/uri.c
index 6000d39..ac7aa0b 100644
--- a/uri.c
+++ b/uri.c
@@ -1513,7 +1513,10 @@
val = xmlSaveUri(ref);
goto done;
}
- res->scheme = xmlMemStrdup(bas->scheme);
+ if (bas->scheme != NULL)
+ res->scheme = xmlMemStrdup(bas->scheme);
+ else
+ res->scheme = NULL;
/*
* 4) If the authority component is defined, then the reference is a
diff --git a/uri.h b/uri.h
index 59c4467..705e385 100644
--- a/uri.h
+++ b/uri.h
@@ -43,6 +43,8 @@
xmlChar * xmlBuildURI (const xmlChar *URI,
const xmlChar *base);
xmlURIPtr xmlParseURI (const char *URI);
+int xmlParseURIReference (xmlURIPtr uri,
+ const char *str);
xmlChar * xmlSaveUri (xmlURIPtr uri);
void xmlPrintURI (FILE *stream,
xmlURIPtr uri);
diff --git a/valid.c b/valid.c
index bc66ac5..5dc37ed 100644
--- a/valid.c
+++ b/valid.c
@@ -154,6 +154,61 @@
xmlElementPtr xmlGetDtdElementDesc(xmlDtdPtr dtd, const xmlChar *name);
xmlAttributePtr xmlScanAttributeDecl(xmlDtdPtr dtd, const xmlChar *elem);
+/************************************************************************
+ * *
+ * QName handling helper *
+ * *
+ ************************************************************************/
+
+/**
+ * xmlSplitQName2:
+ * @name: an XML parser context
+ * @prefix: a xmlChar **
+ *
+ * parse an XML qualified name string
+ *
+ * [NS 5] QName ::= (Prefix ':')? LocalPart
+ *
+ * [NS 6] Prefix ::= NCName
+ *
+ * [NS 7] LocalPart ::= NCName
+ *
+ * Returns NULL if not a QName, otherwise the local part, and prefix
+ * is updated to get the Prefix if any.
+ */
+
+xmlChar *
+xmlSplitQName2(const xmlChar *name, xmlChar **prefix) {
+ int len = 0;
+ xmlChar *ret = NULL;
+
+ *prefix = NULL;
+
+ /* xml: prefix is not really a namespace */
+ if ((name[0] == 'x') && (name[1] == 'm') &&
+ (name[2] == 'l') && (name[3] == ':'))
+ return(NULL);
+
+ /* nasty but valid */
+ if (name[0] == ':')
+ return(NULL);
+
+ /*
+ * we are not trying to validate but just to cut, and yes it will
+ * work even if this is as set of UTF-8 encoded chars
+ */
+ while ((name[len] != 0) && (name[len] != ':'))
+ len++;
+
+ if (name[len] == 0)
+ return(NULL);
+
+ *prefix = xmlStrndup(name, len);
+ ret = xmlStrdup(&name[len + 1]);
+
+ return(ret);
+}
+
/****************************************************************
* *
* Util functions for data allocation/deallocation *
@@ -428,6 +483,7 @@
xmlElementContentPtr content) {
xmlElementPtr ret, cur;
xmlElementTablePtr table;
+ xmlChar *ns, *uqname;
int i;
if (dtd == NULL) {
@@ -473,6 +529,13 @@
}
/*
+ * check if name is a QName
+ */
+ uqname = xmlSplitQName2(name, &ns);
+ if (uqname != NULL)
+ name = uqname;
+
+ /*
* Create the Element table if needed.
*/
table = dtd->elements;
@@ -489,7 +552,10 @@
*/
for (i = 0;i < table->nb_elements;i++) {
cur = table->table[i];
- if (!xmlStrcmp(cur->name, name)) {
+ if ((ns != NULL) && (cur->prefix == NULL)) continue;
+ if ((ns == NULL) && (cur->prefix != NULL)) continue;
+ if ((!xmlStrcmp(cur->name, name)) &&
+ ((ns == NULL) || (!xmlStrcmp(cur->prefix, ns)))) {
/*
* The element is already defined in this Dtd.
*/
@@ -527,6 +593,7 @@
*/
ret->etype = type;
ret->name = xmlStrdup(name);
+ ret->prefix = ns;
ret->content = xmlCopyElementContent(content);
ret->attributes = xmlScanAttributeDecl(dtd, name);
table->nb_elements++;
@@ -543,6 +610,8 @@
ret->prev = dtd->last;
dtd->last = (xmlNodePtr) ret;
}
+ if (uqname != NULL)
+ xmlFree(uqname);
return(ret);
}
@@ -559,6 +628,8 @@
xmlFreeElementContent(elem->content);
if (elem->name != NULL)
xmlFree((xmlChar *) elem->name);
+ if (elem->prefix != NULL)
+ xmlFree((xmlChar *) elem->prefix);
memset(elem, -1, sizeof(xmlElement));
xmlFree(elem);
}
@@ -896,7 +967,7 @@
*
* Register a new attribute declaration
*
- * Returns NULL if not, othervise the entity
+ * Returns NULL if not new, othervise the attribute decl
*/
xmlAttributePtr
xmlAddAttributeDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *elem,
@@ -981,6 +1052,7 @@
*/
VWARNING(ctxt->userData, "Attribute %s on %s: already defined\n",
elem, name);
+ return(NULL);
}
}
@@ -1157,6 +1229,10 @@
xmlBufferWriteChar(buf, "<!ATTLIST ");
xmlBufferWriteCHAR(buf, attr->elem);
xmlBufferWriteChar(buf, " ");
+ if (attr->prefix != NULL) {
+ xmlBufferWriteCHAR(buf, attr->prefix);
+ xmlBufferWriteChar(buf, ":");
+ }
xmlBufferWriteCHAR(buf, attr->name);
switch (attr->atype) {
case XML_ATTRIBUTE_CDATA:
@@ -2066,6 +2142,7 @@
xmlGetDtdElementDesc(xmlDtdPtr dtd, const xmlChar *name) {
xmlElementTablePtr table;
xmlElementPtr cur;
+ xmlChar *uqname = NULL, *prefix = NULL;
int i;
if (dtd == NULL) return(NULL);
@@ -2077,6 +2154,59 @@
if (!xmlStrcmp(cur->name, name))
return(cur);
}
+
+ /*
+ * Specific case if name is a QName.
+ */
+ uqname = xmlSplitQName2(name, &prefix);
+ if (uqname == NULL) return(NULL);
+
+ for (i = 0;i < table->nb_elements;i++) {
+ cur = table->table[i];
+ if ((!xmlStrcmp(cur->name, uqname)) &&
+ ((prefix == cur->prefix) ||
+ ((prefix != NULL) && (cur->prefix != NULL) &&
+ (!xmlStrcmp(cur->prefix, prefix))))) {
+ if (prefix != NULL) xmlFree(prefix);
+ if (uqname != NULL) xmlFree(uqname);
+ return(cur);
+ }
+ }
+ if (prefix != NULL) xmlFree(prefix);
+ if (uqname != NULL) xmlFree(uqname);
+ return(NULL);
+}
+
+/**
+ * xmlGetDtdQElementDesc:
+ * @dtd: a pointer to the DtD to search
+ * @name: the element name
+ * @prefix: the element namespace prefix
+ *
+ * Search the Dtd for the description of this element
+ *
+ * returns the xmlElementPtr if found or NULL
+ */
+
+xmlElementPtr
+xmlGetDtdQElementDesc(xmlDtdPtr dtd, const xmlChar *name,
+ const xmlChar *prefix) {
+ xmlElementTablePtr table;
+ xmlElementPtr cur;
+ int i;
+
+ if (dtd == NULL) return(NULL);
+ if (dtd->elements == NULL) return(NULL);
+ table = dtd->elements;
+
+ for (i = 0;i < table->nb_elements;i++) {
+ cur = table->table[i];
+ if (!xmlStrcmp(cur->name, name) &&
+ ((prefix == cur->prefix) ||
+ ((prefix != NULL) && (cur->prefix != NULL) &&
+ (!xmlStrcmp(cur->prefix, prefix)))))
+ return(cur);
+ }
return(NULL);
}
@@ -2096,6 +2226,7 @@
xmlGetDtdAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name) {
xmlAttributeTablePtr table;
xmlAttributePtr cur;
+ xmlChar *uqname = NULL, *prefix = NULL;
int i;
if (dtd == NULL) return(NULL);
@@ -2108,6 +2239,63 @@
(!xmlStrcmp(cur->elem, elem)))
return(cur);
}
+
+ /*
+ * Specific case if name is a QName.
+ */
+ uqname = xmlSplitQName2(name, &prefix);
+ if (uqname == NULL) return(NULL);
+
+ for (i = 0;i < table->nb_attributes;i++) {
+ cur = table->table[i];
+ if ((!xmlStrcmp(cur->name, uqname)) &&
+ (!xmlStrcmp(cur->elem, elem)) &&
+ ((prefix == cur->prefix) ||
+ ((prefix != NULL) && (cur->prefix != NULL) &&
+ (!xmlStrcmp(cur->prefix, prefix))))) {
+ if (prefix != NULL) xmlFree(prefix);
+ if (uqname != NULL) xmlFree(uqname);
+ return(cur);
+ }
+ }
+ if (prefix != NULL) xmlFree(prefix);
+ if (uqname != NULL) xmlFree(uqname);
+ return(NULL);
+}
+
+/**
+ * xmlGetDtdQAttrDesc:
+ * @dtd: a pointer to the DtD to search
+ * @elem: the element name
+ * @name: the attribute name
+ * @prefix: the attribute namespace prefix
+ *
+ * Search the Dtd for the description of this qualified attribute on
+ * this element.
+ *
+ * returns the xmlAttributePtr if found or NULL
+ */
+
+xmlAttributePtr
+xmlGetDtdQAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name,
+ const xmlChar *prefix) {
+ xmlAttributeTablePtr table;
+ xmlAttributePtr cur;
+ int i;
+
+ if (dtd == NULL) return(NULL);
+ if (dtd->attributes == NULL) return(NULL);
+ table = dtd->attributes;
+
+ for (i = 0;i < table->nb_attributes;i++) {
+ cur = table->table[i];
+ if ((!xmlStrcmp(cur->name, name)) &&
+ (!xmlStrcmp(cur->elem, elem)) &&
+ ((prefix == cur->prefix) ||
+ ((prefix != NULL) && (cur->prefix != NULL) &&
+ (!xmlStrcmp(cur->prefix, prefix)))))
+ return(cur);
+ }
return(NULL);
}
@@ -2586,13 +2774,25 @@
const xmlChar *name, const xmlChar *value) {
xmlChar *ret, *dst;
const xmlChar *src;
- xmlAttributePtr attrDecl;
+ xmlAttributePtr attrDecl = NULL;
if (doc == NULL) return(NULL);
if (elem == NULL) return(NULL);
if (name == NULL) return(NULL);
if (value == NULL) return(NULL);
+ if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
+ xmlChar qname[500];
+#ifdef HAVE_SNPRINTF
+ snprintf((char *) qname, sizeof(qname), "%s:%s",
+ elem->ns->prefix, elem->name);
+#else
+ sprintf(qname, "%s:%s", elem->name, elem->ns->prefix);
+#endif
+ attrDecl = xmlGetDtdAttrDesc(doc->intSubset, qname, name);
+ if ((attrDecl == NULL) && (doc->extSubset != NULL))
+ attrDecl = xmlGetDtdAttrDesc(doc->extSubset, qname, name);
+ }
attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, name);
if ((attrDecl == NULL) && (doc->extSubset != NULL))
attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name, name);
@@ -2850,7 +3050,7 @@
xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
xmlNodePtr elem, xmlAttrPtr attr, const xmlChar *value) {
/* xmlElementPtr elemDecl; */
- xmlAttributePtr attrDecl;
+ xmlAttributePtr attrDecl = NULL;
int val;
int ret = 1;
@@ -2858,9 +3058,42 @@
if ((elem == NULL) || (elem->name == NULL)) return(0);
if ((attr == NULL) || (attr->name == NULL)) return(0);
- attrDecl = xmlGetDtdAttrDesc(doc->intSubset, elem->name, attr->name);
- if ((attrDecl == NULL) && (doc->extSubset != NULL))
- attrDecl = xmlGetDtdAttrDesc(doc->extSubset, elem->name, attr->name);
+ if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
+ xmlChar qname[500];
+#ifdef HAVE_SNPRINTF
+ snprintf((char *) qname, sizeof(qname), "%s:%s",
+ elem->ns->prefix, elem->name);
+#else
+ sprintf(qname, "%s:%s", elem->name, elem->ns->prefix);
+#endif
+ if (attr->ns != NULL) {
+ attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, qname,
+ attr->name, attr->ns->prefix);
+ if ((attrDecl == NULL) && (doc->extSubset != NULL))
+ attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, qname,
+ attr->name, attr->ns->prefix);
+ } else {
+ attrDecl = xmlGetDtdAttrDesc(doc->intSubset, qname, attr->name);
+ if ((attrDecl == NULL) && (doc->extSubset != NULL))
+ attrDecl = xmlGetDtdAttrDesc(doc->extSubset,
+ qname, attr->name);
+ }
+ }
+ if (attrDecl == NULL) {
+ if (attr->ns != NULL) {
+ attrDecl = xmlGetDtdQAttrDesc(doc->intSubset, elem->name,
+ attr->name, attr->ns->prefix);
+ if ((attrDecl == NULL) && (doc->extSubset != NULL))
+ attrDecl = xmlGetDtdQAttrDesc(doc->extSubset, elem->name,
+ attr->name, attr->ns->prefix);
+ } else {
+ attrDecl = xmlGetDtdAttrDesc(doc->intSubset,
+ elem->name, attr->name);
+ if ((attrDecl == NULL) && (doc->extSubset != NULL))
+ attrDecl = xmlGetDtdAttrDesc(doc->extSubset,
+ elem->name, attr->name);
+ }
+ }
/* Validity Constraint: Attribute Value Type */
@@ -3274,7 +3507,7 @@
int
xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
xmlNodePtr elem) {
- xmlElementPtr elemDecl;
+ xmlElementPtr elemDecl = NULL;
xmlElementContentPtr cont;
xmlAttributePtr attr;
xmlNodePtr child;
@@ -3347,9 +3580,25 @@
}
if (elem->name == NULL) return(0);
- elemDecl = xmlGetDtdElementDesc(doc->intSubset, elem->name);
- if ((elemDecl == NULL) && (doc->extSubset != NULL))
- elemDecl = xmlGetDtdElementDesc(doc->extSubset, elem->name);
+ /*
+ * Fetch the declaration for the qualified name
+ */
+ if ((elem->ns != NULL) && (elem->ns->prefix != NULL)) {
+ elemDecl = xmlGetDtdQElementDesc(doc->intSubset,
+ elem->name, elem->ns->prefix);
+ if ((elemDecl == NULL) && (doc->extSubset != NULL))
+ elemDecl = xmlGetDtdQElementDesc(doc->extSubset,
+ elem->name, elem->ns->prefix);
+ }
+
+ /*
+ * Fetch the declaration for the non qualified name
+ */
+ if (elemDecl == NULL) {
+ elemDecl = xmlGetDtdElementDesc(doc->intSubset, elem->name);
+ if ((elemDecl == NULL) && (doc->extSubset != NULL))
+ elemDecl = xmlGetDtdElementDesc(doc->extSubset, elem->name);
+ }
if (elemDecl == NULL) {
VERROR(ctxt->userData, "No declaration for element %s\n",
elem->name);
@@ -3375,6 +3624,34 @@
while (child != NULL) {
if (child->type == XML_ELEMENT_NODE) {
name = child->name;
+ if ((child->ns != NULL) && (child->ns->prefix != NULL)) {
+ xmlChar qname[500];
+#ifdef HAVE_SNPRINTF
+ snprintf((char *) qname, sizeof(qname), "%s:%s",
+ child->ns->prefix, child->name);
+#else
+ sprintf(qname, "%s:%s", child->name, child->ns->prefix);
+#endif
+ cont = elemDecl->content;
+ while (cont != NULL) {
+ if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
+ if (!xmlStrcmp(cont->name, qname)) break;
+ } else if ((cont->type == XML_ELEMENT_CONTENT_OR) &&
+ (cont->c1 != NULL) &&
+ (cont->c1->type == XML_ELEMENT_CONTENT_ELEMENT)){
+ if (!xmlStrcmp(cont->c1->name, qname)) break;
+ } else if ((cont->type != XML_ELEMENT_CONTENT_OR) ||
+ (cont->c1 == NULL) ||
+ (cont->c1->type != XML_ELEMENT_CONTENT_PCDATA)){
+ /* Internal error !!! */
+ fprintf(stderr, "Internal: MIXED struct bad\n");
+ break;
+ }
+ cont = cont->c2;
+ }
+ if (cont != NULL)
+ goto child_ok;
+ }
cont = elemDecl->content;
while (cont != NULL) {
if (cont->type == XML_ELEMENT_CONTENT_ELEMENT) {
@@ -3399,6 +3676,7 @@
ret = 0;
}
}
+child_ok:
child = child->next;
}
break;
@@ -3518,15 +3796,32 @@
VERROR(ctxt->userData, "Not valid: no root element\n");
return(0);
}
+
+ /*
+ * Check first the document root against the NQName
+ */
if (xmlStrcmp(doc->intSubset->name, root->name)) {
- if ((xmlStrcmp(doc->intSubset->name, BAD_CAST "HTML")) ||
- (xmlStrcmp(root->name, BAD_CAST "html"))) {
- VERROR(ctxt->userData,
- "Not valid: root and DtD name do not match '%s' and '%s'\n",
- root->name, doc->intSubset->name);
- return(0);
- }
+ if ((root->ns != NULL) && (root->ns->prefix != NULL)) {
+ xmlChar qname[500];
+#ifdef HAVE_SNPRINTF
+ snprintf((char *) qname, sizeof(qname), "%s:%s",
+ root->ns->prefix, root->name);
+#else
+ sprintf(qname, "%s:%s", root->name, root->ns->prefix);
+#endif
+ if (!xmlStrcmp(doc->intSubset->name, qname))
+ goto name_ok;
+ }
+ if ((!xmlStrcmp(doc->intSubset->name, BAD_CAST "HTML")) &&
+ (!xmlStrcmp(root->name, BAD_CAST "html")))
+ goto name_ok;
+ VERROR(ctxt->userData,
+ "Not valid: root and DtD name do not match '%s' and '%s'\n",
+ root->name, doc->intSubset->name);
+ return(0);
+
}
+name_ok:
return(1);
}
diff --git a/xmlIO.c b/xmlIO.c
index 841a6b6..fdf961c 100644
--- a/xmlIO.c
+++ b/xmlIO.c
@@ -41,9 +41,9 @@
#include <libxml/nanohttp.h>
#include <libxml/nanoftp.h>
-/* #define DEBUG_INPUT */
/* #define VERBOSE_FAILURE */
/* #define DEBUG_EXTERNAL_ENTITIES */
+/* #define DEBUG_INPUT */
#ifdef DEBUG_INPUT
#define MINLEN 40
@@ -67,6 +67,22 @@
int xmlInputCallbackNr = 0;
int xmlInputCallbackInitialized = 0;
+/*
+ * Output I/O callback sets
+ */
+typedef struct _xmlOutputCallback {
+ xmlOutputMatchCallback matchcallback;
+ xmlOutputOpenCallback opencallback;
+ xmlOutputWriteCallback writecallback;
+ xmlOutputCloseCallback closecallback;
+} xmlOutputCallback;
+
+#define MAX_OUTPUT_CALLBACK 15
+
+xmlOutputCallback xmlOutputCallbackTable[MAX_OUTPUT_CALLBACK];
+int xmlOutputCallbackNr = 0;
+int xmlOutputCallbackInitialized = 0;
+
/************************************************************************
* *
* Standard I/O for file accesses *
@@ -124,10 +140,43 @@
}
/**
+ * xmlFdOpenW:
+ * @filename: the URI for matching
+ *
+ * input from file descriptor,
+ * if @filename is "-" then the standard output is used
+ *
+ * Returns an I/O context or NULL in case of error
+ */
+void *
+xmlFdOpenW (const char *filename) {
+ const char *path = NULL;
+ int fd;
+
+ if (!strcmp(filename, "-")) {
+ fd = 1;
+ return((void *) fd);
+ }
+
+ if (!strncmp(filename, "file://localhost", 16))
+ path = &filename[16];
+ else if (!strncmp(filename, "file:///", 8))
+ path = &filename[8];
+ else if (filename[0] == '/')
+ path = filename;
+ if (path == NULL)
+ return(NULL);
+
+ fd = open (filename, O_WRONLY);
+
+ return((void *) fd);
+}
+
+/**
* xmlFdRead:
* @context: the I/O context
* @buffer: where to drop data
- * @len: number of bytes to write
+ * @len: number of bytes to read
*
* Read @len bytes to @buffer from the I/O channel.
*
@@ -139,6 +188,21 @@
}
/**
+ * xmlFdWrite:
+ * @context: the I/O context
+ * @buffer: where to get data
+ * @len: number of bytes to write
+ *
+ * Write @len bytes from @buffer to the I/O channel.
+ *
+ * Returns the number of bytes written
+ */
+int
+xmlFdWrite (void * context, const char * buffer, int len) {
+ return(write((int) context, &buffer[0], len));
+}
+
+/**
* xmlFdClose:
* @context: the I/O context
*
@@ -199,6 +263,38 @@
}
/**
+ * xmlFileOpenW:
+ * @filename: the URI for matching
+ *
+ * output to from FILE *,
+ * if @filename is "-" then the standard output is used
+ *
+ * Returns an I/O context or NULL in case of error
+ */
+void *
+xmlFileOpenW (const char *filename) {
+ const char *path = NULL;
+ FILE *fd;
+
+ if (!strcmp(filename, "-")) {
+ fd = stdout;
+ return((void *) fd);
+ }
+
+ if (!strncmp(filename, "file://localhost", 16))
+ path = &filename[16];
+ else if (!strncmp(filename, "file:///", 8))
+ path = &filename[8];
+ else
+ path = filename;
+ if (path == NULL)
+ return(NULL);
+
+ fd = fopen(path, "w");
+ return((void *) fd);
+}
+
+/**
* xmlFileRead:
* @context: the I/O context
* @buffer: where to drop data
@@ -214,6 +310,21 @@
}
/**
+ * xmlFileWrite:
+ * @context: the I/O context
+ * @buffer: where to drop data
+ * @len: number of bytes to write
+ *
+ * Write @len bytes from @buffer to the I/O channel.
+ *
+ * Returns the number of bytes written
+ */
+int
+xmlFileWrite (void * context, const char * buffer, int len) {
+ return(fwrite(&buffer[0], 1, len, (FILE *) context));
+}
+
+/**
* xmlFileClose:
* @context: the I/O context
*
@@ -274,6 +385,39 @@
}
/**
+ * xmlGzfileOpenW:
+ * @filename: the URI for matching
+ * @compression: the compression factor (0 - 9 included)
+ *
+ * input from compressed file open
+ * if @filename is " " then the standard input is used
+ *
+ * Returns an I/O context or NULL in case of error
+ */
+void *
+xmlGzfileOpenW (const char *filename, int compression) {
+ const char *path = NULL;
+ char mode[15];
+ gzFile fd;
+
+ sprintf(mode, "w%d", compression);
+ if (!strcmp(filename, "-")) {
+ fd = gzdopen(1, mode);
+ return((void *) fd);
+ }
+
+ if (!strncmp(filename, "file://localhost", 16))
+ path = &filename[16];
+ else if (!strncmp(filename, "file:///", 8))
+ path = &filename[8];
+ else
+ path = filename;
+
+ fd = gzopen(filename, mode);
+ return((void *) fd);
+}
+
+/**
* xmlGzfileRead:
* @context: the I/O context
* @buffer: where to drop data
@@ -289,6 +433,21 @@
}
/**
+ * xmlGzfileWrite:
+ * @context: the I/O context
+ * @buffer: where to drop data
+ * @len: number of bytes to write
+ *
+ * Write @len bytes from @buffer to the compressed I/O channel.
+ *
+ * Returns the number of bytes written
+ */
+int
+xmlGzfileWrite (void * context, const char * buffer, int len) {
+ return(gzwrite((gzFile) context, (char *) &buffer[0], len));
+}
+
+/**
* xmlGzfileClose:
* @context: the I/O context
*
@@ -449,6 +608,31 @@
}
/**
+ * xmlRegisterOutputCallbacks:
+ * @match: the xmlOutputMatchCallback
+ * @open: the xmlOutputOpenCallback
+ * @write: the xmlOutputWriteCallback
+ * @close: the xmlOutputCloseCallback
+ *
+ * Register a new set of I/O callback for handling output.
+ *
+ * Returns the registered handler number or -1 in case of error
+ */
+int
+xmlRegisterOutputCallbacks(xmlOutputMatchCallback match,
+ xmlOutputOpenCallback open, xmlOutputWriteCallback write,
+ xmlOutputCloseCallback close) {
+ if (xmlOutputCallbackNr >= MAX_INPUT_CALLBACK) {
+ return(-1);
+ }
+ xmlOutputCallbackTable[xmlOutputCallbackNr].matchcallback = match;
+ xmlOutputCallbackTable[xmlOutputCallbackNr].opencallback = open;
+ xmlOutputCallbackTable[xmlOutputCallbackNr].writecallback = write;
+ xmlOutputCallbackTable[xmlOutputCallbackNr].closecallback = close;
+ return(xmlOutputCallbackNr++);
+}
+
+/**
* xmlRegisterDefaultInputCallbacks:
*
* Registers the default compiled-in I/O handlers.
@@ -474,6 +658,39 @@
}
/**
+ * xmlRegisterDefaultOutputCallbacks:
+ *
+ * Registers the default compiled-in I/O handlers.
+ */
+void
+xmlRegisterDefaultOutputCallbacks(void) {
+ xmlRegisterOutputCallbacks(xmlFileMatch, xmlFileOpenW,
+ xmlFileWrite, xmlFileClose);
+/*********************************
+ No way a-priori to distinguish between gzipped files from
+ uncompressed ones except opening if existing then closing
+ and saving with same compression ratio ... a pain.
+
+#ifdef HAVE_ZLIB_H
+ xmlRegisterOutputCallbacks(xmlGzfileMatch, xmlGzfileOpen,
+ xmlGzfileWrite, xmlGzfileClose);
+#endif
+ No HTTP PUT support yet, patches welcome
+
+#ifdef LIBXML_HTTP_ENABLED
+ xmlRegisterOutputCallbacks(xmlIOHTTPMatch, xmlIOHTTPOpen,
+ xmlIOHTTPWrite, xmlIOHTTPClose);
+#endif
+
+ Nor FTP PUT ....
+#ifdef LIBXML_FTP_ENABLED
+ xmlRegisterOutputCallbacks(xmlIOFTPMatch, xmlIOFTPOpen,
+ xmlIOFTPWrite, xmlIOFTPClose);
+#endif
+ **********************************/
+}
+
+/**
* xmlAllocParserInputBuffer:
* @enc: the charset encoding if known
*
@@ -510,6 +727,47 @@
}
/**
+ * xmlAllocOutputBuffer:
+ * @encoder: the encoding converter or NULL
+ *
+ * Create a buffered parser output
+ *
+ * Returns the new parser output or NULL
+ */
+xmlOutputBufferPtr
+xmlAllocOutputBuffer(xmlCharEncodingHandlerPtr encoder) {
+ xmlOutputBufferPtr ret;
+
+ ret = (xmlOutputBufferPtr) xmlMalloc(sizeof(xmlOutputBuffer));
+ if (ret == NULL) {
+ fprintf(stderr, "xmlAllocOutputBuffer : out of memory!\n");
+ return(NULL);
+ }
+ memset(ret, 0, (size_t) sizeof(xmlOutputBuffer));
+ ret->buffer = xmlBufferCreate();
+ if (ret->buffer == NULL) {
+ xmlFree(ret);
+ return(NULL);
+ }
+ ret->buffer->alloc = XML_BUFFER_ALLOC_DOUBLEIT;
+ ret->encoder = encoder;
+ if (encoder != NULL) {
+ ret->conv = xmlBufferCreateSize(4000);
+ /*
+ * This call is designed to initiate the encoder state
+ */
+ xmlCharEncOutFunc(encoder, ret->conv, NULL);
+ } else
+ ret->conv = NULL;
+ ret->writecallback = NULL;
+ ret->closecallback = NULL;
+ ret->context = NULL;
+ ret->written = 0;
+
+ return(ret);
+}
+
+/**
* xmlFreeParserInputBuffer:
* @in: a buffered parser input
*
@@ -537,6 +795,43 @@
}
/**
+ * xmlOutputBufferClose:
+ * @out: a buffered output
+ *
+ * flushes and close the output I/O channel
+ * and free up all the associated resources
+ *
+ * Returns the number of byte written or -1 in case of error.
+ */
+int
+xmlOutputBufferClose(xmlOutputBufferPtr out) {
+ int written;
+
+ if (out == NULL)
+ return(-1);
+ xmlOutputBufferFlush(out);
+ if (out->closecallback != NULL) {
+ out->closecallback(out->context);
+ }
+ written = out->written;
+ if (out->conv) {
+ xmlBufferFree(out->conv);
+ out->conv = NULL;
+ }
+ if (out->encoder != NULL) {
+ xmlCharEncCloseFunc(out->encoder);
+ }
+ if (out->buffer != NULL) {
+ xmlBufferFree(out->buffer);
+ out->buffer = NULL;
+ }
+
+ memset(out, 0xbe, (size_t) sizeof(xmlOutputBuffer));
+ xmlFree(out);
+ return(written);
+}
+
+/**
* xmlParserInputBufferCreateFilename:
* @URI: a C string containing the URI or filename
* @enc: the charset encoding if known
@@ -592,6 +887,80 @@
}
/**
+ * xmlOutputBufferCreateFilename:
+ * @URI: a C string containing the URI or filename
+ * @encoder: the encoding converter or NULL
+ * @compression: the compression ration (0 none, 9 max).
+ *
+ * Create a buffered output for the progressive saving of a file
+ * If filename is "-' then we use stdout as the output.
+ * Automatic support for ZLIB/Compress compressed document is provided
+ * by default if found at compile-time.
+ * TODO: currently if compression is set, the library only support
+ * writing to a local file.
+ *
+ * Returns the new output or NULL
+ */
+xmlOutputBufferPtr
+xmlOutputBufferCreateFilename(const char *URI,
+ xmlCharEncodingHandlerPtr encoder,
+ int compression) {
+ xmlOutputBufferPtr ret;
+ int i;
+ void *context = NULL;
+
+ if (xmlOutputCallbackInitialized == 0)
+ xmlRegisterDefaultOutputCallbacks();
+
+ if (URI == NULL) return(NULL);
+
+#ifdef HAVE_ZLIB_H
+ if ((compression > 0) && (compression <= 9)) {
+ context = xmlGzfileOpenW(URI, compression);
+ if (context != NULL) {
+ ret = xmlAllocOutputBuffer(encoder);
+ if (ret != NULL) {
+ ret->context = context;
+ ret->writecallback = xmlGzfileWrite;
+ ret->closecallback = xmlGzfileClose;
+ }
+ return(ret);
+ }
+ }
+#endif
+
+ /*
+ * Try to find one of the output accept method accepting taht scheme
+ * Go in reverse to give precedence to user defined handlers.
+ */
+ for (i = xmlOutputCallbackNr - 1;i >= 0;i--) {
+ if ((xmlOutputCallbackTable[i].matchcallback != NULL) &&
+ (xmlOutputCallbackTable[i].matchcallback(URI) != 0)) {
+ context = xmlOutputCallbackTable[i].opencallback(URI);
+ if (context != NULL)
+ break;
+ }
+ }
+ if (context == NULL) {
+#ifdef DEBUG_INPUT
+ fprintf(stderr, "No output filter matching \"%s\"\n", URI);
+#endif
+ return(NULL);
+ }
+
+ /*
+ * Allocate the Output buffer front-end.
+ */
+ ret = xmlAllocOutputBuffer(encoder);
+ if (ret != NULL) {
+ ret->context = context;
+ ret->writecallback = xmlOutputCallbackTable[i].writecallback;
+ ret->closecallback = xmlOutputCallbackTable[i].closecallback;
+ }
+ return(ret);
+}
+
+/**
* xmlParserInputBufferCreateFile:
* @file: a FILE*
* @enc: the charset encoding if known
@@ -621,6 +990,35 @@
}
/**
+ * xmlOutputBufferCreateFile:
+ * @file: a FILE*
+ * @encoder: the encoding converter or NULL
+ *
+ * Create a buffered output for the progressive saving to a FILE *
+ * buffered C I/O
+ *
+ * Returns the new parser output or NULL
+ */
+xmlOutputBufferPtr
+xmlOutputBufferCreateFile(FILE *file, xmlCharEncodingHandlerPtr encoder) {
+ xmlOutputBufferPtr ret;
+
+ if (xmlOutputCallbackInitialized == 0)
+ xmlRegisterDefaultOutputCallbacks();
+
+ if (file == NULL) return(NULL);
+
+ ret = xmlAllocOutputBuffer(encoder);
+ if (ret != NULL) {
+ ret->context = file;
+ ret->writecallback = xmlFileWrite;
+ ret->closecallback = xmlFileClose;
+ }
+
+ return(ret);
+}
+
+/**
* xmlParserInputBufferCreateFd:
* @fd: a file descriptor number
* @enc: the charset encoding if known
@@ -647,6 +1045,32 @@
}
/**
+ * xmlOutputBufferCreateFd:
+ * @fd: a file descriptor number
+ * @encoder: the encoding converter or NULL
+ *
+ * Create a buffered output for the progressive saving
+ * to a file descriptor
+ *
+ * Returns the new parser output or NULL
+ */
+xmlOutputBufferPtr
+xmlOutputBufferCreateFd(int fd, xmlCharEncodingHandlerPtr encoder) {
+ xmlOutputBufferPtr ret;
+
+ if (fd < 0) return(NULL);
+
+ ret = xmlAllocOutputBuffer(encoder);
+ if (ret != NULL) {
+ ret->context = (void *) fd;
+ ret->writecallback = xmlFdWrite;
+ ret->closecallback = xmlFdClose;
+ }
+
+ return(ret);
+}
+
+/**
* xmlParserInputBufferCreateIO:
* @ioread: an I/O read function
* @ioclose: an I/O close function
@@ -654,7 +1078,7 @@
* @enc: the charset encoding if known
*
* Create a buffered parser input for the progressive parsing for the input
- * from a file descriptor
+ * from an I/O handler
*
* Returns the new parser input or NULL
*/
@@ -676,10 +1100,40 @@
}
/**
+ * xmlOutputBufferCreateIO:
+ * @iowrite: an I/O write function
+ * @ioclose: an I/O close function
+ * @ioctx: an I/O handler
+ * @enc: the charset encoding if known
+ *
+ * Create a buffered output for the progressive saving
+ * to an I/O handler
+ *
+ * Returns the new parser output or NULL
+ */
+xmlOutputBufferPtr
+xmlOutputBufferCreateIO(xmlOutputWriteCallback iowrite,
+ xmlOutputCloseCallback ioclose, void *ioctx,
+ xmlCharEncodingHandlerPtr encoder) {
+ xmlOutputBufferPtr ret;
+
+ if (iowrite == NULL) return(NULL);
+
+ ret = xmlAllocOutputBuffer(encoder);
+ if (ret != NULL) {
+ ret->context = (void *) ioctx;
+ ret->writecallback = iowrite;
+ ret->closecallback = ioclose;
+ }
+
+ return(ret);
+}
+
+/**
* xmlParserInputBufferPush:
* @in: a buffered parser input
- * @buf: an char array
* @len: the size in bytes of the array.
+ * @buf: an char array
*
* Push the content of the arry in the input buffer
* This routine handle the I18N transcoding to internal UTF-8
@@ -769,16 +1223,12 @@
xmlFree(buffer);
return(-1);
}
-
- if (res == 0) {
- xmlFree(buffer);
- return(0);
- }
if (res < 0) {
perror ("read error");
xmlFree(buffer);
return(-1);
}
+ len = res;
if (in->encoder != NULL) {
/*
* Store the data in the incoming raw buffer
@@ -797,7 +1247,7 @@
return(-1);
}
} else {
- nbchars = res;
+ nbchars = len;
buffer[nbchars] = 0;
xmlBufferAdd(in->buffer, (xmlChar *) buffer, nbchars);
}
@@ -827,7 +1277,162 @@
if (in->readcallback != NULL)
return(xmlParserInputBufferGrow(in, len));
else
- return(0);
+ return(-1);
+}
+
+/**
+ * xmlOutputBufferWrite:
+ * @out: a buffered parser output
+ * @len: the size in bytes of the array.
+ * @buf: an char array
+ *
+ * Write the content of the array in the output I/O buffer
+ * This routine handle the I18N transcoding from internal UTF-8
+ * The buffer is lossless, i.e. will store in case of partial
+ * or delayed writes.
+ *
+ * Returns the number of chars immediately written, or -1
+ * in case of error.
+ */
+int
+xmlOutputBufferWrite(xmlOutputBufferPtr out, int len, const char *buf) {
+ int nbchars = 0, ret;
+
+ if (len < 0) return(0);
+
+ /*
+ * first handle encoding stuff.
+ */
+ if (out->encoder != NULL) {
+ /*
+ * Store the data in the incoming raw buffer
+ */
+ if (out->conv == NULL) {
+ out->conv = xmlBufferCreate();
+ }
+ xmlBufferAdd(out->buffer, (const xmlChar *) buf, len);
+
+ if (out->buffer->use < MINLEN)
+ return(0);
+
+ /*
+ * convert as much as possible to the parser reading buffer.
+ */
+ nbchars = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
+ if (nbchars < 0) {
+ fprintf(stderr, "xmlOutputBufferWrite: encoder error\n");
+ return(-1);
+ }
+ nbchars = out->conv->use;
+ } else {
+ xmlBufferAdd(out->buffer, (const xmlChar *) buf, len);
+ nbchars = out->buffer->use;
+ }
+ if (nbchars < MINLEN)
+ return(0);
+
+ /*
+ * second write the stuff to the I/O channel
+ */
+ if (out->encoder != NULL) {
+ ret = out->writecallback(out->context,
+ (const char *)out->conv->content, nbchars);
+ if (ret >= 0)
+ xmlBufferShrink(out->conv, nbchars);
+ } else {
+ ret = out->writecallback(out->context,
+ (const char *)out->buffer->content, nbchars);
+ if (ret >= 0)
+ xmlBufferShrink(out->buffer, nbchars);
+ }
+ if (ret < 0) {
+ fprintf(stderr, "I/O: error %d writing %d bytes\n", ret, nbchars);
+ return(ret);
+ }
+ out->written += ret;
+
+#ifdef DEBUG_INPUT
+ fprintf(stderr, "I/O: wrote %d chars\n", ret);
+#endif
+ return(nbchars);
+}
+
+/**
+ * xmlOutputBufferWriteString:
+ * @out: a buffered parser output
+ * @str: a zero terminated C string
+ *
+ * Write the content of the string in the output I/O buffer
+ * This routine handle the I18N transcoding from internal UTF-8
+ * The buffer is lossless, i.e. will store in case of partial
+ * or delayed writes.
+ *
+ * Returns the number of chars immediately written, or -1
+ * in case of error.
+ */
+int
+xmlOutputBufferWriteString(xmlOutputBufferPtr out, const char *str) {
+ int len;
+
+ if (str == NULL)
+ return(-1);
+ len = strlen(str);
+
+ if (len > 0)
+ return(xmlOutputBufferWrite(out, len, str));
+ return(len);
+}
+
+/**
+ * xmlOutputBufferFlush:
+ * @out: a buffered output
+ *
+ * flushes the output I/O channel
+ *
+ * Returns the number of byte written or -1 in case of error.
+ */
+int
+xmlOutputBufferFlush(xmlOutputBufferPtr out) {
+ int nbchars = 0, ret;
+
+ /*
+ * first handle encoding stuff.
+ */
+ if ((out->conv != NULL) && (out->encoder != NULL)) {
+ /*
+ * convert as much as possible to the parser reading buffer.
+ */
+ nbchars = xmlCharEncOutFunc(out->encoder, out->conv, out->buffer);
+ if (nbchars < 0) {
+ fprintf(stderr, "xmlOutputBufferWrite: encoder error\n");
+ return(-1);
+ }
+ }
+
+ /*
+ * second flush the stuff to the I/O channel
+ */
+ if ((out->conv != NULL) && (out->encoder != NULL)) {
+ ret = out->writecallback(out->context,
+ (const char *)out->conv->content, out->conv->use);
+ if (ret >= 0)
+ xmlBufferShrink(out->conv, ret);
+ } else {
+ ret = out->writecallback(out->context,
+ (const char *)out->buffer->content, out->buffer->use);
+ if (ret >= 0)
+ xmlBufferShrink(out->buffer, ret);
+ }
+ if (ret < 0) {
+ fprintf(stderr, "I/O: error %d flushing %d bytes\n", ret, nbchars);
+ return(ret);
+ }
+ out->written += ret;
+
+#ifdef DEBUG_INPUT
+ fprintf(stderr, "I/O: flushed %d chars\n", ret);
+#endif
+ return(ret);
}
/*
diff --git a/xmlIO.h b/xmlIO.h
index 2d14ebe..5289367 100644
--- a/xmlIO.h
+++ b/xmlIO.h
@@ -18,6 +18,11 @@
extern "C" {
#endif
+/*
+ * Those are the functions and datatypes for the parser input
+ * I/O structures.
+ */
+
typedef int (*xmlInputMatchCallback) (char const *filename);
typedef void * (*xmlInputOpenCallback) (char const *filename);
typedef int (*xmlInputReadCallback) (void * context, char * buffer, int len);
@@ -32,13 +37,38 @@
xmlCharEncodingHandlerPtr encoder; /* I18N conversions to UTF-8 */
- xmlBufferPtr buffer; /* Local buffer encoded in UTF-8 */
+ xmlBufferPtr buffer; /* Local buffer encoded in UTF-8 or ISOLatin */
xmlBufferPtr raw; /* if encoder != NULL buffer for raw input */
};
/*
- * Interfaces
+ * Those are the functions and datatypes for the library output
+ * I/O structures.
+ */
+
+typedef int (*xmlOutputMatchCallback) (char const *filename);
+typedef void * (*xmlOutputOpenCallback) (char const *filename);
+typedef int (*xmlOutputWriteCallback) (void * context, const char * buffer,
+ int len);
+typedef void (*xmlOutputCloseCallback) (void * context);
+
+typedef struct _xmlOutputBuffer xmlOutputBuffer;
+typedef xmlOutputBuffer *xmlOutputBufferPtr;
+struct _xmlOutputBuffer {
+ void* context;
+ xmlOutputWriteCallback writecallback;
+ xmlOutputCloseCallback closecallback;
+
+ xmlCharEncodingHandlerPtr encoder; /* I18N conversions to UTF-8 */
+
+ xmlBufferPtr buffer; /* Local buffer encoded in UTF-8 or ISOLatin */
+ xmlBufferPtr conv; /* if encoder != NULL buffer for output */
+ int written; /* total number of byte written */
+};
+
+/*
+ * Interfaces for input
*/
xmlParserInputBufferPtr
@@ -72,6 +102,51 @@
xmlInputOpenCallback open,
xmlInputReadCallback read,
xmlInputCloseCallback close);
+/*
+ * Interfaces for output
+ */
+xmlOutputBufferPtr
+ xmlAllocOutputBuffer (xmlCharEncodingHandlerPtr encoder);
+
+xmlOutputBufferPtr
+ xmlOutputBufferCreateFilename (const char *URI,
+ xmlCharEncodingHandlerPtr encoder,
+ int compression);
+
+xmlOutputBufferPtr
+ xmlOutputBufferCreateFile (FILE *file,
+ xmlCharEncodingHandlerPtr encoder);
+
+xmlOutputBufferPtr
+ xmlOutputBufferCreateFd (int fd,
+ xmlCharEncodingHandlerPtr encoder);
+
+xmlOutputBufferPtr
+ xmlOutputBufferCreateIO (xmlOutputWriteCallback iowrite,
+ xmlOutputCloseCallback ioclose,
+ void *ioctx,
+ xmlCharEncodingHandlerPtr encoder);
+
+int xmlOutputBufferWrite (xmlOutputBufferPtr out,
+ int len,
+ const char *buf);
+int xmlOutputBufferWriteString (xmlOutputBufferPtr out,
+ const char *str);
+
+int xmlOutputBufferFlush (xmlOutputBufferPtr out);
+int xmlOutputBufferClose (xmlOutputBufferPtr out);
+
+int xmlRegisterOutputCallbacks (xmlOutputMatchCallback match,
+ xmlOutputOpenCallback open,
+ xmlOutputWriteCallback write,
+ xmlOutputCloseCallback close);
+
+/*
+ * This save function is part of tree.h actually
+ */
+int xmlSaveFileTo (xmlOutputBuffer *buf,
+ xmlDocPtr cur,
+ const char *encoding);
#ifdef __cplusplus
}
#endif
diff --git a/xmllint.c b/xmllint.c
index 24c17f7..dcd7161 100644
--- a/xmllint.c
+++ b/xmllint.c
@@ -68,6 +68,7 @@
static int push = 0;
static int noblanks = 0;
static int testIO = 0;
+static char *encoding = NULL;
extern int xmlDoValidityCheckingDefaultValue;
extern int xmlGetWarningsDefaultValue;
@@ -499,6 +500,8 @@
#endif
if (compress)
xmlSaveFile("-", doc);
+ else if (encoding != NULL)
+ xmlSaveFileEnc("-", doc, encoding);
else
xmlDocDump(stdout, doc);
#ifdef LIBXML_DEBUG_ENABLED
@@ -531,6 +534,7 @@
int i, count;
int files = 0;
+ LIBXML_TEST_VERSION
for (i = 1; i < argc ; i++) {
#ifdef LIBXML_DEBUG_ENABLED
if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug")))
@@ -593,6 +597,11 @@
(!strcmp(argv[i], "--nowarning"))) {
xmlGetWarningsDefaultValue = 0;
}
+ else if ((!strcmp(argv[i], "-encode")) ||
+ (!strcmp(argv[i], "--encode"))) {
+ i++;
+ encoding = argv[i];
+ }
else if ((!strcmp(argv[i], "-noblanks")) ||
(!strcmp(argv[i], "--noblanks"))) {
noblanks++;
@@ -613,6 +622,11 @@
argv[0]);
}
for (i = 1; i < argc ; i++) {
+ if ((!strcmp(argv[i], "-encode")) ||
+ (!strcmp(argv[i], "--encode"))) {
+ i++;
+ continue;
+ }
if (argv[i][0] != '-') {
if (repeat) {
for (count = 0;count < 100 * repeat;count++)
diff --git a/xmlversion.h.in b/xmlversion.h.in
index 5a62c27..b5edc09 100644
--- a/xmlversion.h.in
+++ b/xmlversion.h.in
@@ -9,8 +9,14 @@
#ifndef __XML_VERSION_H__
#define __XML_VERSION_H__
+/*
+ * use those to be sure nothing nasty will happen if
+ * your library and includes mismatch
+ */
+extern void xmlCheckVersion(int version);
#define LIBXML_VERSION @LIBXML_VERSION_NUMBER@
#define LIBXML_VERSION_STRING "@LIBXML_VERSION_NUMBER@"
+#define LIBXML_TEST_VERSION xmlCheckVersion(@LIBXML_VERSION_NUMBER@);
/*
* Whether the FTP support is configured in
diff --git a/xpath.c b/xpath.c
index a8867a4..19499b7 100644
--- a/xpath.c
+++ b/xpath.c
@@ -733,15 +733,19 @@
xmlXPathObjectPtr
xmlXPathNewNodeSetList(xmlNodeSetPtr val) {
xmlXPathObjectPtr ret;
+ int i;
- ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
- if (ret == NULL) {
- fprintf(xmlXPathDebug, "xmlXPathNewFloat: out of memory\n");
- return(NULL);
- }
- memset(ret, 0 , (size_t) sizeof(xmlXPathObject));
- ret->type = XPATH_NODESET;
- ret->nodesetval = val;
+ if (val == NULL)
+ ret = NULL;
+ else if (val->nodeTab == NULL)
+ ret = xmlXPathNewNodeSet(NULL);
+ else
+ {
+ ret = xmlXPathNewNodeSet(val->nodeTab[0]);
+ for (i = 1; i < val->nodeNr; ++i)
+ xmlXPathNodeSetAdd(ret->nodesetval, val->nodeTab[i]);
+ }
+
return(ret);
}
@@ -1541,7 +1545,11 @@
return(ctxt->context->node->children);
}
- if (cur->children != NULL) return(cur->children);
+ if (cur->children != NULL)
+ {
+ if (cur->children->type != XML_ENTITY_DECL)
+ return(cur->children);
+ }
if (cur->next != NULL) return(cur->next);
do {
@@ -3692,9 +3700,10 @@
xmlXPathEvalFilterExpr(ctxt);
if (name != NULL)
xmlFree(name);
- }
+
if (ctxt->context->nodelist != NULL)
valuePush(ctxt, xmlXPathNewNodeSetList(ctxt->context->nodelist));
+ }
}
/**
@@ -3933,7 +3942,7 @@
xmlXPathEvalEqualityExpr(ctxt);
CHECK_ERROR;
SKIP_BLANKS;
- while ((CUR == 'a') && (NXT(1) == 'n') && (NXT(2) == 'n')) {
+ while ((CUR == 'a') && (NXT(1) == 'n') && (NXT(2) == 'd')) {
xmlXPathObjectPtr arg1, arg2;
SKIP(3);
@@ -4028,7 +4037,7 @@
void
xmlXPathEvalPredicate(xmlXPathParserContextPtr ctxt) {
const xmlChar *cur;
- xmlXPathObjectPtr res;
+ xmlXPathObjectPtr res, listHolder = NULL;
xmlNodeSetPtr newset = NULL;
int i;
@@ -4049,20 +4058,42 @@
} else {
cur = ctxt->cur;
newset = xmlXPathNodeSetCreate(NULL);
+
+ /* Create a copy of the current node set because it is important: */
+ listHolder = xmlXPathNewNodeSetList(ctxt->context->nodelist);
+
for (i = 0; i < ctxt->context->nodelist->nodeNr; i++) {
ctxt->cur = cur;
ctxt->context->node = ctxt->context->nodelist->nodeTab[i];
+
+ /* This nodeset is useful for the loop but no, longer necessary this iteration: */
+ if (ctxt->context->nodelist != NULL)
+ xmlXPathFreeNodeSet(ctxt->context->nodelist);
+
+ /* This line was missed out: */
+ ctxt->context->nodelist = xmlXPathNodeSetCreate(ctxt->context->node);
+
xmlXPathEvalExpr(ctxt);
CHECK_ERROR;
res = valuePop(ctxt);
if (xmlXPathEvaluatePredicateResult(ctxt, res, i + 1))
- xmlXPathNodeSetAdd(newset,
- ctxt->context->nodelist->nodeTab[i]);
+ {
+ /* Add the current node as the result has proven correct: */
+ xmlXPathNodeSetAdd(newset, listHolder->nodesetval->nodeTab[i]);
+ }
if (res != NULL)
xmlXPathFreeObject(res);
+
+ /* Copy the contents of the temporary list back to the node list for the next round: */
+ ctxt->context->nodelist = xmlXPathNewNodeSetList(listHolder->nodesetval)->nodesetval;
}
if (ctxt->context->nodelist != NULL)
xmlXPathFreeNodeSet(ctxt->context->nodelist);
+
+ /* Clean up after temporary variable holder: */
+ if (listHolder != NULL)
+ xmlXPathFreeObject(listHolder);
+
ctxt->context->nodelist = newset;
ctxt->context->node = NULL;
}
@@ -4392,6 +4423,11 @@
while (CUR == '[') {
xmlXPathEvalPredicate(ctxt);
}
+
+ while (CUR == '@') {
+ xmlXPathEvalBasis(ctxt);
+ ctxt->context->node = NULL;
+ }
}
#ifdef DEBUG_STEP
fprintf(xmlXPathDebug, "Step : ");
@@ -4537,6 +4573,7 @@
res = xmlXPathNewNodeSetList(pctxt->context->nodelist);
else
res = NULL;
+
xmlXPathFreeParserContext(pctxt);
return(res);
}
diff --git a/xpath.h b/xpath.h
index 73e3f65..fc567fd 100644
--- a/xpath.h
+++ b/xpath.h
@@ -29,8 +29,8 @@
typedef struct _xmlNodeSet xmlNodeSet;
typedef xmlNodeSet *xmlNodeSetPtr;
struct _xmlNodeSet {
- int nodeNr; /* # of node in the set */
- int nodeMax; /* allocated space */
+ int nodeNr; /* number of nodes in the set */
+ int nodeMax; /* size of the array as allocated */
xmlNodePtr *nodeTab; /* array of nodes in no particular order */
};
@@ -41,6 +41,8 @@
* - boolean
* - number
* - string
+ *
+ * @@ XPointer will add more types !
*/
#define XPATH_UNDEFINED 0