Finally had a bit of time to resynch both trees:
- HTMLparser.[ch]: added a way to avoid adding automatically
omitted tags. htmlHandleOmittedElem() allows to change the
default handling.
- tree.[ch] xmllint.c: added xmlDocDumpFormatMemory() and
xmlDocDumpFormatMemoryEnc(), uses memory functions for output
of xmllint too when using --memory flag, added a memory test
suite at the Makefile level.
- xpathInternals.h xpath.[ch] xpointer.c: fixed problems
with namespace use when encountering QNames in XPath evalation,
added xmlns() scheme in XPointer.
- nanoftp.c : incorporated a fix
- parser.c xmlIO.c: fixed problems raised with encoding when using
the memory I/O
- parserInternals.c: closed bug 25934 reported by
torsten.landschoff@innominate.de
- TODO: updated
Daniel
diff --git a/ChangeLog b/ChangeLog
index f86f81a..d1d2490 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+Wed Dec 27 12:35:49 CET 2000 Daniel Veillard <Daniel.Veillard@w3.org>
+
+ * HTMLparser.[ch]: added a way to avoid adding automatically
+ omitted tags. htmlHandleOmittedElem() allows to change the
+ default handling.
+ * tree.[ch] xmllint.c: added xmlDocDumpFormatMemory() and
+ xmlDocDumpFormatMemoryEnc(), uses memory functions for output
+ of xmllint too when using --memory flag, added a memory test
+ suite at the Makefile level.
+ * xpathInternals.h xpath.[ch] xpointer.c: fixed problems
+ with namespace use when encountering QNames in XPath evalation,
+ added xmlns() scheme in XPointer.
+ * nanoftp.c : incorporated a fix
+ * parser.c xmlIO.c: fixed problems raised with encoding when using
+ the memory I/O
+ * parserInternals.c: closed bug 25934 reported by
+ torsten.landschoff@innominate.de
+ * TODO: updated
+
Sat Nov 25 11:46:27 CET 2000 Daniel Veillard <Daniel.Veillard@w3.org>
* configure.in doc/html/* doc/xml.html: made a 2.2.9 release
diff --git a/HTMLparser.c b/HTMLparser.c
index f2831f6..a494132 100644
--- a/HTMLparser.c
+++ b/HTMLparser.c
@@ -53,6 +53,8 @@
/* #define DEBUG */
/* #define DEBUG_PUSH */
+int htmlOmittedDefaultValue = 1;
+
/************************************************************************
* *
* Parser stacks related functions and macros *
@@ -837,12 +839,14 @@
* @ctxt: an HTML parser context
* @newtag: The new tag name
*
- * The HTmL DtD allows a tag to exists only implicitely
+ * 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 *newtag) {
+ if (!htmlOmittedDefaultValue)
+ return;
if (xmlStrEqual(newtag, BAD_CAST"html"))
return;
if (ctxt->nameNr <= 0) {
@@ -2787,6 +2791,10 @@
if ((ctxt == NULL) || (attvalue == NULL))
return;
+ /* do not change encoding */
+ if (ctxt->input->encoding != NULL)
+ return;
+
encoding = xmlStrcasestr(attvalue, BAD_CAST"charset=");
if (encoding != NULL) {
encoding += 8;
@@ -4822,6 +4830,7 @@
htmlParserInputPtr inputStream;
xmlParserInputBufferPtr buf;
/* htmlCharEncoding enc; */
+ xmlChar *content, *content_line = (xmlChar *) "charset=";
buf = xmlParserInputBufferCreateFilename(filename, XML_CHAR_ENCODING_NONE);
if (buf == NULL) return(NULL);
@@ -4852,6 +4861,18 @@
inputStream->free = NULL;
inputPush(ctxt, inputStream);
+
+ /* set encoding */
+ if (encoding) {
+ content = xmlMalloc (xmlStrlen(content_line) + strlen(encoding) + 1);
+ if (content) {
+ strcpy ((char *)content, (char *)content_line);
+ strcat ((char *)content, (char *)encoding);
+ htmlCheckEncoding (ctxt, content);
+ xmlFree (content);
+ }
+ }
+
return(ctxt);
}
@@ -4913,4 +4934,21 @@
return(htmlSAXParseFile(filename, encoding, NULL, NULL));
}
+/**
+ * htmlHandleOmittedElem:
+ * @val: int 0 or 1
+ *
+ * Set and return the previous value for handling HTML omitted tags.
+ *
+ * Returns the last value for 0 for no handling, 1 for auto insertion.
+ */
+
+int
+htmlHandleOmittedElem(int val) {
+ int old = htmlOmittedDefaultValue;
+
+ htmlOmittedDefaultValue = val;
+ return(old);
+}
+
#endif /* LIBXML_HTML_ENABLED */
diff --git a/HTMLparser.h b/HTMLparser.h
index be95357..b70c0a1 100644
--- a/HTMLparser.h
+++ b/HTMLparser.h
@@ -91,6 +91,7 @@
const unsigned char* in,
int *inlen, int quoteChar);
int htmlIsScriptAttribute(const xmlChar *name);
+int htmlHandleOmittedElem(int val);
/**
* Interfaces for the Push mode
diff --git a/Makefile.am b/Makefile.am
index 1e711fe..1bd18c3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -179,6 +179,24 @@
diff result.$$name result2.$$name ; \
rm result.$$name result2.$$name ; \
fi ; fi ; done)
+ @echo "##"
+ @echo "## XML regression tests on memory"
+ @echo "##"
+ @(for i in $(srcdir)/test/* ; do \
+ name=`basename $$i`; \
+ if [ ! -d $$i ] ; then \
+ if [ ! -f $(srcdir)/result/$$name ] ; then \
+ echo New test file $$name ; \
+ $(top_builddir)/xmllint --memory $$i > $(srcdir)/result/$$name ; \
+ else \
+ echo Testing $$name ; \
+ $(top_builddir)/xmllint --memory $$i > result.$$name ; \
+ grep "MORY ALLO" .memdump | grep -v "MEMORY ALLOCATED : 0";\
+ diff $(srcdir)/result/$$name result.$$name ; \
+ $(top_builddir)/xmllint --memory result.$$name > result2.$$name ; \
+ diff result.$$name result2.$$name ; \
+ rm result.$$name result2.$$name ; \
+ fi ; fi ; done)
XMLenttests : xmllint
@echo "##"
diff --git a/TODO b/TODO
index 61ba935..e83773a 100644
--- a/TODO
+++ b/TODO
@@ -32,6 +32,9 @@
- jamesh suggestion: SAX like functions to save a document ie. call a
function to open a new element with given attributes, write character
data, close last element, etc
+- htmlParseDoc has parameter encoding which is not used.
+ Function htmlCreateDocParserCtxt ignore it.
+
TODO:
=====
diff --git a/aclocal.m4 b/aclocal.m4
index 869e5fc..e372675 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -620,31 +620,35 @@
])
# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for
-# the libltdl convenience library, adds --enable-ltdl-convenience to
-# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor
-# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed
-# to be `${top_builddir}/libltdl'. Make sure you start DIR with
-# '${top_builddir}/' (note the single quotes!) if your package is not
-# flat, and, if you're not using automake, define top_builddir as
-# appropriate in the Makefiles.
+# the libltdl convenience library and INCLTDL to the include flags for
+# the libltdl header and adds --enable-ltdl-convenience to the
+# configure arguments. Note that LIBLTDL and INCLTDL are not
+# AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If DIR is not
+# provided, it is assumed to be `libltdl'. LIBLTDL will be prefixed
+# with '${top_builddir}/' and INCLTDL will be prefixed with
+# '${top_srcdir}/' (note the single quotes!). If your package is not
+# flat and you're not using automake, define top_builddir and
+# top_srcdir appropriately in the Makefiles.
AC_DEFUN(AC_LIBLTDL_CONVENIENCE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
case "$enable_ltdl_convenience" in
no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
"") enable_ltdl_convenience=yes
ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
esac
- LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdlc.la
- INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl'])
+ LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
+ INCLTDL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
])
# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for
-# the libltdl installable library, and adds --enable-ltdl-install to
-# the configure arguments. Note that LIBLTDL is not AC_SUBSTed, nor
-# is AC_CONFIG_SUBDIRS called. If DIR is not provided, it is assumed
-# to be `${top_builddir}/libltdl'. Make sure you start DIR with
-# '${top_builddir}/' (note the single quotes!) if your package is not
-# flat, and, if you're not using automake, define top_builddir as
-# appropriate in the Makefiles.
+# the libltdl installable library and INCLTDL to the include flags for
+# the libltdl header and adds --enable-ltdl-install to the configure
+# arguments. Note that LIBLTDL and INCLTDL are not AC_SUBSTed, nor is
+# AC_CONFIG_SUBDIRS called. If DIR is not provided and an installed
+# libltdl is not found, it is assumed to be `libltdl'. LIBLTDL will
+# be prefixed with '${top_builddir}/' and INCLTDL will be prefixed
+# with '${top_srcdir}/' (note the single quotes!). If your package is
+# not flat and you're not using automake, define top_builddir and
+# top_srcdir appropriately in the Makefiles.
# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
AC_DEFUN(AC_LIBLTDL_INSTALLABLE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
AC_CHECK_LIB(ltdl, main,
@@ -657,8 +661,8 @@
])
if test x"$enable_ltdl_install" = x"yes"; then
ac_configure_args="$ac_configure_args --enable-ltdl-install"
- LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdl.la
- INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl'])
+ LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
+ INCLTDL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
else
ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
LIBLTDL="-lltdl"
diff --git a/include/libxml/HTMLparser.h b/include/libxml/HTMLparser.h
index be95357..b70c0a1 100644
--- a/include/libxml/HTMLparser.h
+++ b/include/libxml/HTMLparser.h
@@ -91,6 +91,7 @@
const unsigned char* in,
int *inlen, int quoteChar);
int htmlIsScriptAttribute(const xmlChar *name);
+int htmlHandleOmittedElem(int val);
/**
* Interfaces for the Push mode
diff --git a/include/libxml/tree.h b/include/libxml/tree.h
index 7b19d09..2dc3242 100644
--- a/include/libxml/tree.h
+++ b/include/libxml/tree.h
@@ -634,6 +634,10 @@
/*
* Saving
*/
+void xmlDocDumpFormatMemory (xmlDocPtr cur,
+ xmlChar**mem,
+ int *size,
+ int format);
void xmlDocDumpMemory (xmlDocPtr cur,
xmlChar**mem,
int *size);
@@ -641,6 +645,11 @@
xmlChar **doc_txt_ptr,
int * doc_txt_len,
const char *txt_encoding);
+void xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc,
+ xmlChar **doc_txt_ptr,
+ int * doc_txt_len,
+ const char *txt_encoding,
+ int format);
int xmlDocDump (FILE *f,
xmlDocPtr cur);
void xmlElemDump (FILE *f,
diff --git a/include/libxml/xpath.h b/include/libxml/xpath.h
index 553b3fc..6f820d4 100644
--- a/include/libxml/xpath.h
+++ b/include/libxml/xpath.h
@@ -47,7 +47,8 @@
XPATH_MEMORY_ERROR,
XPTR_SYNTAX_ERROR,
XPTR_RESOURCE_ERROR,
- XPTR_SUB_RESOURCE_ERROR
+ XPTR_SUB_RESOURCE_ERROR,
+ XPATH_UNDEF_PREFIX_ERROR
} xmlXPathError;
/*
@@ -171,6 +172,8 @@
* - a set of variable bindings
* - a function library
* - the set of namespace declarations in scope for the expression
+ * Following the switch to hash tables, this need to be trimmed up at
+ * the next binary incompatible release.
*/
struct _xmlXPathContext {
@@ -193,10 +196,10 @@
int max_axis; /* max number of axis */
xmlXPathAxisPtr axis; /* Array of defined axis */
- /* Namespace traversal should be implemented with user */
- xmlNsPtr *namespaces; /* The namespaces lookup */
- int nsNr; /* the current Namespace index */
- void *user; /* user defined extra info */
+ /* the namespace nodes of the context node */
+ xmlNsPtr *namespaces; /* Array of namespaces */
+ int nsNr; /* number of namespace in scope */
+ void *user; /* function to free */
/* extra variables */
int contextSize; /* the context size */
@@ -206,6 +209,9 @@
int xptr; /* it this an XPointer context */
xmlNodePtr here; /* for here() */
xmlNodePtr origin; /* for origin() */
+
+ /* the set of namespace declarations in scope for the expression */
+ xmlHashTablePtr nsHash; /* The namespaces hash table */
};
/*
diff --git a/include/libxml/xpathInternals.h b/include/libxml/xpathInternals.h
index a18e453..6967c90 100644
--- a/include/libxml/xpathInternals.h
+++ b/include/libxml/xpathInternals.h
@@ -68,6 +68,13 @@
/**
* Extending a context
*/
+int xmlXPathRegisterNs (xmlXPathContextPtr ctxt,
+ const xmlChar *prefix,
+ const xmlChar *ns_uri);
+const xmlChar * xmlXPathNsLookup (xmlXPathContextPtr ctxt,
+ const xmlChar *ns_uri);
+void xmlXPathRegisteredNsCleanup (xmlXPathContextPtr ctxt);
+
int xmlXPathRegisterFunc (xmlXPathContextPtr ctxt,
const xmlChar *name,
xmlXPathFunction f);
@@ -121,6 +128,7 @@
void xmlXPathRoot (xmlXPathParserContextPtr ctxt);
void xmlXPathEvalExpr (xmlXPathParserContextPtr ctxt);
xmlChar * xmlXPathParseName (xmlXPathParserContextPtr ctxt);
+xmlChar * xmlXPathParseNCName (xmlXPathParserContextPtr ctxt);
/*
* Debug
diff --git a/nanoftp.c b/nanoftp.c
index 1207355..c7ea79a 100644
--- a/nanoftp.c
+++ b/nanoftp.c
@@ -650,6 +650,9 @@
* and analyzed.
*/
len = xmlNanoFTPGetMore(ctx);
+ if (len < 0) {
+ return(-1);
+ }
if ((ctxt->controlBufUsed == 0) && (len == 0)) {
return(-1);
}
diff --git a/parser.c b/parser.c
index c3ea2a3..f3f0565 100644
--- a/parser.c
+++ b/parser.c
@@ -8189,17 +8189,23 @@
if ((terminate) || (ctxt->input->buf->buffer->use > 80))
xmlParseTryOrFinish(ctxt, terminate);
- } else if (ctxt->instate != XML_PARSER_EOF)
- if ((ctxt->input != NULL) && ctxt->input->buf != NULL) {
- xmlParserInputBufferPtr in = ctxt->input->buf;
- int nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
- if (nbchars < 0) {
- xmlGenericError(xmlGenericErrorContext,
- "xmlParseChunk: encoder error\n");
- return(XML_ERR_INVALID_ENCODING);
- }
- }
- xmlParseTryOrFinish(ctxt, terminate);
+ } else if (ctxt->instate != XML_PARSER_EOF) {
+ if ((ctxt->input != NULL) && ctxt->input->buf != NULL) {
+ xmlParserInputBufferPtr in = ctxt->input->buf;
+ if ((in->encoder != NULL) && (in->buffer != NULL) &&
+ (in->raw != NULL)) {
+ int nbchars;
+
+ nbchars = xmlCharEncInFunc(in->encoder, in->buffer, in->raw);
+ if (nbchars < 0) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlParseChunk: encoder error\n");
+ return(XML_ERR_INVALID_ENCODING);
+ }
+ }
+ }
+ }
+ xmlParseTryOrFinish(ctxt, terminate);
if (terminate) {
/*
* Check for termination
@@ -9234,6 +9240,7 @@
} else {
inputStream = xmlLoadExternalEntity((char *)uri, (char *)ID, ctxt);
if (inputStream == NULL) {
+ xmlFree(uri);
xmlFreeParserCtxt(ctxt);
return(NULL);
}
diff --git a/parserInternals.c b/parserInternals.c
index d9cde91..a20faf5 100644
--- a/parserInternals.c
+++ b/parserInternals.c
@@ -481,7 +481,7 @@
(((c) >= 0x06D0) && ((c) <= 0x06D3)) ||
((c) == 0x06D5) ||
(((c) >= 0x06E5) && ((c) <= 0x06E6)) ||
- (((c) > 0x905) && ( /* accelerator */
+ (((c) >= 0x905) && ( /* accelerator */
(((c) >= 0x0905) && ((c) <= 0x0939)) ||
((c) == 0x093D) ||
(((c) >= 0x0958) && ((c) <= 0x0961)) ||
@@ -572,7 +572,7 @@
(((c) >= 0x0EC0) && ((c) <= 0x0EC4)) ||
(((c) >= 0x0F40) && ((c) <= 0x0F47)) ||
(((c) >= 0x0F49) && ((c) <= 0x0F69)) ||
- (((c) > 0x10A0) && ( /* accelerator */
+ (((c) >= 0x10A0) && ( /* accelerator */
(((c) >= 0x10A0) && ((c) <= 0x10C5)) ||
(((c) >= 0x10D0) && ((c) <= 0x10F6)) ||
((c) == 0x1100) ||
@@ -697,7 +697,7 @@
(((c) >= 0x06E0) && ((c) <= 0x06E4)) ||
(((c) >= 0x06E7) && ((c) <= 0x06E8)) ||
(((c) >= 0x06EA) && ((c) <= 0x06ED)) ||
- (((c) > 0x0901) && ( /* accelerator */
+ (((c) >= 0x0901) && ( /* accelerator */
(((c) >= 0x0901) && ((c) <= 0x0903)) ||
((c) == 0x093C) ||
(((c) >= 0x093E) && ((c) <= 0x094C)) ||
@@ -713,7 +713,7 @@
(((c) >= 0x09CB) && ((c) <= 0x09CD)) ||
((c) == 0x09D7) ||
(((c) >= 0x09E2) && ((c) <= 0x09E3)) ||
- (((c) > 0x0A02) && ( /* accelerator */
+ (((c) >= 0x0A02) && ( /* accelerator */
((c) == 0x0A02) ||
((c) == 0x0A3C) ||
((c) == 0x0A3E) ||
@@ -753,7 +753,7 @@
(((c) >= 0x0D46) && ((c) <= 0x0D48)) ||
(((c) >= 0x0D4A) && ((c) <= 0x0D4D)) ||
((c) == 0x0D57) ||
- (((c) > 0x0E31) && ( /* accelerator */
+ (((c) >= 0x0E31) && ( /* accelerator */
((c) == 0x0E31) ||
(((c) >= 0x0E34) && ((c) <= 0x0E3A)) ||
(((c) >= 0x0E47) && ((c) <= 0x0E4E)) ||
diff --git a/tree.c b/tree.c
index 1d6c3a1..8d24503 100644
--- a/tree.c
+++ b/tree.c
@@ -5098,44 +5098,6 @@
xmlBufferFree(buf);
}
-/**
- * xmlDocContentDump:
- * @buf: the XML buffer output
- * @cur: the document
- *
- * Dump an XML document.
- */
-static void
-xmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
- xmlBufferWriteChar(buf, "<?xml version=");
- if (cur->version != NULL)
- xmlBufferWriteQuotedString(buf, cur->version);
- else
- xmlBufferWriteChar(buf, "\"1.0\"");
- if (cur->encoding != NULL) {
- xmlBufferWriteChar(buf, " encoding=");
- xmlBufferWriteQuotedString(buf, cur->encoding);
- }
- switch (cur->standalone) {
- case 0:
- xmlBufferWriteChar(buf, " standalone=\"no\"");
- break;
- case 1:
- xmlBufferWriteChar(buf, " standalone=\"yes\"");
- break;
- }
- xmlBufferWriteChar(buf, "?>\n");
- if (cur->children != NULL) {
- xmlNodePtr child = cur->children;
-
- while (child != NULL) {
- xmlNodeDump(buf, cur, child, 0, 0);
- xmlBufferWriteChar(buf, "\n");
- child = child->next;
- }
- }
-}
-
/************************************************************************
* *
* Dumping XML tree content to an I/O output buffer *
@@ -5522,12 +5484,13 @@
* @buf: the XML buffer output
* @cur: the document
* @encoding: an optional encoding string
+ * @format: should formatting spaces been added
*
* Dump an XML document.
*/
static void
xmlDocContentDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr cur,
- const char *encoding) {
+ const char *encoding, int format) {
xmlOutputBufferWriteString(buf, "<?xml version=");
if (cur->version != NULL)
xmlBufferWriteQuotedString(buf->buffer, cur->version);
@@ -5556,7 +5519,7 @@
xmlNodePtr child = cur->children;
while (child != NULL) {
- xmlNodeDumpOutput(buf, cur, child, 0, 1, encoding);
+ xmlNodeDumpOutput(buf, cur, child, 0, format, encoding);
xmlOutputBufferWriteString(buf, "\n");
child = child->next;
}
@@ -5570,6 +5533,105 @@
************************************************************************/
/**
+ * xmlDocDumpMemoryEnc:
+ * @out_doc: Document to generate XML text from
+ * @doc_txt_ptr: Memory pointer for allocated XML text
+ * @doc_txt_len: Length of the generated XML text
+ * @txt_encoding: Character encoding to use when generating XML text
+ * @format: should formatting spaces been added
+ *
+ * Dump the current DOM tree into memory using the character encoding specified
+ * by the caller. Note it is up to the caller of this function to free the
+ * allocated memory.
+ */
+
+void
+xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr,
+ int * doc_txt_len, const char * txt_encoding, int format) {
+ int dummy = 0;
+
+ xmlCharEncoding doc_charset;
+ xmlOutputBufferPtr out_buff = NULL;
+ xmlCharEncodingHandlerPtr conv_hdlr = NULL;
+
+ if (doc_txt_len == NULL) {
+ doc_txt_len = &dummy; /* Continue, caller just won't get length */
+ }
+
+ if (doc_txt_ptr == NULL) {
+ *doc_txt_len = 0;
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlDocDumpFormatMemoryEnc: Null return buffer pointer.");
+ return;
+ }
+
+ *doc_txt_ptr = NULL;
+ *doc_txt_len = 0;
+
+ if (out_doc == NULL) {
+ /* No document, no output */
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlDocDumpFormatMemoryEnc: Null DOM tree document pointer.\n");
+ return;
+ }
+
+ /*
+ * Validate the encoding value, if provided.
+ * This logic is copied from xmlSaveFileEnc.
+ */
+
+ if (txt_encoding == NULL)
+ txt_encoding = (const char *) out_doc->encoding;
+ if (txt_encoding != NULL) {
+ doc_charset = xmlParseCharEncoding(txt_encoding);
+
+ if (out_doc->charset != XML_CHAR_ENCODING_UTF8) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlDocDumpFormatMemoryEnc: Source document not in UTF8\n");
+ return;
+
+ } else if (doc_charset != XML_CHAR_ENCODING_UTF8) {
+ conv_hdlr = xmlFindCharEncodingHandler(txt_encoding);
+ if ( conv_hdlr == NULL ) {
+ xmlGenericError(xmlGenericErrorContext,
+ "%s: %s %s '%s'\n",
+ "xmlDocDumpFormatMemoryEnc",
+ "Failed to identify encoding handler for",
+ "character set",
+ txt_encoding);
+ return;
+ }
+ }
+ }
+
+ if ((out_buff = xmlAllocOutputBuffer(conv_hdlr)) == NULL ) {
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlDocDumpFormatMemoryEnc: Failed to allocate output buffer.\n");
+ return;
+ }
+
+ xmlDocContentDumpOutput(out_buff, out_doc, txt_encoding, 1);
+ xmlOutputBufferFlush(out_buff);
+ if (out_buff->conv != NULL) {
+ *doc_txt_len = out_buff->conv->use;
+ *doc_txt_ptr = xmlStrndup(out_buff->conv->content, *doc_txt_len);
+ } else {
+ *doc_txt_len = out_buff->buffer->use;
+ *doc_txt_ptr = xmlStrndup(out_buff->buffer->content, *doc_txt_len);
+ }
+ (void)xmlOutputBufferClose(out_buff);
+
+ if ((*doc_txt_ptr == NULL) && (*doc_txt_len > 0)) {
+ *doc_txt_len = 0;
+ xmlGenericError(xmlGenericErrorContext,
+ "xmlDocDumpFormatMemoryEnc: %s\n",
+ "Failed to allocate memory for document text representation.");
+ }
+
+ return;
+}
+
+/**
* xmlDocDumpMemory:
* @cur: the document
* @mem: OUT: the memory pointer
@@ -5580,27 +5642,23 @@
*/
void
xmlDocDumpMemory(xmlDocPtr cur, xmlChar**mem, int *size) {
- xmlBufferPtr buf;
+ xmlDocDumpFormatMemoryEnc(cur, mem, size, NULL, 0);
+}
- if (cur == NULL) {
-#ifdef DEBUG_TREE
- xmlGenericError(xmlGenericErrorContext,
- "xmlDocDumpMemory : document == NULL\n");
-#endif
- *mem = NULL;
- *size = 0;
- return;
- }
- buf = xmlBufferCreate();
- if (buf == NULL) {
- *mem = NULL;
- *size = 0;
- return;
- }
- xmlDocContentDump(buf, cur);
- *mem = xmlStrndup(buf->content, buf->use);
- *size = buf->use;
- xmlBufferFree(buf);
+/**
+ * xmlDocDumpFormatMemory:
+ * @cur: the document
+ * @mem: OUT: the memory pointer
+ * @size: OUT: the memory lenght
+ * @format: should formatting spaces been added
+ *
+ *
+ * Dump an XML document in memory and return the xmlChar * and it's size.
+ * It's up to the caller to free the memory.
+ */
+void
+xmlDocDumpFormatMemory(xmlDocPtr cur, xmlChar**mem, int *size, int format) {
+ xmlDocDumpFormatMemoryEnc(cur, mem, size, NULL, format);
}
/**
@@ -5618,79 +5676,8 @@
void
xmlDocDumpMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr,
int * doc_txt_len, const char * txt_encoding) {
- int dummy = 0;
-
- xmlCharEncoding doc_charset;
- xmlOutputBufferPtr out_buff = NULL;
- xmlCharEncodingHandlerPtr conv_hdlr = NULL;
-
- if (doc_txt_len == NULL) {
- doc_txt_len = &dummy; /* Continue, caller just won't get length */
- }
-
- if (doc_txt_ptr == NULL) {
- *doc_txt_len = 0;
- xmlGenericError(xmlGenericErrorContext,
- "xmlDocDumpMemoryEnc: Null return buffer pointer.");
- return;
- }
-
- *doc_txt_ptr = NULL;
- *doc_txt_len = 0;
-
- if (out_doc == NULL) {
- /* No document, no output */
- xmlGenericError(xmlGenericErrorContext,
- "xmlDocDumpMemoryEnc: Null DOM tree document pointer.\n");
- return;
- }
-
- /*
- * Validate the encoding value, if provided.
- * This logic is copied from xmlSaveFileEnc.
- */
-
- if (txt_encoding != NULL) {
- doc_charset = xmlParseCharEncoding(txt_encoding);
-
- if (out_doc->charset != XML_CHAR_ENCODING_UTF8) {
- xmlGenericError(xmlGenericErrorContext,
- "xmlDocDumpMemoryEnc: Source document not in UTF8\n");
- return;
-
- } else if (doc_charset != XML_CHAR_ENCODING_UTF8) {
- conv_hdlr = xmlFindCharEncodingHandler(txt_encoding);
- if ( conv_hdlr == NULL ) {
- xmlGenericError(xmlGenericErrorContext,
- "%s: %s %s '%s'\n",
- "xmlDocDumpMemoryEnc",
- "Failed to identify encoding handler for",
- "character set",
- txt_encoding);
- return;
- }
- }
- }
-
- if ((out_buff = xmlAllocOutputBuffer(conv_hdlr)) == NULL ) {
- xmlGenericError(xmlGenericErrorContext,
- "xmlDocDumpMemoryEnc: Failed to allocate output buffer.\n");
- return;
- }
-
- xmlDocContentDumpOutput(out_buff, out_doc, txt_encoding);
- *doc_txt_len = out_buff->buffer->use;
- *doc_txt_ptr = xmlStrndup(out_buff->buffer->content, *doc_txt_len);
- (void)xmlOutputBufferClose(out_buff);
-
- if ((*doc_txt_ptr == NULL) && (*doc_txt_len > 0)) {
- *doc_txt_len = 0;
- xmlGenericError(xmlGenericErrorContext,
- "xmlDocDumpMemoryEnc: %s\n",
- "Failed to allocate memory for document text representation.");
- }
-
- return;
+ xmlDocDumpFormatMemoryEnc(out_doc, doc_txt_ptr, doc_txt_len,
+ txt_encoding, 1);
}
/**
@@ -5792,7 +5779,7 @@
}
buf = xmlOutputBufferCreateFile(f, handler);
if (buf == NULL) return(-1);
- xmlDocContentDumpOutput(buf, cur, NULL);
+ xmlDocContentDumpOutput(buf, cur, NULL, 1);
ret = xmlOutputBufferClose(buf);
return(ret);
@@ -5813,7 +5800,7 @@
int ret;
if (buf == NULL) return(0);
- xmlDocContentDumpOutput(buf, cur, encoding);
+ xmlDocContentDumpOutput(buf, cur, encoding, 1);
ret = xmlOutputBufferClose(buf);
return(ret);
}
@@ -5857,7 +5844,7 @@
buf = xmlOutputBufferCreateFilename(filename, handler, 0);
if (buf == NULL) return(0);
- xmlDocContentDumpOutput(buf, cur, encoding);
+ xmlDocContentDumpOutput(buf, cur, encoding, 1);
ret = xmlOutputBufferClose(buf);
return(ret);
@@ -5912,7 +5899,7 @@
buf = xmlOutputBufferCreateFilename(filename, handler, cur->compression);
if (buf == NULL) return(0);
- xmlDocContentDumpOutput(buf, cur, NULL);
+ xmlDocContentDumpOutput(buf, cur, NULL, 1);
ret = xmlOutputBufferClose(buf);
return(ret);
diff --git a/tree.h b/tree.h
index 7b19d09..2dc3242 100644
--- a/tree.h
+++ b/tree.h
@@ -634,6 +634,10 @@
/*
* Saving
*/
+void xmlDocDumpFormatMemory (xmlDocPtr cur,
+ xmlChar**mem,
+ int *size,
+ int format);
void xmlDocDumpMemory (xmlDocPtr cur,
xmlChar**mem,
int *size);
@@ -641,6 +645,11 @@
xmlChar **doc_txt_ptr,
int * doc_txt_len,
const char *txt_encoding);
+void xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc,
+ xmlChar **doc_txt_ptr,
+ int * doc_txt_len,
+ const char *txt_encoding,
+ int format);
int xmlDocDump (FILE *f,
xmlDocPtr cur);
void xmlElemDump (FILE *f,
diff --git a/xmlIO.c b/xmlIO.c
index ca8413d..3a8fcf2 100644
--- a/xmlIO.c
+++ b/xmlIO.c
@@ -1413,6 +1413,9 @@
if (nbchars < MINLEN)
return(0);
+ if (!out->writecallback)
+ return(nbchars);
+
/*
* second write the stuff to the I/O channel
*/
@@ -1477,7 +1480,7 @@
*/
int
xmlOutputBufferFlush(xmlOutputBufferPtr out) {
- int nbchars = 0, ret;
+ int nbchars = 0, ret = 0;
/*
* first handle encoding stuff.
@@ -1497,12 +1500,13 @@
/*
* second flush the stuff to the I/O channel
*/
- if ((out->conv != NULL) && (out->encoder != NULL)) {
+ if ((out->conv != NULL) && (out->encoder != NULL) &&
+ (out->writecallback != NULL)) {
ret = out->writecallback(out->context,
(const char *)out->conv->content, out->conv->use);
if (ret >= 0)
xmlBufferShrink(out->conv, ret);
- } else {
+ } else if (out->writecallback != NULL) {
ret = out->writecallback(out->context,
(const char *)out->buffer->content, out->buffer->use);
if (ret >= 0)
diff --git a/xmllint.c b/xmllint.c
index 099084b..3dd413a 100644
--- a/xmllint.c
+++ b/xmllint.c
@@ -565,15 +565,31 @@
#ifdef LIBXML_DEBUG_ENABLED
if (!debug) {
#endif
- if (compress)
+ if (memory) {
+ xmlChar *result;
+ int len;
+
+ if (encoding != NULL) {
+ xmlDocDumpMemoryEnc(doc, &result, &len, encoding);
+ } else {
+ xmlDocDumpMemory(doc, &result, &len);
+ }
+ if (result == NULL) {
+ fprintf(stderr, "Failed to save\n");
+ } else {
+ write(1, result, len);
+ xmlFree(result);
+ }
+ } else if (compress)
xmlSaveFile("-", doc);
else if (encoding != NULL)
xmlSaveFileEnc("-", doc, encoding);
else
xmlDocDump(stdout, doc);
#ifdef LIBXML_DEBUG_ENABLED
- } else
+ } else {
xmlDebugDumpDocument(stdout, doc);
+ }
#endif
}
diff --git a/xpath.c b/xpath.c
index 62fa15c..d667bbb 100644
--- a/xpath.c
+++ b/xpath.c
@@ -444,7 +444,8 @@
"Memory allocation error",
"Syntax error",
"Resource error",
- "Sub resource error"
+ "Sub resource error",
+ "Undefined namespace prefix"
};
/**
@@ -1064,6 +1065,70 @@
ctxt->varHash = NULL;
}
+/**
+ * xmlXPathRegisterNs:
+ * @ctxt: the XPath context
+ * @prefix: the namespace prefix
+ * @ns_uri: the namespace name
+ *
+ * Register a new namespace. If @ns_uri is NULL it unregisters
+ * the namespace
+ *
+ * Returns 0 in case of success, -1 in case of error
+ */
+int
+xmlXPathRegisterNs(xmlXPathContextPtr ctxt, const xmlChar *prefix,
+ const xmlChar *ns_uri) {
+ if (ctxt == NULL)
+ return(-1);
+ if (prefix == NULL)
+ return(-1);
+
+ if (ctxt->nsHash == NULL)
+ ctxt->nsHash = xmlHashCreate(10);
+ if (ctxt->nsHash == NULL)
+ return(-1);
+ return(xmlHashUpdateEntry(ctxt->nsHash, prefix, (void *) ns_uri,
+ (xmlHashDeallocator)xmlFree));
+}
+
+/**
+ * xmlXPathNsLookup:
+ * @ctxt: the XPath context
+ * @prefix: the namespace prefix value
+ *
+ * Search in the namespace declaration array of the context for the given
+ * namespace name associated to the given prefix
+ *
+ * Returns the value or NULL if not found
+ */
+const xmlChar *
+xmlXPathNsLookup(xmlXPathContextPtr ctxt, const xmlChar *prefix) {
+ if (ctxt == NULL)
+ return(NULL);
+ if (prefix == NULL)
+ return(NULL);
+ if (ctxt->nsHash == NULL)
+ return(NULL);
+
+ return((const xmlChar *) xmlHashLookup(ctxt->nsHash, prefix));
+}
+
+/**
+ * xmlXPathRegisteredVariablesCleanup:
+ * @ctxt: the XPath context
+ *
+ * Cleanup the XPath context data associated to registered variables
+ */
+void
+xmlXPathRegisteredNsCleanup(xmlXPathContextPtr ctxt) {
+ if (ctxt == NULL)
+ return;
+
+ xmlHashFree(ctxt->nsHash, NULL);
+ ctxt->nsHash = NULL;
+}
+
/************************************************************************
* *
* Routines to handle Values *
@@ -1285,9 +1350,8 @@
ret->max_axis = 0;
ret->axis = NULL;
- ret->namespaces = NULL;
+ ret->nsHash = NULL;
ret->user = NULL;
- ret->nsNr = 0;
ret->contextSize = -1;
ret->proximityPosition = -1;
@@ -1305,9 +1369,7 @@
*/
void
xmlXPathFreeContext(xmlXPathContextPtr ctxt) {
- if (ctxt->namespaces != NULL)
- xmlFree(ctxt->namespaces);
-
+ xmlXPathRegisteredNsCleanup(ctxt);
xmlXPathRegisteredFuncsCleanup(ctxt);
xmlXPathRegisteredVariablesCleanup(ctxt);
#ifdef DEBUG
@@ -2712,10 +2774,19 @@
if ((cur->type == XML_ELEMENT_NODE) ||
(cur->type == XML_DOCUMENT_NODE) ||
(cur->type == XML_HTML_DOCUMENT_NODE)) {
+ if (prefix == NULL) {
#ifdef DEBUG_STEP
- n++;
+ n++;
#endif
- xmlXPathNodeSetAdd(ret, cur);
+ xmlXPathNodeSetAdd(ret, cur);
+ } else if ((cur->ns != NULL) &&
+ (xmlStrEqual(prefix,
+ cur->ns->href))) {
+#ifdef DEBUG_STEP
+ n++;
+#endif
+ xmlXPathNodeSetAdd(ret, cur);
+ }
}
}
break;
@@ -2726,14 +2797,25 @@
case NODE_TEST_NAME:
switch (cur->type) {
case XML_ELEMENT_NODE:
- if (xmlStrEqual(name, cur->name) &&
- (((prefix == NULL) ||
- ((cur->ns != NULL) &&
- (xmlStrEqual(prefix, cur->ns->href)))))) {
+ if (xmlStrEqual(name, cur->name)) {
+ if (prefix == NULL) {
+ if ((cur->ns == NULL) ||
+ (cur->ns->prefix == NULL)) {
#ifdef DEBUG_STEP
- n++;
+ n++;
#endif
- xmlXPathNodeSetAdd(ret, cur);
+ xmlXPathNodeSetAdd(ret, cur);
+ }
+ } else {
+ if ((cur->ns != NULL) &&
+ (xmlStrEqual(prefix,
+ cur->ns->href))) {
+#ifdef DEBUG_STEP
+ n++;
+#endif
+ xmlXPathNodeSetAdd(ret, cur);
+ }
+ }
}
break;
case XML_ATTRIBUTE_NODE: {
@@ -5106,7 +5188,7 @@
*/
xmlChar *
xmlXPathEvalNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test,
- xmlXPathTypeVal *type, xmlChar **prefix, xmlChar *name) {
+ xmlXPathTypeVal *type, const xmlChar **prefix, xmlChar *name) {
int blanks;
if ((test == NULL) || (type == NULL) || (prefix == NULL)) {
@@ -5148,8 +5230,11 @@
*type = NODE_TYPE_PI;
else if (xmlStrEqual(name, BAD_CAST "text"))
*type = NODE_TYPE_TEXT;
- else
+ else {
+ if (name != NULL)
+ xmlFree(name);
XP_ERROR0(XPATH_EXPR_ERROR);
+ }
*test = NODE_TEST_TYPE;
@@ -5172,8 +5257,11 @@
xmlXPathFreeObject(cur);
SKIP_BLANKS;
}
- if (CUR != ')')
+ if (CUR != ')') {
+ if (name != NULL)
+ xmlFree(name);
XP_ERROR0(XPATH_UNCLOSED_ERROR);
+ }
NEXT;
return(name);
}
@@ -5181,7 +5269,15 @@
if ((!blanks) && (CUR == ':')) {
NEXT;
- *prefix = name;
+ /*
+ * get the namespace name for this prefix
+ */
+ *prefix = xmlXPathNsLookup(ctxt->context, name);
+ if (name != NULL)
+ xmlFree(name);
+ if (*prefix == NULL) {
+ XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
+ }
if (CUR == '*') {
/*
@@ -5347,7 +5443,7 @@
SKIP_BLANKS;
} else {
xmlChar *name = NULL;
- xmlChar *prefix = NULL;
+ const xmlChar *prefix = NULL;
xmlXPathTestVal test;
xmlXPathAxisVal axis;
xmlXPathTypeVal type;
@@ -5420,8 +5516,6 @@
#endif
if (name != NULL)
xmlFree(name);
- if (prefix != NULL)
- xmlFree(prefix);
eval_predicates:
SKIP_BLANKS;
diff --git a/xpath.h b/xpath.h
index 553b3fc..6f820d4 100644
--- a/xpath.h
+++ b/xpath.h
@@ -47,7 +47,8 @@
XPATH_MEMORY_ERROR,
XPTR_SYNTAX_ERROR,
XPTR_RESOURCE_ERROR,
- XPTR_SUB_RESOURCE_ERROR
+ XPTR_SUB_RESOURCE_ERROR,
+ XPATH_UNDEF_PREFIX_ERROR
} xmlXPathError;
/*
@@ -171,6 +172,8 @@
* - a set of variable bindings
* - a function library
* - the set of namespace declarations in scope for the expression
+ * Following the switch to hash tables, this need to be trimmed up at
+ * the next binary incompatible release.
*/
struct _xmlXPathContext {
@@ -193,10 +196,10 @@
int max_axis; /* max number of axis */
xmlXPathAxisPtr axis; /* Array of defined axis */
- /* Namespace traversal should be implemented with user */
- xmlNsPtr *namespaces; /* The namespaces lookup */
- int nsNr; /* the current Namespace index */
- void *user; /* user defined extra info */
+ /* the namespace nodes of the context node */
+ xmlNsPtr *namespaces; /* Array of namespaces */
+ int nsNr; /* number of namespace in scope */
+ void *user; /* function to free */
/* extra variables */
int contextSize; /* the context size */
@@ -206,6 +209,9 @@
int xptr; /* it this an XPointer context */
xmlNodePtr here; /* for here() */
xmlNodePtr origin; /* for origin() */
+
+ /* the set of namespace declarations in scope for the expression */
+ xmlHashTablePtr nsHash; /* The namespaces hash table */
};
/*
diff --git a/xpathInternals.h b/xpathInternals.h
index a18e453..6967c90 100644
--- a/xpathInternals.h
+++ b/xpathInternals.h
@@ -68,6 +68,13 @@
/**
* Extending a context
*/
+int xmlXPathRegisterNs (xmlXPathContextPtr ctxt,
+ const xmlChar *prefix,
+ const xmlChar *ns_uri);
+const xmlChar * xmlXPathNsLookup (xmlXPathContextPtr ctxt,
+ const xmlChar *ns_uri);
+void xmlXPathRegisteredNsCleanup (xmlXPathContextPtr ctxt);
+
int xmlXPathRegisterFunc (xmlXPathContextPtr ctxt,
const xmlChar *name,
xmlXPathFunction f);
@@ -121,6 +128,7 @@
void xmlXPathRoot (xmlXPathParserContextPtr ctxt);
void xmlXPathEvalExpr (xmlXPathParserContextPtr ctxt);
xmlChar * xmlXPathParseName (xmlXPathParserContextPtr ctxt);
+xmlChar * xmlXPathParseNCName (xmlXPathParserContextPtr ctxt);
/*
* Debug
diff --git a/xpointer.c b/xpointer.c
index 376421f..1b2efe7 100644
--- a/xpointer.c
+++ b/xpointer.c
@@ -28,6 +28,7 @@
#include <libxml/xpointer.h>
#include <libxml/xmlmemory.h>
#include <libxml/parserInternals.h>
+#include <libxml/uri.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#ifdef LIBXML_DEBUG_ENABLED
@@ -37,6 +38,9 @@
#ifdef LIBXML_XPTR_ENABLED
+/* Add support of the xmlns() xpointer scheme to initialize the namespaces */
+#define XPTR_XMLNS_SCHEME
+
/* #define DEBUG_RANGES */
#define TODO \
@@ -1038,6 +1042,50 @@
xmlXPathRoot(ctxt);
xmlXPathEvalExpr(ctxt);
CUR_PTR=left;
+#ifdef XPTR_XMLNS_SCHEME
+ } else if (xmlStrEqual(name, (xmlChar *) "xmlns")) {
+ const xmlChar *left = CUR_PTR;
+ xmlChar *prefix;
+ xmlChar *URI;
+ xmlURIPtr value;
+
+ CUR_PTR = buffer;
+ prefix = xmlXPathParseNCName(ctxt);
+ if (prefix == NULL) {
+ xmlFree(buffer);
+ xmlFree(name);
+ XP_ERROR(XPTR_SYNTAX_ERROR);
+ }
+ SKIP_BLANKS;
+ if (CUR != '=') {
+ xmlFree(prefix);
+ xmlFree(buffer);
+ xmlFree(name);
+ XP_ERROR(XPTR_SYNTAX_ERROR);
+ }
+ NEXT;
+ SKIP_BLANKS;
+ /* @@ check escaping in the XPointer WD */
+
+ value = xmlParseURI((const char *)ctxt->cur);
+ if (value == NULL) {
+ xmlFree(prefix);
+ xmlFree(buffer);
+ xmlFree(name);
+ XP_ERROR(XPTR_SYNTAX_ERROR);
+ }
+ URI = xmlSaveUri(value);
+ xmlFreeURI(value);
+ if (URI == NULL) {
+ xmlFree(prefix);
+ xmlFree(buffer);
+ xmlFree(name);
+ XP_ERROR(XPATH_MEMORY_ERROR);
+ }
+
+ xmlXPathRegisterNs(ctxt->context, prefix, URI);
+ CUR_PTR = left;
+#endif /* XPTR_XMLNS_SCHEME */
} else {
xmlGenericError(xmlGenericErrorContext,
"unsupported scheme '%s'\n", name);