- 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:
Daniel Veillard 2000-06-28 23:40:59 +00:00
parent c310d56482
commit be803967db
41 changed files with 2877 additions and 1562 deletions

View File

@ -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

View File

@ -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
*/

View File

@ -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, "=\"\"");
}
}
}

View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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()

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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:
*

View File

@ -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);

View File

@ -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))

View File

@ -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 )

View File

@ -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

View File

@ -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);

View File

@ -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 */
};
/**

View File

@ -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
*/

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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
View File

@ -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
*/

View File

@ -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 */
};
/**

View File

@ -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>

View File

@ -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&amp;Filter=docs_filter.hts&amp;ResultTemplate=vignette.hts&amp;Collection=vignette&amp;QueryMode=Internet&amp;Query=">Wired News</option>
<option value="http://search.hotwired.com/search97/s97.vts?Action=FilterSearch&amp;Filter=docs_filter.hts&amp;ResultTemplate=vignette.hts&amp;Collection=vignette&amp;QueryMode=Internet&amp;Query=" selected>Wired News</option>
<option value="http://search.hotwired.com/search97/s97.vts?Action=FilterSearch&amp;Filter=docs_filter.hts&amp;ResultTemplate=webmonkey.hts&amp;Collection=webmonkey&amp;QueryMode=Internet&amp;Query=">Webmonkey</option>
<option value="http://search.hotwired.com/search97/s97.vts?collection=webmonkey_guides&amp;Action=FilterSearch&amp;filter=docs_filter.hts&amp;ResultTemplate=webmonkey_guides.hts&amp;QueryMode=Internet&amp;Query=">Webmonkey Guides</option>
<option value="http://search.hotwired.com/search97/s97.vts?collection=hotwired&amp;Action=FilterSearch&amp;filter=docs_filter.hts&amp;ResultTemplate=hotwired_archive.hts&amp;QueryMode=Internet&amp;Query=">HotWired Archives</option>

View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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

View File

@ -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++)

View File

@ -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
View File

@ -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);
}

View File

@ -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