mirror of
https://github.com/darlinghq/darling-libxml2.git
synced 2025-03-09 05:20:53 +00:00
- 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
This commit is contained in:
parent
c310d56482
commit
be803967db
19
ChangeLog
19
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
|
||||
|
64
HTMLparser.c
64
HTMLparser.c
@ -388,6 +388,7 @@ char *htmlStartClose[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
static char** htmlStartCloseIndex[100];
|
||||
static int htmlStartCloseIndexinitialized = 0;
|
||||
|
||||
@ -604,6 +605,54 @@ htmlAutoCloseOnClose(htmlParserCtxtPtr ctxt, const xmlChar *new) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 @@ htmlNewDoc(const xmlChar *URI, const xmlChar *ExternalID) {
|
||||
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 @@ htmlParseAttribute(htmlParserCtxtPtr ctxt, xmlChar **value) {
|
||||
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;
|
||||
@ -2219,6 +2270,11 @@ htmlParseStartTag(htmlParserCtxtPtr ctxt) {
|
||||
*/
|
||||
htmlAutoClose(ctxt, name);
|
||||
|
||||
/*
|
||||
* Check for implied HTML elements.
|
||||
*/
|
||||
htmlCheckImplied(ctxt, name);
|
||||
|
||||
/*
|
||||
* Now parse the attributes, it ends up with the ending
|
||||
*
|
||||
@ -2759,6 +2815,10 @@ htmlParseDocument(htmlParserCtxtPtr ctxt) {
|
||||
ctxt->wellFormed = 0;
|
||||
}
|
||||
|
||||
if ((ctxt->sax) && (ctxt->sax->startDocument) && (!ctxt->disableSAX))
|
||||
ctxt->sax->startDocument(ctxt->userData);
|
||||
|
||||
|
||||
/*
|
||||
* Parse possible comments before any content
|
||||
*/
|
||||
|
16
HTMLtree.c
16
HTMLtree.c
@ -84,13 +84,15 @@ htmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
|
||||
}
|
||||
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, "=\"\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,12 +86,14 @@ testURI_LDADD= $(LDADDS)
|
||||
|
||||
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
|
||||
|
2
README
2
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
|
||||
|
||||
|
178
SAX.c
178
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 @@ externalSubset(void *ctx, const xmlChar *name,
|
||||
int oldwellFormed;
|
||||
xmlParserInputPtr input = NULL;
|
||||
xmlCharEncoding enc;
|
||||
xmlCharEncoding oldcharset;
|
||||
|
||||
/*
|
||||
* Ask the Entity resolver to load the damn thing
|
||||
@ -214,6 +216,7 @@ externalSubset(void *ctx, const xmlChar *name,
|
||||
oldinputMax = ctxt->inputMax;
|
||||
oldinputTab = ctxt->inputTab;
|
||||
oldwellFormed = ctxt->wellFormed;
|
||||
oldcharset = ctxt->charset;
|
||||
|
||||
ctxt->inputTab = (xmlParserInputPtr *)
|
||||
xmlMalloc(5 * sizeof(xmlParserInputPtr));
|
||||
@ -227,6 +230,7 @@ externalSubset(void *ctx, const xmlChar *name,
|
||||
ctxt->inputNr = oldinputNr;
|
||||
ctxt->inputMax = oldinputMax;
|
||||
ctxt->inputTab = oldinputTab;
|
||||
ctxt->charset = oldcharset;
|
||||
return;
|
||||
}
|
||||
ctxt->inputNr = 0;
|
||||
@ -269,6 +273,7 @@ externalSubset(void *ctx, const xmlChar *name,
|
||||
ctxt->inputNr = oldinputNr;
|
||||
ctxt->inputMax = oldinputMax;
|
||||
ctxt->inputTab = oldinputTab;
|
||||
ctxt->charset = oldcharset;
|
||||
/* ctxt->wellFormed = oldwellFormed; */
|
||||
}
|
||||
}
|
||||
@ -604,6 +609,14 @@ endDocument(void *ctx)
|
||||
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 @@ attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
|
||||
/*
|
||||
* 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 @@ attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
|
||||
/*
|
||||
* 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 @@ attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
|
||||
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 @@ attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
|
||||
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 @@ attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
|
||||
}
|
||||
}
|
||||
|
||||
if (ctxt->validate && ctxt->wellFormed &&
|
||||
if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
|
||||
ctxt->myDoc && ctxt->myDoc->intSubset) {
|
||||
|
||||
/*
|
||||
@ -817,6 +850,7 @@ startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
|
||||
} else if (parent == NULL) {
|
||||
parent = ctxt->myDoc->children;
|
||||
}
|
||||
ctxt->nodemem = -1;
|
||||
|
||||
/*
|
||||
* We are parsing a new node.
|
||||
@ -844,15 +878,6 @@ startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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"
|
||||
*/
|
||||
@ -860,31 +885,14 @@ startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
|
||||
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 @@ startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
|
||||
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 @@ endElement(void *ctx, const xmlChar *name)
|
||||
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 @@ characters(void *ctx, const xmlChar *ch, int len)
|
||||
#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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
15
TODO
15
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 @@ TODO:
|
||||
- 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 @@ EXTENSIONS:
|
||||
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()
|
||||
|
@ -1326,7 +1326,7 @@ xmlShellDu(xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr tree,
|
||||
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++;
|
||||
|
File diff suppressed because it is too large
Load Diff
406
encoding.c
406
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 --
|
||||
@ -65,6 +66,73 @@ static int xmlLittleEndian = 1;
|
||||
* I hope we won't use values > 0xFFFF anytime soon !
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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 @@ UTF16LEToUTF8(unsigned char* out, int *outlen,
|
||||
(*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 @@ UTF16LEToUTF8(unsigned char* out, int *outlen,
|
||||
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 @@ UTF8ToUTF16LE(unsigned char* outb, int *outlen,
|
||||
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 @@ UTF8ToUTF16LE(unsigned char* outb, int *outlen,
|
||||
break;
|
||||
processed = in;
|
||||
}
|
||||
*outlen = out - outstart;
|
||||
*outlen = (out - outstart) * 2;
|
||||
*inlen = processed - in;
|
||||
return(0);
|
||||
}
|
||||
@ -509,6 +595,24 @@ UTF8ToUTF16BE(unsigned char* outb, int *outlen,
|
||||
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 @@ UTF8ToUTF16BE(unsigned char* outb, int *outlen,
|
||||
break;
|
||||
processed = in;
|
||||
}
|
||||
*outlen = out - outstart;
|
||||
*outlen = (out - outstart) * 2;
|
||||
*inlen = processed - in;
|
||||
return(0);
|
||||
}
|
||||
@ -695,6 +799,70 @@ xmlParseCharEncoding(const char* name)
|
||||
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 @@ xmlGetCharEncodingHandler(xmlCharEncoding enc) {
|
||||
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 @@ xmlGetCharEncodingHandler(xmlCharEncoding enc) {
|
||||
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 @@ xmlGetCharEncodingHandler(xmlCharEncoding enc) {
|
||||
*/
|
||||
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 @@ xmlFindCharEncodingHandler(const char *name) {
|
||||
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 @@ xmlFindCharEncodingHandler(const char *name) {
|
||||
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 @@ xmlIconvWrapper(iconv_t cd,
|
||||
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) {
|
||||
@ -1066,6 +1261,91 @@ xmlIconvWrapper(iconv_t cd,
|
||||
}
|
||||
#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
|
||||
@ -1113,8 +1393,8 @@ xmlCharEncInFunc(xmlCharEncodingHandler *handler, xmlBufferPtr out,
|
||||
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 @@ xmlCharEncInFunc(xmlCharEncodingHandler *handler, xmlBufferPtr out,
|
||||
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 @@ xmlCharEncInFunc(xmlCharEncodingHandler *handler, xmlBufferPtr out,
|
||||
* @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 @@ xmlCharEncOutFunc(xmlCharEncodingHandler *handler, xmlBufferPtr out,
|
||||
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 @@ xmlCharEncOutFunc(xmlCharEncodingHandler *handler, xmlBufferPtr out,
|
||||
}
|
||||
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 @@ xmlCharEncOutFunc(xmlCharEncodingHandler *handler, xmlBufferPtr out,
|
||||
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 @@ xmlCharEncOutFunc(xmlCharEncodingHandler *handler, xmlBufferPtr out,
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -102,6 +102,8 @@ typedef int (* xmlCharEncodingInputFunc)(unsigned char* out, int *outlen,
|
||||
*
|
||||
* 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 @@ void xmlRegisterCharEncodingHandler (xmlCharEncodingHandlerPtr handler);
|
||||
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 xmlCharEncOutFunc (xmlCharEncodingHandler *handler,
|
||||
int xmlCharEncInFunc (xmlCharEncodingHandler *handler,
|
||||
xmlBufferPtr out,
|
||||
xmlBufferPtr in);
|
||||
int xmlCharEncFirstLine (xmlCharEncodingHandler *handler,
|
||||
xmlBufferPtr out,
|
||||
xmlBufferPtr in);
|
||||
int xmlCharEncCloseFunc (xmlCharEncodingHandler *handler);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
80
entities.c
80
entities.c
@ -945,6 +945,86 @@ xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
|
||||
return(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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:
|
||||
*
|
||||
|
@ -106,6 +106,8 @@ const xmlChar * xmlEncodeEntities (xmlDocPtr doc,
|
||||
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);
|
||||
|
@ -6,5 +6,9 @@ INCLUDES = \
|
||||
|
||||
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))
|
||||
|
@ -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 @@ DEBUG("parsePerson\n");
|
||||
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 @@ DEBUG("parseJob\n");
|
||||
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 @@ DEBUG("parseJob\n");
|
||||
}
|
||||
}
|
||||
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 @@ gJobPtr parseGjobFile(char *filename) {
|
||||
* 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 @@ gJobPtr parseGjobFile(char *filename) {
|
||||
* 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 @@ gJobPtr parseGjobFile(char *filename) {
|
||||
}
|
||||
|
||||
/* 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 main(int argc, char **argv) {
|
||||
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 )
|
||||
|
@ -102,6 +102,8 @@ typedef int (* xmlCharEncodingInputFunc)(unsigned char* out, int *outlen,
|
||||
*
|
||||
* 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 @@ void xmlRegisterCharEncodingHandler (xmlCharEncodingHandlerPtr handler);
|
||||
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 xmlCharEncOutFunc (xmlCharEncodingHandler *handler,
|
||||
int xmlCharEncInFunc (xmlCharEncodingHandler *handler,
|
||||
xmlBufferPtr out,
|
||||
xmlBufferPtr in);
|
||||
int xmlCharEncFirstLine (xmlCharEncodingHandler *handler,
|
||||
xmlBufferPtr out,
|
||||
xmlBufferPtr in);
|
||||
int xmlCharEncCloseFunc (xmlCharEncodingHandler *handler);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -106,6 +106,8 @@ const xmlChar * xmlEncodeEntities (xmlDocPtr doc,
|
||||
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);
|
||||
|
@ -120,8 +120,8 @@ struct _xmlParserCtxt {
|
||||
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 @@ struct _xmlParserCtxt {
|
||||
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 */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -181,6 +181,7 @@ struct _xmlElement {
|
||||
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,12 +348,22 @@ struct _xmlDoc {
|
||||
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.
|
||||
*/
|
||||
@ -374,6 +385,9 @@ int xmlBufferDump (FILE *file,
|
||||
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 @@ xmlNodePtr xmlStringLenGetNodeList (xmlDocPtr doc,
|
||||
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 @@ int xmlReconciliateNs (xmlDocPtr doc,
|
||||
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 @@ void xmlElemDump (FILE *f,
|
||||
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
|
||||
*/
|
||||
|
@ -43,6 +43,8 @@ xmlURIPtr xmlCreateURI (void);
|
||||
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);
|
||||
|
@ -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 @@ struct _xmlParserInputBuffer {
|
||||
|
||||
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 @@ int xmlRegisterInputCallbacks (xmlInputMatchCallback match,
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -29,8 +29,8 @@ typedef xmlXPathParserContext *xmlXPathParserContextPtr;
|
||||
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 @@ struct _xmlNodeSet {
|
||||
* - boolean
|
||||
* - number
|
||||
* - string
|
||||
*
|
||||
* @@ XPointer will add more types !
|
||||
*/
|
||||
|
||||
#define XPATH_UNDEFINED 0
|
||||
|
10
nanoftp.c
10
nanoftp.c
@ -1193,7 +1193,9 @@ xmlNanoFTPGetConnection(void *ctx) {
|
||||
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 @@ xmlNanoFTPList(void *ctx, ftpListCallback callback, void *userData,
|
||||
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 @@ xmlNanoFTPList(void *ctx, ftpListCallback callback, void *userData,
|
||||
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 @@ xmlNanoFTPGetSocket(void *ctx, const char *filename) {
|
||||
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");
|
||||
|
17
nanohttp.c
17
nanohttp.c
@ -654,6 +654,23 @@ xmlNanoHTTPConnectAttempt(struct in_addr ia, int port)
|
||||
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);
|
||||
}
|
||||
|
197
parser.c
197
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 xmlParserHandleReference(xmlParserCtxtPtr ctxt);
|
||||
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 @@ xmlNextChar(xmlParserCtxtPtr ctxt) {
|
||||
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 @@ encoding_error:
|
||||
* 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 @@ xmlCurrentChar(xmlParserCtxtPtr ctxt, int *len) {
|
||||
*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 @@ encoding_error:
|
||||
* 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 @@ encoding_error:
|
||||
|
||||
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 @@ encoding_error:
|
||||
* 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 @@ xmlInitParserCtxt(xmlParserCtxtPtr ctxt)
|
||||
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 @@ xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
|
||||
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 @@ xmlParseStringCharRef(xmlParserCtxtPtr ctxt, const xmlChar **str) {
|
||||
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 @@ xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc)
|
||||
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 @@ xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc)
|
||||
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 @@ xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc)
|
||||
(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 @@ xmlSwitchEncoding(xmlParserCtxtPtr ctxt, xmlCharEncoding enc)
|
||||
}
|
||||
if (handler == NULL)
|
||||
return(-1);
|
||||
ctxt->charset = XML_CHAR_ENCODING_UTF8;
|
||||
return(xmlSwitchToEncoding(ctxt, handler));
|
||||
}
|
||||
|
||||
@ -2427,10 +2477,14 @@ xmlSwitchToEncoding(xmlParserCtxtPtr ctxt, xmlCharEncodingHandlerPtr handler)
|
||||
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 @@ xmlSwitchToEncoding(xmlParserCtxtPtr ctxt, xmlCharEncodingHandlerPtr handler)
|
||||
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 @@ xmlSwitchToEncoding(xmlParserCtxtPtr ctxt, xmlCharEncodingHandlerPtr handler)
|
||||
/*
|
||||
* 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 @@ xmlParseEntityValue(xmlParserCtxtPtr ctxt, xmlChar **orig) {
|
||||
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 @@ xmlParseAttValue(xmlParserCtxtPtr ctxt) {
|
||||
/*
|
||||
* 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 @@ xmlParseAttValue(xmlParserCtxtPtr ctxt) {
|
||||
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 @@ xmlParseAttValue(xmlParserCtxtPtr ctxt) {
|
||||
/*
|
||||
* 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 @@ xmlParseAttValue(xmlParserCtxtPtr ctxt) {
|
||||
ctxt->disableSAX = 1;
|
||||
} else
|
||||
NEXT;
|
||||
return(buffer);
|
||||
return(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -6341,7 +6381,7 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
|
||||
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 @@ xmlParseReference(xmlParserCtxtPtr ctxt) {
|
||||
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");
|
||||
@ -9557,15 +9597,6 @@ xmlParseChunk(xmlParserCtxtPtr ctxt, const char *chunk, int size,
|
||||
} else if (ctxt->instate != XML_PARSER_EOF)
|
||||
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
|
||||
*/
|
||||
|
10
parser.h
10
parser.h
@ -120,8 +120,8 @@ struct _xmlParserCtxt {
|
||||
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 @@ struct _xmlParserCtxt {
|
||||
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 */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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) {
|
||||
|
736
tree.c
736
tree.c
@ -846,6 +846,80 @@ xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) {
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -3787,7 +3861,7 @@ xmlBufferGrow(xmlBufferPtr buf, int len) {
|
||||
|
||||
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);
|
||||
@ -3948,6 +4022,52 @@ xmlBufferAdd(xmlBufferPtr buf, const xmlChar *str, int len) {
|
||||
buf->content[buf->use] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -4045,6 +4165,12 @@ xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string) {
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* *
|
||||
* 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 @@ xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* *
|
||||
* 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 @@ xmlSetCompressMode(int mode) {
|
||||
else xmlCompressMode = mode;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* xmlDocDump:
|
||||
* @f: the FILE*
|
||||
@ -4698,4 +5308,128 @@ xmlSaveFile(const char *filename, xmlDocPtr cur) {
|
||||
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
|
||||
|
32
tree.h
32
tree.h
@ -181,6 +181,7 @@ struct _xmlElement {
|
||||
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,12 +348,22 @@ struct _xmlDoc {
|
||||
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.
|
||||
*/
|
||||
@ -374,6 +385,9 @@ int xmlBufferDump (FILE *file,
|
||||
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 @@ xmlNodePtr xmlStringLenGetNodeList (xmlDocPtr doc,
|
||||
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 @@ int xmlReconciliateNs (xmlDocPtr doc,
|
||||
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 @@ void xmlElemDump (FILE *f,
|
||||
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
|
||||
*/
|
||||
|
5
uri.c
5
uri.c
@ -1513,7 +1513,10 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
|
||||
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
|
||||
|
2
uri.h
2
uri.h
@ -43,6 +43,8 @@ xmlURIPtr xmlCreateURI (void);
|
||||
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);
|
||||
|
331
valid.c
331
valid.c
@ -154,6 +154,61 @@ void xmlValidDebug(xmlNodePtr cur, xmlElementContentPtr cont) {
|
||||
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 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name,
|
||||
xmlElementContentPtr content) {
|
||||
xmlElementPtr ret, cur;
|
||||
xmlElementTablePtr table;
|
||||
xmlChar *ns, *uqname;
|
||||
int i;
|
||||
|
||||
if (dtd == NULL) {
|
||||
@ -472,6 +528,13 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name,
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* check if name is a QName
|
||||
*/
|
||||
uqname = xmlSplitQName2(name, &ns);
|
||||
if (uqname != NULL)
|
||||
name = uqname;
|
||||
|
||||
/*
|
||||
* Create the Element table if needed.
|
||||
*/
|
||||
@ -489,7 +552,10 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name,
|
||||
*/
|
||||
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 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name,
|
||||
*/
|
||||
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 @@ xmlAddElementDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name,
|
||||
ret->prev = dtd->last;
|
||||
dtd->last = (xmlNodePtr) ret;
|
||||
}
|
||||
if (uqname != NULL)
|
||||
xmlFree(uqname);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
@ -559,6 +628,8 @@ xmlFreeElement(xmlElementPtr elem) {
|
||||
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 @@ xmlScanIDAttributeDecl(xmlValidCtxtPtr ctxt, xmlElementPtr elem) {
|
||||
*
|
||||
* 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 @@ xmlAddAttributeDecl(xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *elem,
|
||||
*/
|
||||
VWARNING(ctxt->userData, "Attribute %s on %s: already defined\n",
|
||||
elem, name);
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1157,6 +1229,10 @@ xmlDumpAttributeDecl(xmlBufferPtr buf, xmlAttributePtr attr) {
|
||||
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 @@ xmlElementPtr
|
||||
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 @@ xmlGetDtdElementDesc(xmlDtdPtr dtd, const xmlChar *name) {
|
||||
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 @@ xmlAttributePtr
|
||||
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 @@ xmlGetDtdAttrDesc(xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name) {
|
||||
(!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 @@ xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem,
|
||||
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 @@ int
|
||||
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 @@ xmlValidateOneAttribute(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
|
||||
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 @@ xmlSprintfElementChilds(char *buf, xmlNodePtr node, int glob) {
|
||||
int
|
||||
xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
|
||||
xmlNodePtr elem) {
|
||||
xmlElementPtr elemDecl;
|
||||
xmlElementPtr elemDecl = NULL;
|
||||
xmlElementContentPtr cont;
|
||||
xmlAttributePtr attr;
|
||||
xmlNodePtr child;
|
||||
@ -3347,9 +3580,25 @@ xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
|
||||
}
|
||||
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 @@ xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
|
||||
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 @@ xmlValidateOneElement(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
child_ok:
|
||||
child = child->next;
|
||||
}
|
||||
break;
|
||||
@ -3518,15 +3796,32 @@ xmlValidateRoot(xmlValidCtxtPtr ctxt, xmlDocPtr doc) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
627
xmlIO.c
627
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 @@ xmlInputCallback xmlInputCallbackTable[MAX_INPUT_CALLBACK];
|
||||
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 *
|
||||
@ -123,11 +139,44 @@ xmlFdOpen (const char *filename) {
|
||||
return((void *) fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
@ -138,6 +187,21 @@ xmlFdRead (void * context, char * buffer, int len) {
|
||||
return(read((int) context, &buffer[0], len));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -198,6 +262,38 @@ xmlFileOpen (const char *filename) {
|
||||
return((void *) fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -213,6 +309,21 @@ xmlFileRead (void * context, char * buffer, int len) {
|
||||
return(fread(&buffer[0], 1, len, (FILE *) context));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -273,6 +384,39 @@ xmlGzfileOpen (const char *filename) {
|
||||
return((void *) fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -288,6 +432,21 @@ xmlGzfileRead (void * context, char * buffer, int len) {
|
||||
return(gzread((gzFile) context, &buffer[0], len));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -448,6 +607,31 @@ xmlRegisterInputCallbacks(xmlInputMatchCallback match,
|
||||
return(xmlInputCallbackNr++);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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:
|
||||
*
|
||||
@ -473,6 +657,39 @@ xmlRegisterDefaultInputCallbacks(void) {
|
||||
#endif /* LIBXML_FTP_ENABLED */
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -509,6 +726,47 @@ xmlAllocParserInputBuffer(xmlCharEncoding enc) {
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -536,6 +794,43 @@ xmlFreeParserInputBuffer(xmlParserInputBufferPtr in) {
|
||||
xmlFree(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -591,6 +886,80 @@ xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc) {
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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*
|
||||
@ -620,6 +989,35 @@ xmlParserInputBufferCreateFile(FILE *file, xmlCharEncoding enc) {
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -646,6 +1044,32 @@ xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -654,7 +1078,7 @@ xmlParserInputBufferCreateFd(int fd, xmlCharEncoding enc) {
|
||||
* @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
|
||||
*/
|
||||
@ -675,11 +1099,41 @@ xmlParserInputBufferCreateIO(xmlInputReadCallback ioread,
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 @@ xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
|
||||
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 @@ xmlParserInputBufferGrow(xmlParserInputBufferPtr in, int len) {
|
||||
return(-1);
|
||||
}
|
||||
} else {
|
||||
nbchars = res;
|
||||
nbchars = len;
|
||||
buffer[nbchars] = 0;
|
||||
xmlBufferAdd(in->buffer, (xmlChar *) buffer, nbchars);
|
||||
}
|
||||
@ -827,7 +1277,162 @@ xmlParserInputBufferRead(xmlParserInputBufferPtr in, int len) {
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
79
xmlIO.h
79
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 @@ struct _xmlParserInputBuffer {
|
||||
|
||||
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 @@ int xmlRegisterInputCallbacks (xmlInputMatchCallback match,
|
||||
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
|
||||
|
14
xmllint.c
14
xmllint.c
@ -68,6 +68,7 @@ static int htmlout = 0;
|
||||
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 @@ void parseAndPrintFile(char *filename) {
|
||||
#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 main(int argc, char **argv) {
|
||||
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 @@ int main(int argc, char **argv) {
|
||||
(!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 @@ int main(int argc, char **argv) {
|
||||
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++)
|
||||
|
@ -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
|
||||
|
65
xpath.c
65
xpath.c
@ -733,15 +733,19 @@ xmlXPathNewNodeSet(xmlNodePtr val) {
|
||||
xmlXPathObjectPtr
|
||||
xmlXPathNewNodeSetList(xmlNodeSetPtr val) {
|
||||
xmlXPathObjectPtr ret;
|
||||
int i;
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
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;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
@ -1541,7 +1545,11 @@ xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
|
||||
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 @@ xmlXPathEvalPathExpr(xmlXPathParserContextPtr ctxt) {
|
||||
xmlXPathEvalFilterExpr(ctxt);
|
||||
if (name != NULL)
|
||||
xmlFree(name);
|
||||
}
|
||||
|
||||
if (ctxt->context->nodelist != NULL)
|
||||
valuePush(ctxt, xmlXPathNewNodeSetList(ctxt->context->nodelist));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3933,7 +3942,7 @@ xmlXPathEvalAndExpr(xmlXPathParserContextPtr ctxt) {
|
||||
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 @@ xmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt,
|
||||
void
|
||||
xmlXPathEvalPredicate(xmlXPathParserContextPtr ctxt) {
|
||||
const xmlChar *cur;
|
||||
xmlXPathObjectPtr res;
|
||||
xmlXPathObjectPtr res, listHolder = NULL;
|
||||
xmlNodeSetPtr newset = NULL;
|
||||
int i;
|
||||
|
||||
@ -4049,20 +4058,42 @@ xmlXPathEvalPredicate(xmlXPathParserContextPtr ctxt) {
|
||||
} 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 @@ xmlXPathEvalStep(xmlXPathParserContextPtr ctxt) {
|
||||
while (CUR == '[') {
|
||||
xmlXPathEvalPredicate(ctxt);
|
||||
}
|
||||
|
||||
while (CUR == '@') {
|
||||
xmlXPathEvalBasis(ctxt);
|
||||
ctxt->context->node = NULL;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_STEP
|
||||
fprintf(xmlXPathDebug, "Step : ");
|
||||
@ -4537,6 +4573,7 @@ xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctxt) {
|
||||
res = xmlXPathNewNodeSetList(pctxt->context->nodelist);
|
||||
else
|
||||
res = NULL;
|
||||
|
||||
xmlXPathFreeParserContext(pctxt);
|
||||
return(res);
|
||||
}
|
||||
|
6
xpath.h
6
xpath.h
@ -29,8 +29,8 @@ typedef xmlXPathParserContext *xmlXPathParserContextPtr;
|
||||
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 @@ struct _xmlNodeSet {
|
||||
* - boolean
|
||||
* - number
|
||||
* - string
|
||||
*
|
||||
* @@ XPointer will add more types !
|
||||
*/
|
||||
|
||||
#define XPATH_UNDEFINED 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user