From 198c1bfc1cd2cc031410e4be4e5faebed45c557c Mon Sep 17 00:00:00 2001 From: Daniel Veillard Date: Mon, 20 Oct 2003 17:07:41 +0000 Subject: [PATCH] removing xmldwalk module since it got merged with the xmlreader. cleanup * Makefile.am configure.in xmldwalk.c xmlreader.c include/libxml/Makefile.am include/libxml/xmldwalk.h include/libxml/xmlversion.h.in: removing xmldwalk module since it got merged with the xmlreader. * parser.c: cleanup * win32/libxml2.def.src python/libxml2class.txt doc/libxml2-api.xml: rebuilt the API * python/tests/Makefile.am python/tests/reader7.py python/tests/walker.py: adding regression testing for the new xmlreader APIs, new APIs for reader creation, including makeing reader "walker" operating on preparsed document trees. Daniel --- ChangeLog | 14 + Makefile.am | 4 +- configure.in | 17 - doc/libxml2-api.xml | 53 +- include/libxml/Makefile.am | 1 - include/libxml/xmldwalk.h | 116 ---- include/libxml/xmlreader.h | 42 +- include/libxml/xmlversion.h.in | 9 - parser.c | 5 +- python/generator.py | 22 + python/libxml2class.txt | 22 +- python/tests/Makefile.am | 2 + python/tests/reader7.py | 102 +++ python/tests/walker.py | 145 ++++ win32/libxml2.def.src | 32 + xmldwalk.c | 1197 -------------------------------- xmllint.c | 15 +- xmlreader.c | 564 +++++++++++++-- 18 files changed, 903 insertions(+), 1459 deletions(-) delete mode 100644 include/libxml/xmldwalk.h create mode 100755 python/tests/reader7.py create mode 100755 python/tests/walker.py delete mode 100644 xmldwalk.c diff --git a/ChangeLog b/ChangeLog index 0f7be2c8..5c4e8de3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +Mon Oct 20 19:02:53 CEST 2003 Daniel Veillard + + * Makefile.am configure.in xmldwalk.c xmlreader.c + include/libxml/Makefile.am include/libxml/xmldwalk.h + include/libxml/xmlversion.h.in: removing xmldwalk module + since it got merged with the xmlreader. + * parser.c: cleanup + * win32/libxml2.def.src python/libxml2class.txt doc/libxml2-api.xml: + rebuilt the API + * python/tests/Makefile.am python/tests/reader7.py + python/tests/walker.py: adding regression testing for the + new xmlreader APIs, new APIs for reader creation, including + makeing reader "walker" operating on preparsed document trees. + Sun Oct 20 22:37:03 HKT 2003 William Brack * entities.c, valid.c: fixed problem reported on the mailing diff --git a/Makefile.am b/Makefile.am index 02640dea..5d45ceac 100644 --- a/Makefile.am +++ b/Makefile.am @@ -27,7 +27,7 @@ libxml2_la_SOURCES = SAX.c entities.c encoding.c error.c parserInternals.c \ catalog.c globals.c threads.c c14n.c \ xmlregexp.c xmlschemas.c xmlschemastypes.c xmlunicode.c \ triostr.c trio.c xmlreader.c relaxng.c dict.c SAX2.c \ - legacy.c xmldwalk.c chvalid.c + legacy.c chvalid.c else libxml2_la_SOURCES = SAX.c entities.c encoding.c error.c parserInternals.c \ parser.c tree.c hash.c list.c xmlIO.c xmlmemory.c uri.c \ @@ -36,7 +36,7 @@ libxml2_la_SOURCES = SAX.c entities.c encoding.c error.c parserInternals.c \ catalog.c globals.c threads.c c14n.c \ xmlregexp.c xmlschemas.c xmlschemastypes.c xmlunicode.c \ xmlreader.c relaxng.c dict.c SAX2.c \ - legacy.c xmldwalk.c chvalid.c + legacy.c chvalid.c endif DEPS = $(top_builddir)/libxml2.la diff --git a/configure.in b/configure.in index 6f23db60..f53ebf68 100644 --- a/configure.in +++ b/configure.in @@ -639,23 +639,6 @@ fi AC_SUBST(WITH_SAX1) AC_SUBST(TEST_SAX) -AC_ARG_WITH(walker, -[ --with-walker add the xmlDocWalker interface (on)]) -if test "$with_minimum" = "yes" -a "$with_walker" = "" -then - with_walker=no -fi -if test "$with_walker" = "no" ; then - echo Disabling the xmlDocWalker interface - WITH_WALKER=0 - TEST_WALKER= -else - WITH_WALKER=1 - TEST_WALKER=WALKERtests -fi -AC_SUBST(WITH_WALKER) -AC_SUBST(TEST_WALKER) - AC_ARG_WITH(push, [ --with-push add the PUSH parser interfaces (on)]) if test "$with_minimum" = "yes" -a "$with_push" = "" diff --git a/doc/libxml2-api.xml b/doc/libxml2-api.xml index 7234bbc4..b4c47d0c 100644 --- a/doc/libxml2-api.xml +++ b/doc/libxml2-api.xml @@ -1438,7 +1438,9 @@ + + @@ -1449,6 +1451,7 @@ + @@ -1480,6 +1483,7 @@ + @@ -7283,9 +7287,9 @@ actually an xmlCharEncoding'/> - - - + The base URI of the node. + + Hacking interface allowing to get the xmlDocPtr correponding to the current document being accessed by the xmlDocWalker. @@ -9900,7 +9904,7 @@ actually an xmlCharEncoding'/> - Create an xmltextReader for an XML in-memory document. + Create an xmltextReader for an XML in-memory document. The parsing flags @options are a combination of xmlParserOption(s). @@ -9908,7 +9912,7 @@ actually an xmlCharEncoding'/> - Create an xmltextReader for an XML from a file descriptor. + Create an xmltextReader for an XML from a file descriptor. The parsing flags @options are a combination of xmlParserOption(s). @@ -9916,14 +9920,14 @@ actually an xmlCharEncoding'/> - parse an XML file from the filesystem or the network. + parse an XML file from the filesystem or the network. The parsing flags @options are a combination of xmlParserOption(s). - Create an xmltextReader for an XML document from I/O functions and source. + Create an xmltextReader for an XML document from I/O functions and source. The parsing flags @options are a combination of xmlParserOption(s). @@ -9933,7 +9937,7 @@ actually an xmlCharEncoding'/> - Create an xmltextReader for an XML in-memory document. + Create an xmltextReader for an XML in-memory document. The parsing flags @options are a combination of xmlParserOption(s). @@ -9942,7 +9946,7 @@ actually an xmlCharEncoding'/> - Setup an xmltextReader to parse an XML in-memory document. This reuses the existing @reader xmlTextReader. + Setup an xmltextReader to parse an XML in-memory document. The parsing flags @options are a combination of xmlParserOption(s). This reuses the existing @reader xmlTextReader. @@ -9951,7 +9955,7 @@ actually an xmlCharEncoding'/> - Setup an xmltextReader to parse an XML from a file descriptor. This reuses the existing @reader xmlTextReader. + Setup an xmltextReader to parse an XML from a file descriptor. The parsing flags @options are a combination of xmlParserOption(s). This reuses the existing @reader xmlTextReader. @@ -9960,7 +9964,7 @@ actually an xmlCharEncoding'/> - parse an XML file from the filesystem or the network. This reuses the existing @reader xmlTextReader. + parse an XML file from the filesystem or the network. The parsing flags @options are a combination of xmlParserOption(s). This reuses the existing @reader xmlTextReader. @@ -9968,7 +9972,7 @@ actually an xmlCharEncoding'/> - Setup an xmltextReader to parse an XML document from I/O functions and source. This reuses the existing @reader xmlTextReader. + Setup an xmltextReader to parse an XML document from I/O functions and source. The parsing flags @options are a combination of xmlParserOption(s). This reuses the existing @reader xmlTextReader. @@ -9979,7 +9983,7 @@ actually an xmlCharEncoding'/> - Setup an xmltextReader to parse an XML in-memory document. This reuses the existing @reader xmlTextReader. + Setup an xmltextReader to parse an XML in-memory document. The parsing flags @options are a combination of xmlParserOption(s). This reuses the existing @reader xmlTextReader. @@ -9988,6 +9992,17 @@ actually an xmlCharEncoding'/> + + Setup an xmltextReader to parse a preparsed XML document. This reuses the existing @reader xmlTextReader. + + + + + + Create an xmltextReader for a preparsed document. + + + Signature for a realloc() implementation. @@ -11335,6 +11350,11 @@ actually an xmlCharEncoding'/> + + Provides the text value of the node if present + + + The xml:lang scope within which the node resides. @@ -11500,6 +11520,11 @@ actually an xmlCharEncoding'/> + + + + + Get the node type of the current node Reference: http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html @@ -11583,7 +11608,7 @@ actually an xmlCharEncoding'/> Provides the text value of the node if present - + diff --git a/include/libxml/Makefile.am b/include/libxml/Makefile.am index 1bf338ce..9b754e83 100644 --- a/include/libxml/Makefile.am +++ b/include/libxml/Makefile.am @@ -43,7 +43,6 @@ xmlinc_HEADERS = \ dict.h \ SAX2.h \ xmlexports.h \ - xmldwalk.h \ chvalid.h install-exec-hook: diff --git a/include/libxml/xmldwalk.h b/include/libxml/xmldwalk.h deleted file mode 100644 index f0bd536e..00000000 --- a/include/libxml/xmldwalk.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * xmldwalk.h : Interfaces, constants and types of the document traversing API.for XML - * - * this is heavily based upon the xmlTextReader streaming node API - * of libxml2 by Daniel Veillard (daniel@veillard.com). In fact I - * just copied and modified xmlreader.h - * - * So for license and disclaimer see the license and disclaimer of - * libxml2. - * - * alfred@mickautsch.de - */ - -#ifndef __XML_XMLDWALK_H__ -#define __XML_XMLDWALK_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - XML_DWALK_NONE = 0, - XML_DWALK_START, - XML_DWALK_BACKTRACK, - XML_DWALK_END -} xmlDocWalkerState; - -typedef struct _xmlDocWalker xmlDocWalker; -typedef xmlDocWalker *xmlDocWalkerPtr; - -/* - * Constructor & Destructor - */ -XMLPUBFUN xmlDocWalkerPtr XMLCALL - xmlNewDocWalker (xmlDocPtr doc); -XMLPUBFUN void XMLCALL - xmlFreeDocWalker (xmlDocWalkerPtr iter); - -/* - * Iterator Functions - */ -XMLPUBFUN int XMLCALL - xmlDocWalkerRewind (xmlDocWalkerPtr iter); -XMLPUBFUN int XMLCALL - xmlDocWalkerStep (xmlDocWalkerPtr iter); - -XMLPUBFUN int XMLCALL - xmlDocWalkerAttributeCount (xmlDocWalkerPtr iter); -XMLPUBFUN int XMLCALL - xmlDocWalkerDepth (xmlDocWalkerPtr iter); -XMLPUBFUN int XMLCALL - xmlDocWalkerHasAttributes (xmlDocWalkerPtr iter); -XMLPUBFUN int XMLCALL - xmlDocWalkerHasValue (xmlDocWalkerPtr iter); -XMLPUBFUN int XMLCALL - xmlDocWalkerIsEmptyElement (xmlDocWalkerPtr iter); -XMLPUBFUN xmlChar * XMLCALL - xmlDocWalkerLocalName (xmlDocWalkerPtr iter); -XMLPUBFUN xmlChar * XMLCALL - xmlDocWalkerName (xmlDocWalkerPtr iter); -XMLPUBFUN int XMLCALL - xmlDocWalkerNodeType (xmlDocWalkerPtr iter); -XMLPUBFUN xmlChar * XMLCALL - xmlDocWalkerPrefix (xmlDocWalkerPtr iter); -XMLPUBFUN xmlChar * XMLCALL - xmlDocWalkerNamespaceUri (xmlDocWalkerPtr iter); -XMLPUBFUN xmlChar * XMLCALL - xmlDocWalkerBaseUri (xmlDocWalkerPtr iter); -XMLPUBFUN xmlChar * XMLCALL - xmlDocWalkerValue (xmlDocWalkerPtr iter); - -XMLPUBFUN xmlChar * XMLCALL - xmlDocWalkerGetAttributeNo (xmlDocWalkerPtr iter, - int no); -XMLPUBFUN xmlChar * XMLCALL - xmlDocWalkerGetAttribute (xmlDocWalkerPtr iter, - const xmlChar *name); -XMLPUBFUN xmlChar * XMLCALL - xmlDocWalkerGetAttributeNs (xmlDocWalkerPtr iter, - const xmlChar *localName, - const xmlChar *namespaceURI); -XMLPUBFUN xmlChar * XMLCALL - xmlDocWalkerLookupNamespace (xmlDocWalkerPtr iter, - const xmlChar *prefix); -XMLPUBFUN int XMLCALL - xmlDocWalkerMoveToAttributeNo (xmlDocWalkerPtr iter, - int no); -XMLPUBFUN int XMLCALL - xmlDocWalkerMoveToAttribute (xmlDocWalkerPtr iter, - const xmlChar *name); -XMLPUBFUN int XMLCALL - xmlDocWalkerMoveToAttributeNs (xmlDocWalkerPtr iter, - const xmlChar *localName, - const xmlChar *namespaceURI); -XMLPUBFUN int XMLCALL - xmlDocWalkerMoveToFirstAttribute(xmlDocWalkerPtr iter); -XMLPUBFUN int XMLCALL - xmlDocWalkerMoveToNextAttribute (xmlDocWalkerPtr iter); -XMLPUBFUN int XMLCALL - xmlDocWalkerMoveToElement (xmlDocWalkerPtr iter); - -xmlNodePtr - xmlDocWalkerCurrentNode (xmlDocWalkerPtr iter); -xmlDocPtr - xmlDocWalkerCurrentDoc (xmlDocWalkerPtr iter); -XMLPUBFUN int XMLCALL - xmlDocWalkerNext (xmlDocWalkerPtr iter); - -#ifdef __cplusplus -} -#endif - -#endif /* __XML_XMLDWALK_H__ */ diff --git a/include/libxml/xmlreader.h b/include/libxml/xmlreader.h index bbff65d6..d273681f 100644 --- a/include/libxml/xmlreader.h +++ b/include/libxml/xmlreader.h @@ -104,20 +104,6 @@ XMLPUBFUN int XMLCALL xmlTextReaderQuoteChar (xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderReadState (xmlTextReaderPtr reader); -XMLPUBFUN xmlChar * XMLCALL - xmlTextReaderBaseUri (xmlTextReaderPtr reader); -XMLPUBFUN xmlChar * XMLCALL - xmlTextReaderLocalName (xmlTextReaderPtr reader); -XMLPUBFUN xmlChar * XMLCALL - xmlTextReaderName (xmlTextReaderPtr reader); -XMLPUBFUN xmlChar * XMLCALL - xmlTextReaderNamespaceUri(xmlTextReaderPtr reader); -XMLPUBFUN xmlChar * XMLCALL - xmlTextReaderPrefix (xmlTextReaderPtr reader); -XMLPUBFUN xmlChar * XMLCALL - xmlTextReaderXmlLang (xmlTextReaderPtr reader); -XMLPUBFUN xmlChar * XMLCALL - xmlTextReaderValue (xmlTextReaderPtr reader); XMLPUBFUN const xmlChar * XMLCALL xmlTextReaderConstBaseUri (xmlTextReaderPtr reader); @@ -134,6 +120,27 @@ XMLPUBFUN const xmlChar * XMLCALL XMLPUBFUN const xmlChar * XMLCALL xmlTextReaderConstString (xmlTextReaderPtr reader, const xmlChar *str); +XMLPUBFUN const xmlChar * XMLCALL + xmlTextReaderConstValue (xmlTextReaderPtr reader); + +/* + * use the Const version of the routine for + * better performance and simpler code + */ +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderBaseUri (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderLocalName (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderName (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderNamespaceUri(xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderPrefix (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderXmlLang (xmlTextReaderPtr reader); +XMLPUBFUN xmlChar * XMLCALL + xmlTextReaderValue (xmlTextReaderPtr reader); /* * Methods of the XmlTextReader @@ -194,6 +201,8 @@ XMLPUBFUN xmlNodePtr XMLCALL xmlTextReaderExpand (xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderNext (xmlTextReaderPtr reader); +XMLPUBFUN int XMLCALL + xmlTextReaderNextSibling (xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderIsValid (xmlTextReaderPtr reader); #ifdef LIBXML_SCHEMAS_ENABLED @@ -208,6 +217,8 @@ XMLPUBFUN int XMLCALL /* * New more complete APIs for simpler creation and reuse of readers */ +XMLPUBFUN xmlTextReaderPtr XMLCALL + xmlReaderWalker (xmlDocPtr doc); XMLPUBFUN xmlTextReaderPtr XMLCALL xmlReaderForDoc (const xmlChar * cur, const char *URL, @@ -236,6 +247,9 @@ XMLPUBFUN xmlTextReaderPtr XMLCALL const char *encoding, int options); +XMLPUBFUN int XMLCALL + xmlReaderNewWalker (xmlTextReaderPtr reader, + xmlDocPtr doc); XMLPUBFUN int XMLCALL xmlReaderNewDoc (xmlTextReaderPtr reader, const xmlChar * cur, diff --git a/include/libxml/xmlversion.h.in b/include/libxml/xmlversion.h.in index 7b87a439..e1cd4345 100644 --- a/include/libxml/xmlversion.h.in +++ b/include/libxml/xmlversion.h.in @@ -128,15 +128,6 @@ XMLPUBFUN void XMLCALL xmlCheckVersion(int version); #define LIBXML_SAX1_ENABLED #endif -/** - * LIBXML_WALKER_ENABLED: - * - * Whether the xmlDocWalker interface is configured in - */ -#if @WITH_WALKER@ -#define LIBXML_WALKER_ENABLED -#endif - /** * LIBXML_FTP_ENABLED: * diff --git a/parser.c b/parser.c index 31b50a52..9d6db090 100644 --- a/parser.c +++ b/parser.c @@ -9241,7 +9241,8 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { } #endif - if (ctxt->input->cur - ctxt->input->base > 4096) { + if ((ctxt->input != NULL) && + (ctxt->input->cur - ctxt->input->base > 4096)) { xmlSHRINK(ctxt); ctxt->checkIndex = 0; } @@ -9258,7 +9259,7 @@ xmlParseTryOrFinish(xmlParserCtxtPtr ctxt, int terminate) { while ((RAW == 0) && (ctxt->inputNr > 1)) xmlPopInput(ctxt); - if (ctxt->input ==NULL) break; + if (ctxt->input == NULL) break; if (ctxt->input->buf == NULL) avail = ctxt->input->length - (ctxt->input->cur - ctxt->input->base); diff --git a/python/generator.py b/python/generator.py index 732b8b93..79eeeb53 100755 --- a/python/generator.py +++ b/python/generator.py @@ -303,6 +303,24 @@ def skip_function(name): # the next function is defined in libxml.c if name == "xmlRelaxNGFreeValidCtxt": return 1 +# +# Those are skipped because the Const version is used of the bindings +# instead. +# + if name == "xmlTextReaderBaseUri": + return 1 + if name == "xmlTextReaderLocalName": + return 1 + if name == "xmlTextReaderName": + return 1 + if name == "xmlTextReaderNamespaceUri": + return 1 + if name == "xmlTextReaderPrefix": + return 1 + if name == "xmlTextReaderXmlLang": + return 1 + if name == "xmlTextReaderValue": + return 1 return 0 def print_function_wrapper(name, output, export, include): @@ -718,8 +736,12 @@ def nameFixup(name, classe, type, file): func = "regexp" + name[6:] elif name[0:20] == "xmlTextReaderLocator" and file == "xmlreader": func = name[20:] + elif name[0:18] == "xmlTextReaderConst" and file == "xmlreader": + func = name[18:] elif name[0:13] == "xmlTextReader" and file == "xmlreader": func = name[13:] + elif name[0:12] == "xmlReaderNew" and file == "xmlreader": + func = name[9:] elif name[0:11] == "xmlACatalog": func = name[11:] func = string.lower(func[0:1]) + func[1:] diff --git a/python/libxml2class.txt b/python/libxml2class.txt index 1f8b3e77..863982c9 100644 --- a/python/libxml2class.txt +++ b/python/libxml2class.txt @@ -584,6 +584,10 @@ Class xmlDoc(xmlNode) # functions from module xinclude xincludeProcess() + # functions from module xmlreader + NewWalker() + readerWalker() + # functions from module xpath xpathNewContext() xpathOrderDocElems() @@ -667,13 +671,6 @@ Class xmlTextReader(xmlTextReaderCore) AttributeCount() BaseUri() Close() - ConstBaseUri() - ConstLocalName() - ConstName() - ConstNamespaceUri() - ConstPrefix() - ConstString() - ConstXmlLang() CurrentDoc() CurrentNode() Depth() @@ -698,7 +695,13 @@ Class xmlTextReader(xmlTextReaderCore) MoveToNextAttribute() Name() NamespaceUri() + NewDoc() + NewFd() + NewFile() + NewMemory() + NewWalker() Next() + NextSibling() NodeType() Normalization() Prefix() @@ -713,12 +716,9 @@ Class xmlTextReader(xmlTextReaderCore) RelaxNGSetSchema() RelaxNGValidate() SetParserProp() + String() Value() XmlLang() - readerNewDoc() - readerNewFd() - readerNewFile() - readerNewMemory() Class xmlReg() # functions from module xmlregexp diff --git a/python/tests/Makefile.am b/python/tests/Makefile.am index d4e91dd5..3d5989d2 100644 --- a/python/tests/Makefile.am +++ b/python/tests/Makefile.am @@ -26,6 +26,8 @@ PYTESTS= \ reader4.py \ reader5.py \ reader6.py \ + reader7.py \ + walker.py \ ctxterror.py\ readererr.py\ relaxng.py \ diff --git a/python/tests/reader7.py b/python/tests/reader7.py new file mode 100755 index 00000000..35a426fd --- /dev/null +++ b/python/tests/reader7.py @@ -0,0 +1,102 @@ +#!/usr/bin/python -u +# +# this tests the entities substitutions with the XmlTextReader interface +# +import sys +import StringIO +import libxml2 + +# Memory debug specific +libxml2.debugMemory(1) + +result = "" +def processNode(reader): + global result + + result = result + "%d %d %s %d\n" % (reader.Depth(), reader.NodeType(), + reader.Name(), reader.IsEmptyElement()) + +# +# Parse a document testing the readerForxxx API +# +docstr=""" + +100 +""" +expect="""0 1 foo 0 +1 14 #text 0 +1 1 label 0 +2 3 #text 0 +1 15 label 0 +1 14 #text 0 +1 1 item 0 +2 3 #text 0 +1 15 item 0 +1 14 #text 0 +0 15 foo 0 +""" +result = "" + +reader = libxml2.readerForDoc(docstr, "test1", None, 0) +ret = reader.Read() +while ret == 1: + processNode(reader) + ret = reader.Read() + +if ret != 0: + print "Error parsing the document test1" + sys.exit(1) + +if result != expect: + print "Unexpected result for test1" + print result + sys.exit(1) + +# +# Reuse the reader for another document testing the ReaderNewxxx API +# +docstr=""" + +1000 +""" +expect="""0 1 foo 0 +1 14 #text 0 +1 1 label 0 +2 3 #text 0 +1 15 label 0 +1 14 #text 0 +1 1 item 0 +2 3 #text 0 +1 15 item 0 +1 14 #text 0 +0 15 foo 0 +""" +result = "" + +reader.NewDoc(docstr, "test2", None, 0) +ret = reader.Read() +while ret == 1: + processNode(reader) + ret = reader.Read() + +if ret != 0: + print "Error parsing the document test2" + sys.exit(1) + +if result != expect: + print "Unexpected result for test2" + print result + sys.exit(1) + +# +# cleanup +# +del reader + +# Memory debug specific +libxml2.cleanupParser() +if libxml2.debugMemory(1) == 0: + print "OK" +else: + print "Memory leak %d bytes" % (libxml2.debugMemory(1)) + libxml2.dumpMemory() diff --git a/python/tests/walker.py b/python/tests/walker.py new file mode 100755 index 00000000..3b5a62aa --- /dev/null +++ b/python/tests/walker.py @@ -0,0 +1,145 @@ +#!/usr/bin/python -u +# +# this tests the entities substitutions with the XmlTextReader interface +# +import sys +import StringIO +import libxml2 + +# Memory debug specific +libxml2.debugMemory(1) + +result = "" +def processNode(reader): + global result + + result = result + "%d %d %s %d\n" % (reader.Depth(), reader.NodeType(), + reader.Name(), reader.IsEmptyElement()) + +# +# Parse a document testing the readerForxxx API +# +docstr=""" + +100 +""" +expect="""0 1 foo 0 +1 14 #text 0 +1 1 label 0 +2 3 #text 0 +1 15 label 0 +1 14 #text 0 +1 1 item 0 +2 3 #text 0 +1 15 item 0 +1 14 #text 0 +0 15 foo 0 +""" +result = "" + +doc = libxml2.parseDoc(docstr) +reader = doc.readerWalker(); +ret = reader.Read() +while ret == 1: + processNode(reader) + ret = reader.Read() + +if ret != 0: + print "Error parsing the document test1" + sys.exit(1) + +if result != expect: + print "Unexpected result for test1" + print result + sys.exit(1) + +doc.freeDoc() + +# +# Reuse the reader for another document testing the ReaderNewWalker API +# +docstr=""" + +1000 +""" +expect="""0 1 foo 0 +1 14 #text 0 +1 1 label 0 +2 3 #text 0 +1 15 label 0 +1 14 #text 0 +1 1 item 0 +2 3 #text 0 +1 15 item 0 +1 14 #text 0 +0 15 foo 0 +""" +result = "" + +doc = libxml2.parseDoc(docstr) +reader.NewWalker(doc) + +ret = reader.Read() +while ret == 1: + processNode(reader) + ret = reader.Read() + +if ret != 0: + print "Error parsing the document test2" + sys.exit(1) + +if result != expect: + print "Unexpected result for test2" + print result + sys.exit(1) + +doc.freeDoc() + +# +# Reuse the reader for another document testing the ReaderNewxxx API +# +docstr=""" + +1000 +""" +expect="""0 1 foo 0 +1 14 #text 0 +1 1 label 0 +2 3 #text 0 +1 15 label 0 +1 14 #text 0 +1 1 item 0 +2 3 #text 0 +1 15 item 0 +1 14 #text 0 +0 15 foo 0 +""" +result = "" + +reader.NewDoc(docstr, "test3", None, 0) +ret = reader.Read() +while ret == 1: + processNode(reader) + ret = reader.Read() + +if ret != 0: + print "Error parsing the document test3" + sys.exit(1) + +if result != expect: + print "Unexpected result for test3" + print result + sys.exit(1) + +# +# cleanup +# +del reader + +# Memory debug specific +libxml2.cleanupParser() +if libxml2.debugMemory(1) == 0: + print "OK" +else: + print "Memory leak %d bytes" % (libxml2.debugMemory(1)) + libxml2.dumpMemory() diff --git a/win32/libxml2.def.src b/win32/libxml2.def.src index 2aea070b..b64b95e8 100644 --- a/win32/libxml2.def.src +++ b/win32/libxml2.def.src @@ -80,6 +80,13 @@ __xmlIndentTreeOutput #else xmlIndentTreeOutput DATA #endif +xmlIsBaseCharGroup DATA +xmlIsCharGroup DATA +xmlIsCombiningGroup DATA +xmlIsDigitGroup DATA +xmlIsExtenderGroup DATA +xmlIsIdeographicGroup DATA +xmlIsPubidChar_tab DATA #ifdef LIBXML_THREAD_ENABLED __xmlKeepBlanksDefaultValue #else @@ -619,9 +626,11 @@ xmlCharEncCloseFunc xmlCharEncFirstLine xmlCharEncInFunc xmlCharEncOutFunc +xmlCharInRange xmlCharStrdup xmlCharStrndup xmlCheckFilename +xmlCheckHTTPInput xmlCheckLanguageID xmlCheckUTF8 xmlCheckVersion @@ -902,11 +911,19 @@ xmlInitializeCatalog #endif xmlInitializeGlobalState xmlInitializePredefinedEntities +xmlIsBaseChar +xmlIsBlank xmlIsBlankNode +xmlIsChar +xmlIsCombining +xmlIsDigit +xmlIsExtender xmlIsID +xmlIsIdeographic xmlIsLetter xmlIsMainThread xmlIsMixedElement +xmlIsPubidChar xmlIsRef #ifdef LIBXML_HTML_ENABLED xmlIsXHTML @@ -1059,6 +1076,9 @@ xmlNanoHTTPCleanup xmlNanoHTTPClose #endif #ifdef LIBXML_HTTP_ENABLED +xmlNanoHTTPEncoding +#endif +#ifdef LIBXML_HTTP_ENABLED xmlNanoHTTPFetch #endif #ifdef LIBXML_HTTP_ENABLED @@ -1071,6 +1091,9 @@ xmlNanoHTTPMethod xmlNanoHTTPMethodRedir #endif #ifdef LIBXML_HTTP_ENABLED +xmlNanoHTTPMimeType +#endif +#ifdef LIBXML_HTTP_ENABLED xmlNanoHTTPOpen #endif #ifdef LIBXML_HTTP_ENABLED @@ -1080,6 +1103,9 @@ xmlNanoHTTPOpenRedir xmlNanoHTTPRead #endif #ifdef LIBXML_HTTP_ENABLED +xmlNanoHTTPRedir +#endif +#ifdef LIBXML_HTTP_ENABLED xmlNanoHTTPReturnCode #endif #ifdef LIBXML_HTTP_ENABLED @@ -1138,6 +1164,7 @@ xmlNextChar xmlNoNetExternalEntityLoader xmlNodeAddContent xmlNodeAddContentLen +xmlNodeBufGetContent xmlNodeDump xmlNodeDumpOutput xmlNodeGetBase @@ -1272,6 +1299,8 @@ xmlReaderNewFd xmlReaderNewFile xmlReaderNewIO xmlReaderNewMemory +xmlReaderNewWalker +xmlReaderWalker #ifdef DEBUG_MEMORY_LOCATION xmlReallocLoc #endif @@ -1596,6 +1625,7 @@ xmlStrstr xmlStrsub xmlSubstituteEntitiesDefault xmlSwitchEncoding +xmlSwitchInputEncoding xmlSwitchToEncoding xmlTextConcat xmlTextMerge @@ -1608,6 +1638,7 @@ xmlTextReaderConstName xmlTextReaderConstNamespaceUri xmlTextReaderConstPrefix xmlTextReaderConstString +xmlTextReaderConstValue xmlTextReaderConstXmlLang xmlTextReaderCurrentDoc xmlTextReaderCurrentNode @@ -1637,6 +1668,7 @@ xmlTextReaderMoveToNextAttribute xmlTextReaderName xmlTextReaderNamespaceUri xmlTextReaderNext +xmlTextReaderNextSibling xmlTextReaderNodeType xmlTextReaderNormalization xmlTextReaderPrefix diff --git a/xmldwalk.c b/xmldwalk.c deleted file mode 100644 index 408c143a..00000000 --- a/xmldwalk.c +++ /dev/null @@ -1,1197 +0,0 @@ -/* - * xmldwalk.c : the document traversing API.for XML - * - * this is heavily based upon the xmlTextReader streaming node API - * of libxml2 by Daniel Veillard (daniel@veillard.com). In fact I - * just copied and modified xmlreader.c - * - * So for license and disclaimer see the license and disclaimer of - * libxml2. - * - * alfred@mickautsch.de - */ - -#define IN_LIBXML -#include "libxml.h" - -#ifdef LIBXML_WALKER_ENABLED -#include - -#include -#include -#include -#include - -struct _xmlDocWalker { - xmlDocPtr doc; /* current document */ - xmlNodePtr node; /* current node */ - xmlNodePtr curnode; /* current attribute node */ - int depth; /* depth of the current node */ - xmlDocWalkerState state; /* state of the iterator */ -}; - -/** - * xmlNewDocWalker: - * @doc: the xmlDocPtr - * - * Creates a new instance of the xmlDocWalker - * - * Returns 0 in case of error, the new allocated xmlDocWalkerPtr otherwise - */ -xmlDocWalkerPtr -xmlNewDocWalker(xmlDocPtr doc) -{ - xmlDocWalkerPtr ret; - - if (doc == 0) - return(0); - - ret = xmlMalloc(sizeof(xmlDocWalker)); - if (ret == 0) { - xmlGenericError(xmlGenericErrorContext, - "xmlNewDocWalker : malloc failed\n"); - return(0); - } - - memset(ret, 0, sizeof(xmlDocWalker)); - - ret->doc = doc; - ret->node = 0; - ret->state = XML_DWALK_NONE; - - return ret; -} - -/** - * xmlFreeDocWalker: - * @iter: the xmlDocWalkerPtr - * - * Deallocate the xmlDocWalker - */ -void -xmlFreeDocWalker(xmlDocWalkerPtr iter) -{ - if (iter != 0) - xmlFree(iter); -} - -/** - * xmlDocWalkerRewind: - * @iter: the xmlDocWalkerPtr - * - * Initializes the xmlDocWalker - * - * Returns 0 or -1 in case of error - */ -int -xmlDocWalkerRewind(xmlDocWalkerPtr iter) -{ - if (iter == 0 || iter->doc == 0) - return(-1); - - if (iter->doc->children == 0) - return(0); - - iter->state = XML_DWALK_NONE; - iter->depth = 0; - iter->node = 0; - - return(1); -} - -/** - * xmlDocWalkerStep: - * @iter: the xmlDocWalkerPtr - * - * Steps through the xml tree - * - * Returns 0 or -1 in case of error - */ -int -xmlDocWalkerStep(xmlDocWalkerPtr iter) -{ - if (iter == 0) - return(-1); - - if (iter->state == XML_DWALK_END) - return(0); - - if (iter->node == 0) { - if (iter->doc->children == 0) { - iter->state = XML_DWALK_END; - return(0); - } - - iter->node = iter->doc->children; - iter->state = XML_DWALK_START; - return(1); - } - - if (iter->state != XML_DWALK_BACKTRACK) { - if (iter->node->children != 0) { - iter->node = iter->node->children; - iter->depth++; - iter->state = XML_DWALK_START; - return(1); - } - - if ((iter->node->type == XML_ELEMENT_NODE) || - (iter->node->type == XML_ATTRIBUTE_NODE)) { - iter->state = XML_DWALK_BACKTRACK; - return(1); - } - } - - if (iter->node->next != 0) { - iter->node = iter->node->next; - iter->state = XML_DWALK_START; - return(1); - } - - if (iter->node->parent != 0) { - if (iter->node->parent->type == XML_DOCUMENT_NODE) { - iter->state = XML_DWALK_END; - return(0); - } - - iter->node = iter->node->parent; - iter->depth--; - iter->state = XML_DWALK_BACKTRACK; - return(1); - } - - iter->state = XML_DWALK_END; - - return(1); -} - -/** - * xmlDocWalkerAttributeCount: - * @iter: the xmlDocWalkerPtr - * - * Provides the number of attributes of the current node - * - * Returns 0 if no attributes, -1 in case of error or the attribute count - */ -int -xmlDocWalkerAttributeCount(xmlDocWalkerPtr iter) -{ - int ret; - xmlAttrPtr attr; - xmlNsPtr ns; - xmlNodePtr node; - - if (iter == 0) - return(-1); - - if (iter->node == 0) - return(0); - - if (iter->curnode != 0) - node = iter->curnode; - else - node = iter->node; - - if (node->type != XML_ELEMENT_NODE) - return(0); - - ret = 0; - attr = node->properties; - while (attr != 0) { - ret++; - attr = attr->next; - } - - ns = node->nsDef; - while (ns != 0) { - ret++; - ns = ns->next; - } - - return ret; -} - -/** - * xmlDocWalkerDepth: - * @iter: the xmlDocWalkerPtr - * - * The depth of the node in the tree. - * - * Returns the depth or -1 in case of error - */ -int -xmlDocWalkerDepth(xmlDocWalkerPtr iter) -{ - if (iter == 0) - return(-1); - - if (iter->node == 0) - return(0); - - if (iter->curnode != 0) { - if ((iter->curnode->type == XML_ATTRIBUTE_NODE) || - (iter->curnode->type == XML_NAMESPACE_DECL)) - return iter->depth + 1; - - return iter->depth + 2; - } - - return iter->depth; -} - -/** - * xmlDocWalkerHasAttributes: - * @iter: the xmlDocWalkerPtr - * - * Whether the node has attributes. - * - * Returns 1 if true, 0 if false, and -1 in case or error - */ -int -xmlDocWalkerHasAttributes(xmlDocWalkerPtr iter) -{ - xmlNodePtr node; - - if (iter == 0) - return(-1); - - if (iter->node == 0) - return(0); - - if (iter->curnode != 0) - node = iter->curnode; - else - node = iter->node; - - if ((node->type == XML_ELEMENT_NODE) && (node->properties != 0)) - return(1); - - return(0); -} - -/** - * xmlDocWalkerHasValue: - * @iter: the xmlDocWalkerPtr - * - * Whether the node can have a text value. - * - * Returns 1 if true, 0 if false, and -1 in case or error - */ -int -xmlDocWalkerHasValue(xmlDocWalkerPtr iter) -{ - xmlNodePtr node; - - if (iter == 0) - return(-1); - - if (iter->node == 0) - return(0); - - if (iter->curnode != 0) - node = iter->curnode; - else - node = iter->node; - - switch (node->type) { - case XML_ATTRIBUTE_NODE: - case XML_TEXT_NODE: - case XML_CDATA_SECTION_NODE: - case XML_PI_NODE: - case XML_COMMENT_NODE: - case XML_NAMESPACE_DECL: - return(1); - default: - break; - } - - return(0); -} - -/** - * xmlDocWalkerIsEmptyElement: - * @iter: the xmlDocWalkerPtr - * - * Check if the current node is empty - * - * Returns 1 if empty, 0 if not and -1 in case of error - */ -int -xmlDocWalkerIsEmptyElement(xmlDocWalkerPtr iter) -{ - if ((iter == 0) || (iter->node == 0)) - return(-1); - - if (iter->node->type != XML_ELEMENT_NODE) - return(0); - - if (iter->curnode != 0) - return(0); - - if (iter->node->children != 0) - return(0); - - return(1); -} - -/** - * xmlDocWalkerLocalName: - * @iter: the xmlDocWalkerPtr - * - * The local name of the node. - * - * Returns the local name or NULL if not available - */ -xmlChar * -xmlDocWalkerLocalName(xmlDocWalkerPtr iter) -{ - xmlNodePtr node; - - if ((iter == 0) || (iter->node == 0)) - return(0); - - if (iter->curnode != 0) - node = iter->curnode; - else - node = iter->node; - - if (node->type == XML_NAMESPACE_DECL) { - xmlNsPtr ns = (xmlNsPtr) node; - - if (ns->prefix == 0) - return xmlStrdup(BAD_CAST "xmlns"); - else - return xmlStrdup(ns->prefix); - } - - if ((node->type != XML_ELEMENT_NODE) - && (node->type != XML_ATTRIBUTE_NODE)) - return (xmlDocWalkerName(iter)); - - return xmlStrdup(node->name); - -} - -/** - * xmlDocWalkerName: - * @iter: the xmlDocWalkerPtr - * - * The qualified name of the node, equal to Prefix :LocalName. - * - * Returns the local name or NULL if not available - */ -xmlChar * -xmlDocWalkerName(xmlDocWalkerPtr iter) -{ - xmlNodePtr node; - xmlChar *ret; - - if ((iter == 0) || (iter->node == 0)) - return(0); - - if (iter->curnode != 0) - node = iter->curnode; - else - node = iter->node; - - switch (node->type) { - case XML_ELEMENT_NODE: - case XML_ATTRIBUTE_NODE: - if ((node->ns == 0) || (node->ns->prefix == NULL)) - return xmlStrdup(node->name); - - if ((ret = xmlStrdup(node->ns->prefix)) && - (ret = xmlStrcat(ret, BAD_CAST ":")) && - (ret = xmlStrcat(ret, node->name))) - return ret; - if (ret) - xmlFree(ret); - return(0); - case XML_TEXT_NODE: - return xmlStrdup(BAD_CAST "#text"); - case XML_CDATA_SECTION_NODE: - return xmlStrdup(BAD_CAST "#cdata-section"); - case XML_ENTITY_NODE: - case XML_ENTITY_REF_NODE: - return xmlStrdup(node->name); - case XML_PI_NODE: - return xmlStrdup(node->name); - case XML_COMMENT_NODE: - return xmlStrdup(BAD_CAST "#comment"); - case XML_DOCUMENT_NODE: - case XML_HTML_DOCUMENT_NODE: -#ifdef LIBXML_DOCB_ENABLED - case XML_DOCB_DOCUMENT_NODE: -#endif - return xmlStrdup(BAD_CAST "#document"); - case XML_DOCUMENT_FRAG_NODE: - return xmlStrdup(BAD_CAST "#document-fragment"); - case XML_NOTATION_NODE: - return xmlStrdup(node->name); - case XML_DOCUMENT_TYPE_NODE: - case XML_DTD_NODE: - return xmlStrdup(node->name); - case XML_NAMESPACE_DECL: - { - xmlNsPtr ns = (xmlNsPtr) node; - - ret = xmlStrdup(BAD_CAST "xmlns"); - if (ns->prefix == 0) - return ret; - if ((ret) && - (ret = xmlStrcat(ret, BAD_CAST ":")) && - (ret = xmlStrcat(ret, ns->prefix))) - return ret; - if (ret) - xmlFree(ret); - return(0); - } - case XML_ELEMENT_DECL: - case XML_ATTRIBUTE_DECL: - case XML_ENTITY_DECL: - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: - return(0); - } - - return(0); -} - -/** - * xmlDocWalkerNodeType: - * @iter: the xmlDocWalkerPtr - * - * Get the node type of the current node - * Reference: - * http://dotgnu.org/pnetlib-doc/System/Xml/XmlNodeType.html - * - * Returns the xmlNodeType of the current node or -1 in case of error - */ -int -xmlDocWalkerNodeType(xmlDocWalkerPtr iter) -{ - xmlNodePtr node; - - if (iter == 0) - return(-1); - - if (iter->curnode != 0) - node = iter->curnode; - else - node = iter->node; - - if (node == 0) - return(0); - - switch (node->type) { - case XML_ELEMENT_NODE: - if ((iter->state == XML_DWALK_END) || - (iter->state == XML_DWALK_BACKTRACK)) - return XML_READER_TYPE_END_ELEMENT; - return XML_READER_TYPE_ELEMENT; - - case XML_NAMESPACE_DECL: - case XML_ATTRIBUTE_NODE: - return XML_READER_TYPE_ATTRIBUTE; - - case XML_TEXT_NODE: - if (xmlIsBlankNode(iter->node)) { - if (xmlNodeGetSpacePreserve(iter->node)) - return XML_READER_TYPE_SIGNIFICANT_WHITESPACE; - - return XML_READER_TYPE_WHITESPACE; - } - return XML_READER_TYPE_TEXT; - - case XML_CDATA_SECTION_NODE: - return XML_READER_TYPE_CDATA; - - case XML_ENTITY_REF_NODE: - return XML_READER_TYPE_ENTITY_REFERENCE; - - case XML_ENTITY_NODE: - return XML_READER_TYPE_ENTITY; - - case XML_PI_NODE: - return XML_READER_TYPE_PROCESSING_INSTRUCTION; - - case XML_COMMENT_NODE: - return XML_READER_TYPE_COMMENT; - - case XML_DOCUMENT_NODE: - case XML_HTML_DOCUMENT_NODE: -#ifdef LIBXML_DOCB_ENABLED - case XML_DOCB_DOCUMENT_NODE: -#endif - return XML_READER_TYPE_DOCUMENT; - - case XML_DOCUMENT_FRAG_NODE: - return XML_READER_TYPE_DOCUMENT_FRAGMENT; - - case XML_NOTATION_NODE: - return XML_READER_TYPE_NOTATION; - - case XML_DOCUMENT_TYPE_NODE: - case XML_DTD_NODE: - return XML_READER_TYPE_DOCUMENT_TYPE; - - case XML_ELEMENT_DECL: - case XML_ATTRIBUTE_DECL: - case XML_ENTITY_DECL: - case XML_XINCLUDE_START: - case XML_XINCLUDE_END: - return XML_READER_TYPE_NONE; - } - - return(-1); -} - -/** - * xmlDocWalkerPrefix: - * @iter: the xmlDocWalkerPtr - * - * A shorthand reference to the namespace associated with the node. - * - * Returns the prefix or NULL if not available - */ -xmlChar * -xmlDocWalkerPrefix(xmlDocWalkerPtr iter) -{ - xmlNodePtr node; - - if ((iter == 0) || (iter->node == 0) || (iter->node->ns == 0)) - return(0); - - if (iter->curnode != NULL) - node = iter->curnode; - else - node = iter->node; - - if (node->type == XML_NAMESPACE_DECL) { - xmlNsPtr ns = (xmlNsPtr) node; - - if (ns->prefix == 0) - return(0); - - return xmlStrdup(BAD_CAST "xmlns"); - } - - if ((node->type != XML_ELEMENT_NODE) && - (node->type != XML_ATTRIBUTE_NODE)) - return NULL; - - if ((node->ns != 0) && (node->ns->prefix != 0)) - return xmlStrdup(node->ns->prefix); - - return(0); -} - -/** - * xmlDocWalkerNamespaceUri: - * @iter: the xmlDocWalkerPtr - * - * The URI defining the namespace associated with the node. - * - * Returns the namespace URI or NULL if not available - */ -xmlChar * -xmlDocWalkerNamespaceUri(xmlDocWalkerPtr iter) -{ - xmlNodePtr node; - - if ((iter == 0) || (iter->node == 0)) - return(0); - - if (iter->curnode != 0) - node = iter->curnode; - else - node = iter->node; - - if (node->type == XML_NAMESPACE_DECL) - return xmlStrdup(BAD_CAST "http://www.w3.org/2000/xmlns/"); - - if ((node->type != XML_ELEMENT_NODE) - && (node->type != XML_ATTRIBUTE_NODE)) - return(0); - - if (node->ns != 0) - return xmlStrdup(node->ns->href); - - return(0); -} - -/** - * xmlDocWalkerBaseUri: - * @iter: the xmlDocWalkerPtr - * - * The base URI of the node. - * - * Returns the base URI or NULL if not available - */ -xmlChar * -xmlDocWalkerBaseUri(xmlDocWalkerPtr iter) -{ - if ((iter == 0) || (iter->node == 0)) - return(0); - - return xmlNodeGetBase(0, iter->node); -} - -/** - * xmlDocWalkerValue: - * @iter: the xmlDocWalkerPtr - * - * Provides the text value of the node if present - * - * Returns the string or NULL if not available. The retsult must be deallocated - * with xmlFree() - */ -xmlChar * -xmlDocWalkerValue(xmlDocWalkerPtr iter) -{ - xmlNodePtr node; - - if ((iter == 0) || (iter->node == 0)) - return(0); - - if (iter->curnode != 0) - node = iter->curnode; - else - node = iter->node; - - switch (node->type) { - case XML_NAMESPACE_DECL: - return xmlStrdup(((xmlNsPtr) node)->href); - case XML_ATTRIBUTE_NODE: - { - xmlAttrPtr attr = (xmlAttrPtr) node; - - if (attr->parent != 0) - return xmlNodeListGetString(attr->parent->doc, - attr->children, 1); - else - return xmlNodeListGetString(0, attr->children, 1); - } - break; - case XML_TEXT_NODE: - case XML_CDATA_SECTION_NODE: - case XML_PI_NODE: - case XML_COMMENT_NODE: - if (node->content != 0) - return xmlStrdup(node->content); - default: - break; - } - return (NULL); -} - -/** - * xmlDocWalkerGetAttributeNo: - * @iter: the xmlDocWalkerPtr - * @no: the zero-based index of the attribute relative to the containing element - * - * Provides the value of the attribute with the specified index relative - * to the containing element. - * - * Returns a string containing the value of the specified attribute, or NULL - * in case of error. The string must be deallocated by the caller. - */ -xmlChar * -xmlDocWalkerGetAttributeNo(xmlDocWalkerPtr iter, int no) -{ - xmlChar *ret; - int i; - xmlAttrPtr cur; - xmlNsPtr ns; - - if ((iter == 0) || (iter->node == 0) || (iter->curnode != 0) || - (iter->node->type != XML_ELEMENT_NODE)) - return(0); - - ns = iter->node->nsDef; - for (i = 0; i < no && ns != 0; i++) - ns = ns->next; - - if (ns != 0) - return (xmlStrdup(ns->href)); - - cur = iter->node->properties; - if (cur == 0) - return(0); - - for (; i < no; i++) { - cur = cur->next; - if (cur == 0) - return(0); - } - - ret = xmlNodeListGetString(iter->node->doc, cur->children, 1); - if (ret == 0) - return (xmlStrdup((xmlChar *) "")); - - return ret; -} - -/** - * xmlDocWalkerGetAttribute: - * @iter: the xmlDocWalkerPtr - * @name: the qualified name of the attribute. - * - * Provides the value of the attribute with the specified qualified name. - * - * Returns a string containing the value of the specified attribute, or NULL - * in case of error. The string must be deallocated by the caller. - */ -xmlChar * -xmlDocWalkerGetAttribute(xmlDocWalkerPtr iter, const xmlChar * name) -{ - xmlChar *prefix = 0; - xmlChar *localname; - xmlNsPtr ns; - xmlChar *ret = 0; - - if ((iter == 0) || (iter->node == 0) || (iter->curnode != 0) || - (iter->node->type != XML_ELEMENT_NODE)) - return(0); - - localname = xmlSplitQName2(name, &prefix); - if (localname == 0) - return xmlGetProp(iter->node, name); - - ns = xmlSearchNs(iter->node->doc, iter->node, prefix); - if (ns != 0) - ret = xmlGetNsProp(iter->node, localname, ns->href); - - if (localname != 0) - xmlFree(localname); - if (prefix != 0) - xmlFree(prefix); - - return ret; -} - -/** - * xmlDocWalkerGetAttributeNs: - * @iter: the xmlDocWalkerPtr - * @localName: the local name of the attribute. - * @namespaceURI: the namespace URI of the attribute. - * - * Provides the value of the specified attribute - * - * Returns a string containing the value of the specified attribute, or NULL - * in case of error. The string must be deallocated by the caller. - */ -xmlChar * -xmlDocWalkerGetAttributeNs(xmlDocWalkerPtr iter, - const xmlChar * localName, - const xmlChar * namespaceURI) -{ - if ((iter == 0) || (iter->node == 0) - || (iter->node->type != XML_ELEMENT_NODE)) - return(0); - - return xmlGetNsProp(iter->node, localName, namespaceURI); -} - -/** - * xmlDocWalkerLookupNamespace: - * @iter: the xmlDocWalkerPtr - * @prefix: the prefix whose namespace URI is to be resolved. To return - * the default namespace, specify NULL - * - * Resolves a namespace prefix in the scope of the current element. - * - * Returns a string containing the namespace URI to which the prefix maps - * or NULL in case of error. The string must be deallocated by the caller. - */ -xmlChar * -xmlDocWalkerLookupNamespace(xmlDocWalkerPtr iter, const xmlChar * prefix) -{ - xmlNsPtr ns; - - if ((iter == 0) || (iter->node == 0)) - return(0); - - ns = xmlSearchNs(iter->node->doc, iter->node, prefix); - if (ns == NULL) - return (NULL); - return (xmlStrdup(ns->href)); -} - -/** - * xmlDocWalkerMoveToAttributeNo: - * @iter: the xmlDocWalkerPtr - * @no: the zero-based index of the attribute relative to the containing - * element. - * - * Moves the position of the current instance to the attribute with - * the specified index relative to the containing element. - * - * Returns 1 in case of success, -1 in case of error, 0 if not found - */ -int -xmlDocWalkerMoveToAttributeNo(xmlDocWalkerPtr iter, int no) -{ - int i; - xmlAttrPtr cur; - xmlNsPtr ns; - - if ((iter == 0) || (iter->node == 0)) - return(-1); - - if ((iter->state == XML_DWALK_NONE) || - (iter->state == XML_DWALK_BACKTRACK) || - (iter->state == XML_DWALK_END)) - return(0); - - if (iter->node->type != XML_ELEMENT_NODE) - return(0); - - iter->curnode = NULL; - - ns = iter->node->nsDef; - for (i = 0; i < no && ns != NULL; i++) - ns = ns->next; - - if (ns != 0) { - iter->curnode = (xmlNodePtr) ns; - return(1); - } - - cur = iter->node->properties; - if (cur == 0) - return(0); - - for (; i < no; i++) { - cur = cur->next; - if (cur == 0) - return(0); - } - - iter->curnode = (xmlNodePtr) cur; - return(1); -} - -/** - * xmlDocWalkerMoveToAttribute: - * @iter: the xmlDocWalkerPtr - * @name: the qualified name of the attribute. - * - * Moves the position of the current instance to the attribute with - * the specified qualified name. - * - * Returns 1 in case of success, -1 in case of error, 0 if not found - */ -int -xmlDocWalkerMoveToAttribute(xmlDocWalkerPtr iter, const xmlChar * name) -{ - xmlChar *prefix = NULL; - xmlChar *localname = NULL; - xmlNsPtr ns; - xmlAttrPtr prop; - int ret = 0; - - if ((iter == 0) || (iter->node == 0) || (name == 0)) - return(-1); - - if ((iter->state == XML_DWALK_NONE) || - (iter->state == XML_DWALK_BACKTRACK) || - (iter->state == XML_DWALK_END)) - goto not_found; - - if (iter->node->type != XML_ELEMENT_NODE) - goto not_found; - - localname = xmlSplitQName2(name, &prefix); - if (localname == 0) { - if (xmlStrEqual(name, BAD_CAST "xmlns")) { - ns = iter->node->nsDef; - while (ns != 0) { - if (ns->prefix == 0) { - iter->curnode = (xmlNodePtr) ns; - goto found; - } - ns = ns->next; - } - - goto not_found; - } - - prop = iter->node->properties; - while (prop != 0) { - if (xmlStrEqual(prop->name, name) && - ((prop->ns == NULL) || (prop->ns->prefix == NULL))) { - iter->curnode = (xmlNodePtr) prop; - goto found; - } - prop = prop->next; - } - - goto not_found; - } - - if (xmlStrEqual(prefix, BAD_CAST "xmlns")) { - ns = iter->node->nsDef; - while (ns != 0) { - if (ns->prefix != NULL && xmlStrEqual(ns->prefix, localname)) { - iter->curnode = (xmlNodePtr) ns; - goto found; - } - ns = ns->next; - } - goto not_found; - } - - prop = iter->node->properties; - while (prop != NULL) { - if (xmlStrEqual(prop->name, localname) && - (prop->ns != NULL) && xmlStrEqual(prop->ns->prefix, prefix)) { - iter->curnode = (xmlNodePtr) prop; - goto found; - } - prop = prop->next; - } - - if (0) - found:{ - ret = 1; - } - not_found: - - if (localname != 0) - xmlFree(localname); - if (prefix != 0) - xmlFree(prefix); - return ret; -} - -/** - * xmlDocWalkerMoveToAttributeNs: - * @iter: the xmlDocWalkerPtr - * @localName: the local name of the attribute. - * @namespaceURI: the namespace URI of the attribute. - * - * Moves the position of the current instance to the attribute with the - * specified local name and namespace URI. - * - * Returns 1 in case of success, -1 in case of error, 0 if not found - */ -int -xmlDocWalkerMoveToAttributeNs(xmlDocWalkerPtr iter, - const xmlChar * localName, - const xmlChar * namespaceURI) -{ - xmlAttrPtr prop; - xmlNodePtr node; - - if ((iter == 0) || (iter->node == 0) || (localName == 0) - || (namespaceURI == 0)) - return(-1); - - if ((iter->state == XML_DWALK_NONE) || - (iter->state == XML_DWALK_BACKTRACK) || - (iter->state == XML_DWALK_END)) - return(0); - - if (iter->node->type != XML_ELEMENT_NODE) - return(0); - - node = iter->node; - - prop = node->properties; - while (prop != NULL) { - if (xmlStrEqual(prop->name, localName) && - ((prop->ns != NULL) - && (xmlStrEqual(prop->ns->href, namespaceURI)))) { - iter->curnode = (xmlNodePtr) prop; - return(1); - } - - prop = prop->next; - } - - return(0); -} - -/** - * xmlDocWalkerMoveToFirstAttribute: - * @iter: the xmlDocWalkerPtr - * - * Moves the position of the current instance to the first attribute - * associated with the current node. - * - * Returns 1 in case of success, -1 in case of error, 0 if not found - */ -int -xmlDocWalkerMoveToFirstAttribute(xmlDocWalkerPtr iter) -{ - if ((iter == 0) || (iter->node == 0)) - return(-1); - - if ((iter->state == XML_DWALK_NONE) || - (iter->state == XML_DWALK_BACKTRACK) || - (iter->state == XML_DWALK_END)) - return(0); - - if (iter->node->type != XML_ELEMENT_NODE) - return(0); - - if (iter->node->nsDef != NULL) { - iter->curnode = (xmlNodePtr) iter->node->nsDef; - return(1); - } - - if (iter->node->properties != NULL) { - iter->curnode = (xmlNodePtr) iter->node->properties; - return(1); - } - - return(0); -} - -/** - * xmlDocWalkerMoveToNextAttribute: - * @iter: the xmlDocWalkerPtr - * - * Moves the position of the current instance to the next attribute - * associated with the current node. - * - * Returns 1 in case of success, -1 in case of error, 0 if not found - */ -int -xmlDocWalkerMoveToNextAttribute(xmlDocWalkerPtr iter) -{ - if ((iter == 0) || (iter->node == 0)) - return(-1); - - if ((iter->state == XML_DWALK_NONE) || - (iter->state == XML_DWALK_BACKTRACK) || - (iter->state == XML_DWALK_END)) - return(0); - - if (iter->node->type != XML_ELEMENT_NODE) - return(0); - if (iter->curnode == NULL) - return (xmlDocWalkerMoveToFirstAttribute(iter)); - - if (iter->curnode->type == XML_NAMESPACE_DECL) { - xmlNsPtr ns = (xmlNsPtr) iter->curnode; - - if (ns->next != NULL) { - iter->curnode = (xmlNodePtr) ns->next; - return(1); - } - if (iter->node->properties != NULL) { - iter->curnode = (xmlNodePtr) iter->node->properties; - return(1); - } - - return(0); - } else if ((iter->curnode->type == XML_ATTRIBUTE_NODE) && - (iter->curnode->next != NULL)) { - iter->curnode = iter->curnode->next; - return(1); - } - - return(0); -} - -/** - * xmlDocWalkerMoveToElement: - * @iter: the xmlDocWalkerPtr - * - * Moves the position of the current instance to the node that - * contains the current Attribute node. - * - * Returns 1 in case of success, -1 in case of error, 0 if not moved - */ -int -xmlDocWalkerMoveToElement(xmlDocWalkerPtr iter) -{ - if ((iter == 0) || (iter->node == 0)) - return(-1); - - if ((iter->state == XML_DWALK_NONE) || - (iter->state == XML_DWALK_BACKTRACK) || - (iter->state == XML_DWALK_END)) - return(0); - - if (iter->node->type != XML_ELEMENT_NODE) - return(0); - - if (iter->curnode != NULL) { - iter->curnode = NULL; - return(1); - } - - return(0); -} - -/** - * xmlDocWalkerCurrentNode: - * @iter: the xmlDocWalkerPtr - * - * Hacking interface allowing to get the xmlNodePtr correponding to the - * current node being accessed by the xmlDocWalker. - * - * Returns the xmlNodePtr or NULL in case of error. - */ -xmlNodePtr -xmlDocWalkerCurrentNode(xmlDocWalkerPtr iter) -{ - if (iter == 0) - return(0); - - if (iter->curnode != NULL) - return iter->curnode; - - return iter->node; -} - -/** - * xmlDocWalkerCurrentDoc: - * @iter: the xmlDocWalkerPtr - * - * Hacking interface allowing to get the xmlDocPtr correponding to the - * current document being accessed by the xmlDocWalker. - * - * Returns the xmlDocPtr or NULL in case of error. - */ -xmlDocPtr -xmlDocWalkerCurrentDoc(xmlDocWalkerPtr iter) -{ - if (iter == 0) - return(0); - - return iter->doc; -} - -/** - * xmlDocWalkerNext: - * @iter: the xmlDocWalkerPtr - * - * Step to the next sibling of the current node in document order - * - * Returns 1 if ok, 0 if there are no more nodes, or -1 in case of error - */ -int -xmlDocWalkerNext(xmlDocWalkerPtr iter) -{ - if ((iter == 0) || (iter->doc == 0)) - return(-1); - - if (iter->state == XML_DWALK_END) - return(0); - - if (iter->node == 0) - return xmlDocWalkerStep(iter); - - if (iter->node->next != 0) { - iter->node = iter->node->next; - iter->state = XML_DWALK_START; - return(1); - } - - return(0); -} -#endif /* LIBXML_WALKER_ENABLED */ diff --git a/xmllint.c b/xmllint.c index 81c2ea58..d0d2ed20 100644 --- a/xmllint.c +++ b/xmllint.c @@ -599,13 +599,13 @@ static void myClose(FILE *f) { * * ************************************************************************/ static void processNode(xmlTextReaderPtr reader) { - xmlChar *name, *value; + const xmlChar *name, *value; - name = xmlTextReaderName(reader); + name = xmlTextReaderConstName(reader); if (name == NULL) name = xmlStrdup(BAD_CAST "--"); - value = xmlTextReaderValue(reader); + value = xmlTextReaderConstValue(reader); printf("%d %d %s %d %d", xmlTextReaderDepth(reader), @@ -613,12 +613,10 @@ static void processNode(xmlTextReaderPtr reader) { name, xmlTextReaderIsEmptyElement(reader), xmlTextReaderHasValue(reader)); - xmlFree(name); if (value == NULL) printf("\n"); else { printf(" %s\n", value); - xmlFree(value); } } @@ -1803,12 +1801,15 @@ main(int argc, char **argv) { if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) { if (repeat) { xmlParserCtxtPtr ctxt = NULL; +#ifdef LIBXML_READER_ENABLED + xmlTextReaderPtr reader = NULL; +#endif /* LIBXML_READER_ENABLED */ for (acount = 0;acount < repeat;acount++) { #ifdef LIBXML_READER_ENABLED - if (stream != 0) + if (stream != 0) { streamFile(argv[i]); - else { + } else { #endif /* LIBXML_READER_ENABLED */ if (ctxt == NULL) ctxt = xmlNewParserCtxt(); diff --git a/xmlreader.c b/xmlreader.c index 1f1176b6..6efb27fa 100644 --- a/xmlreader.c +++ b/xmlreader.c @@ -37,6 +37,7 @@ #include #include #include +#include /* #define DEBUG_CALLBACKS */ /* #define DEBUG_READER */ @@ -96,6 +97,7 @@ typedef enum { struct _xmlTextReader { int mode; /* the parsing mode */ + xmlDocPtr doc; /* when walking an existing doc */ xmlTextReaderValidate validate;/* is there any validation */ int allocs; /* what structure were deallocated */ xmlTextReaderState state; @@ -115,6 +117,8 @@ struct _xmlTextReader { int depth; /* depth of the current node */ xmlNodePtr faketext;/* fake xmlNs chld */ int preserve;/* preserve the resulting document */ + xmlBufferPtr buffer; /* used to return const xmlChar * */ + xmlDictPtr dict; /* the context dictionnary */ /* entity stack when traversing entities content */ xmlNodePtr ent; /* Current Entity Ref Node */ @@ -144,8 +148,11 @@ static const char *xmlTextReaderIsPreserved = "Preserve this element"; * * Macro used to return an interned string */ -#define CONSTSTR(str) xmlDictLookup(reader->ctxt->dict, (str), -1) -#define CONSTQSTR(p, str) xmlDictQLookup(reader->ctxt->dict, (p), (str)) +#define CONSTSTR(str) xmlDictLookup(reader->dict, (str), -1) +#define CONSTQSTR(p, str) xmlDictQLookup(reader->dict, (p), (str)) + +static int xmlTextReaderReadTree(xmlTextReaderPtr reader); +static int xmlTextReaderNextTree(xmlTextReaderPtr reader); /************************************************************************ * * @@ -572,7 +579,7 @@ xmlTextReaderStartElementNs(void *ctx, xmlTextReaderPtr reader = ctxt->_private; #ifdef DEBUG_CALLBACKS - printf("xmlTextReaderStartElementNs(%s)\n", fullname); + printf("xmlTextReaderStartElementNs(%s)\n", localname); #endif if ((reader != NULL) && (reader->startElementNs != NULL)) { reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces, @@ -606,7 +613,7 @@ xmlTextReaderEndElementNs(void *ctx, xmlTextReaderPtr reader = ctxt->_private; #ifdef DEBUG_CALLBACKS - printf("xmlTextReaderEndElementNs(%s)\n", fullname); + printf("xmlTextReaderEndElementNs(%s)\n", localname); #endif if ((reader != NULL) && (reader->endElementNs != NULL)) { reader->endElementNs(ctx, localname, prefix, URI); @@ -1063,7 +1070,12 @@ xmlTextReaderRead(xmlTextReaderPtr reader) { xmlTextReaderState oldstate = XML_TEXTREADER_START; xmlNodePtr oldnode = NULL; - if ((reader == NULL) || (reader->ctxt == NULL)) + + if (reader == NULL) + return(-1); + if (reader->doc != NULL) + return(xmlTextReaderReadTree(reader)); + if (reader->ctxt == NULL) return(-1); if (reader->ctxt->wellFormed != 1) return(-1); @@ -1317,6 +1329,8 @@ xmlNodePtr xmlTextReaderExpand(xmlTextReaderPtr reader) { if ((reader == NULL) || (reader->node == NULL) || (reader->ctxt == NULL)) return(NULL); + if (reader->doc != NULL) + return(reader->node); if (xmlTextReaderDoExpand(reader) < 0) return(NULL); return(reader->node); @@ -1339,6 +1353,8 @@ xmlTextReaderNext(xmlTextReaderPtr reader) { if (reader == NULL) return(-1); + if (reader->doc != NULL) + return(xmlTextReaderNextTree(reader)); cur = reader->node; if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE)) return(xmlTextReaderRead(reader)); @@ -1466,6 +1482,169 @@ xmlTextReaderReadBinHex(xmlTextReaderPtr reader, } #endif +/************************************************************************ + * * + * Operating on a preparsed tree * + * * + ************************************************************************/ +static int +xmlTextReaderNextTree(xmlTextReaderPtr reader) +{ + if (reader == 0) + return(-1); + + if (reader->state == XML_TEXTREADER_END) + return(0); + + if (reader->node == 0) { + if (reader->doc->children == 0) { + reader->state = XML_TEXTREADER_END; + return(0); + } + + reader->node = reader->doc->children; + reader->state = XML_TEXTREADER_START; + return(1); + } + + if (reader->state != XML_TEXTREADER_BACKTRACK) { + if (reader->node->children != 0) { + reader->node = reader->node->children; + reader->depth++; + reader->state = XML_TEXTREADER_START; + return(1); + } + + if ((reader->node->type == XML_ELEMENT_NODE) || + (reader->node->type == XML_ATTRIBUTE_NODE)) { + reader->state = XML_TEXTREADER_BACKTRACK; + return(1); + } + } + + if (reader->node->next != 0) { + reader->node = reader->node->next; + reader->state = XML_TEXTREADER_START; + return(1); + } + + if (reader->node->parent != 0) { + if (reader->node->parent->type == XML_DOCUMENT_NODE) { + reader->state = XML_TEXTREADER_END; + return(0); + } + + reader->node = reader->node->parent; + reader->depth--; + reader->state = XML_TEXTREADER_BACKTRACK; + return(1); + } + + reader->state = XML_TEXTREADER_END; + + return(1); +} + +/** + * xmlTextReaderReadTree: + * @reader: the xmlTextReaderPtr used + * + * Moves the position of the current instance to the next node in + * the stream, exposing its properties. + * + * Returns 1 if the node was read successfully, 0 if there is no more + * nodes to read, or -1 in case of error + */ +static int +xmlTextReaderReadTree(xmlTextReaderPtr reader) { + if (reader->state == XML_TEXTREADER_END) + return(0); + + if (reader->node == NULL) { + if (reader->doc->children == NULL) { + reader->state = XML_TEXTREADER_END; + return(0); + } + + reader->node = reader->doc->children; + reader->state = XML_TEXTREADER_START; + return(1); + } + + if (reader->state != XML_TEXTREADER_BACKTRACK) { + if (reader->node->children != 0) { + reader->node = reader->node->children; + reader->depth++; + reader->state = XML_TEXTREADER_START; + return(1); + } + + if ((reader->node->type == XML_ELEMENT_NODE) || + (reader->node->type == XML_ATTRIBUTE_NODE)) { + reader->state = XML_TEXTREADER_BACKTRACK; + return(1); + } + } + + if (reader->node->next != 0) { + reader->node = reader->node->next; + reader->state = XML_TEXTREADER_START; + return(1); + } + + if (reader->node->parent != 0) { + if ((reader->node->parent->type == XML_DOCUMENT_NODE) || + (reader->node->parent->type == XML_HTML_DOCUMENT_NODE)) { + reader->state = XML_TEXTREADER_END; + return(0); + } + + reader->node = reader->node->parent; + reader->depth--; + reader->state = XML_TEXTREADER_BACKTRACK; + return(1); + } + + reader->state = XML_TEXTREADER_END; + + return(1); +} + +/** + * xmlTextReaderNextTree: + * @reader: the xmlTextReaderPtr used + * + * Skip to the node following the current one in document order while + * avoiding the subtree if any. + * Currently implemented only for Readers built on a document + * + * Returns 1 if the node was read successfully, 0 if there is no more + * nodes to read, or -1 in case of error + */ +int +xmlTextReaderNextSibling(xmlTextReaderPtr reader) { + if (reader == NULL) + return(-1); + if (reader->doc == NULL) { + TODO + return(-1); + } + + if (reader->state == XML_TEXTREADER_END) + return(0); + + if (reader->node == 0) + return(xmlTextReaderNextTree(reader)); + + if (reader->node->next != 0) { + reader->node = reader->node->next; + reader->state = XML_TEXTREADER_START; + return(1); + } + + return(0); +} + /************************************************************************ * * * Constructor and destructors * @@ -1493,10 +1672,12 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) { return(NULL); } memset(ret, 0, sizeof(xmlTextReader)); + ret->doc = NULL; ret->entTab = NULL; ret->entMax = 0; ret->entNr = 0; ret->input = input; + ret->buffer = xmlBufferCreateSize(100); ret->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler)); if (ret->sax == NULL) { xmlFree(ret); @@ -1559,6 +1740,7 @@ xmlNewTextReader(xmlParserInputBufferPtr input, const char *URI) { * use the parser dictionnary to allocate all elements and attributes names */ ret->ctxt->docdict = 1; + ret->dict = ret->ctxt->dict; return(ret); } @@ -1615,6 +1797,8 @@ xmlFreeTextReader(xmlTextReaderPtr reader) { } #endif if (reader->ctxt != NULL) { + if (reader->dict == reader->ctxt->dict) + reader->dict = NULL; if (reader->ctxt->myDoc != NULL) { if (reader->preserve == 0) xmlTextReaderFreeDoc(reader, reader->ctxt->myDoc); @@ -1636,8 +1820,12 @@ xmlFreeTextReader(xmlTextReaderPtr reader) { if (reader->faketext != NULL) { xmlFreeNode(reader->faketext); } + if (reader->buffer != NULL) + xmlBufferFree(reader->buffer); if (reader->entTab != NULL) xmlFree(reader->entTab); + if (reader->dict != NULL) + xmlDictFree(reader->dict); xmlFree(reader); } @@ -2819,7 +3007,7 @@ xmlTextReaderHasValue(xmlTextReaderPtr reader) { * * Provides the text value of the node if present * - * Returns the string or NULL if not available. The retsult must be deallocated + * Returns the string or NULL if not available. The result must be deallocated * with xmlFree() */ xmlChar * @@ -2859,6 +3047,55 @@ xmlTextReaderValue(xmlTextReaderPtr reader) { return(NULL); } +/** + * xmlTextReaderConstValue: + * @reader: the xmlTextReaderPtr used + * + * Provides the text value of the node if present + * + * Returns the string or NULL if not available. The result will be + * deallocated on the next Read() operation. + */ +const xmlChar * +xmlTextReaderConstValue(xmlTextReaderPtr reader) { + xmlNodePtr node; + if (reader == NULL) + return(NULL); + if (reader->node == NULL) + return(NULL); + if (reader->curnode != NULL) + node = reader->curnode; + else + node = reader->node; + + switch (node->type) { + case XML_NAMESPACE_DECL: + return(((xmlNsPtr) node)->href); + case XML_ATTRIBUTE_NODE:{ + xmlAttrPtr attr = (xmlAttrPtr) node; + + if ((attr->children != NULL) && + (attr->children->type == XML_TEXT_NODE) && + (attr->children->next == NULL)) + return(attr->children->content); + else { + reader->buffer->use = 0; + xmlNodeBufGetContent(reader->buffer, node); + return(reader->buffer->content); + } + break; + } + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: + return(node->content); + default: + break; + } + return(NULL); +} + /** * xmlTextReaderIsDefault: * @reader: the xmlTextReaderPtr used @@ -3141,6 +3378,10 @@ xmlTextReaderPreserve(xmlTextReaderPtr reader) { */ xmlDocPtr xmlTextReaderCurrentDoc(xmlTextReaderPtr reader) { + if (reader == NULL) + return(NULL); + if (reader->doc != NULL) + return(reader->doc); if ((reader == NULL) || (reader->ctxt == NULL) || (reader->ctxt->myDoc == NULL)) return(NULL); @@ -3544,12 +3785,140 @@ xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader, * Returns 0 in case of success and -1 in case of error. */ static int -xmlTextReaderSetup(xmlTextReaderPtr reader, const char *URL, +xmlTextReaderSetup(xmlTextReaderPtr reader, + xmlParserInputBufferPtr input, const char *URL, const char *encoding, int options) { - if ((reader == NULL) || (reader->ctxt == NULL)) + if (reader == NULL) return (-1); + reader->doc = NULL; + reader->entNr = 0; + if ((input != NULL) && (reader->input != NULL) && + (reader->allocs & XML_TEXTREADER_INPUT)) { + xmlFreeParserInputBuffer(reader->input); + reader->input = NULL; + reader->allocs -= XML_TEXTREADER_INPUT; + } + if (input != NULL) { + reader->input = input; + reader->allocs |= XML_TEXTREADER_INPUT; + } + if (reader->buffer == NULL) + reader->buffer = xmlBufferCreateSize(100); + if (reader->buffer == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlTextReaderSetup : malloc failed\n"); + return (-1); + } + if (reader->sax == NULL) + reader->sax = (xmlSAXHandler *) xmlMalloc(sizeof(xmlSAXHandler)); + if (reader->sax == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlTextReaderSetup : malloc failed\n"); + return (-1); + } + xmlSAXVersion(reader->sax, 2); + reader->startElement = reader->sax->startElement; + reader->sax->startElement = xmlTextReaderStartElement; + reader->endElement = reader->sax->endElement; + reader->sax->endElement = xmlTextReaderEndElement; +#ifdef LIBXML_SAX1_ENABLED + if (reader->sax->initialized == XML_SAX2_MAGIC) { +#endif /* LIBXML_SAX1_ENABLED */ + reader->startElementNs = reader->sax->startElementNs; + reader->sax->startElementNs = xmlTextReaderStartElementNs; + reader->endElementNs = reader->sax->endElementNs; + reader->sax->endElementNs = xmlTextReaderEndElementNs; +#ifdef LIBXML_SAX1_ENABLED + } else { + reader->startElementNs = NULL; + reader->endElementNs = NULL; + } +#endif /* LIBXML_SAX1_ENABLED */ + reader->characters = reader->sax->characters; + reader->sax->characters = xmlTextReaderCharacters; + reader->sax->ignorableWhitespace = xmlTextReaderCharacters; + reader->cdataBlock = reader->sax->cdataBlock; + reader->sax->cdataBlock = xmlTextReaderCDataBlock; + + reader->mode = XML_TEXTREADER_MODE_INITIAL; + reader->node = NULL; + reader->curnode = NULL; + if (input != NULL) { + if (reader->input->buffer->use < 4) { + xmlParserInputBufferRead(input, 4); + } + if (reader->ctxt == NULL) { + if (reader->input->buffer->use >= 4) { + reader->ctxt = xmlCreatePushParserCtxt(reader->sax, NULL, + (const char *) reader->input->buffer->content, 4, URL); + reader->base = 0; + reader->cur = 4; + } else { + reader->ctxt = + xmlCreatePushParserCtxt(reader->sax, NULL, NULL, 0, URL); + reader->base = 0; + reader->cur = 0; + } + } else { + xmlParserInputPtr inputStream; + xmlParserInputBufferPtr buf; + xmlCharEncoding enc = XML_CHAR_ENCODING_NONE; + + if (reader->ctxt->myDoc != NULL) + xmlDictReference(reader->ctxt->myDoc->dict); + xmlCtxtReset(reader->ctxt); + buf = xmlAllocParserInputBuffer(enc); + if (buf == NULL) return(-1); + inputStream = xmlNewInputStream(reader->ctxt); + if (inputStream == NULL) { + xmlFreeParserInputBuffer(buf); + return(-1); + } + + if (URL == NULL) + inputStream->filename = NULL; + else + inputStream->filename = (char *) + xmlCanonicPath((const xmlChar *) URL); + inputStream->buf = buf; + inputStream->base = inputStream->buf->buffer->content; + inputStream->cur = inputStream->buf->buffer->content; + inputStream->end = + &inputStream->buf->buffer->content[inputStream->buf->buffer->use]; + + inputPush(reader->ctxt, inputStream); + reader->cur = 0; + } + if (reader->ctxt == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlTextReaderSetup : malloc failed\n"); + return (-1); + } + } + if (reader->dict != NULL) { + if (reader->ctxt->dict != NULL) { + if (reader->dict != reader->ctxt->dict) { + xmlDictFree(reader->dict); + reader->dict = reader->ctxt->dict; + } + } else { + reader->ctxt->dict = reader->dict; + } + } else { + if (reader->ctxt->dict == NULL) + reader->ctxt->dict = xmlDictCreate(); + reader->dict = reader->ctxt->dict; + } + reader->ctxt->_private = reader; + reader->ctxt->linenumbers = 1; + reader->ctxt->dictNames = 1; + /* + * use the parser dictionnary to allocate all elements and attributes names + */ + reader->ctxt->docdict = 1; + xmlCtxtUseOptions(reader->ctxt, options); if (encoding != NULL) { xmlCharEncodingHandlerPtr hdlr; @@ -3562,9 +3931,49 @@ xmlTextReaderSetup(xmlTextReaderPtr reader, const char *URL, (reader->ctxt->input->filename == NULL)) reader->ctxt->input->filename = (char *) xmlStrdup((const xmlChar *) URL); + + reader->doc = NULL; + return (0); } +/** + * xmlReaderWalker: + * @doc: a preparsed document + * + * Create an xmltextReader for a preparsed document. + * + * Returns the new reader or NULL in case of error. + */ +xmlTextReaderPtr +xmlReaderWalker(xmlDocPtr doc) +{ + xmlTextReaderPtr ret; + + if (doc == NULL) + return(NULL); + + ret = xmlMalloc(sizeof(xmlTextReader)); + if (ret == NULL) { + xmlGenericError(xmlGenericErrorContext, + "xmlNewTextReader : malloc failed\n"); + return(NULL); + } + memset(ret, 0, sizeof(xmlTextReader)); + ret->entNr = 0; + ret->input = NULL; + ret->mode = XML_TEXTREADER_MODE_INITIAL; + ret->node = NULL; + ret->curnode = NULL; + ret->base = 0; + ret->cur = 0; + ret->allocs = XML_TEXTREADER_CTXT; + ret->doc = doc; + ret->state = XML_TEXTREADER_START; + ret->dict = xmlDictCreate(); + return(ret); +} + /** * xmlReaderForDoc: * @cur: a pointer to a zero terminated string @@ -3573,6 +3982,7 @@ xmlTextReaderSetup(xmlTextReaderPtr reader, const char *URL, * @options: a combination of xmlParserOption(s) * * Create an xmltextReader for an XML in-memory document. + * The parsing flags @options are a combination of xmlParserOption(s). * * Returns the new reader or NULL in case of error. */ @@ -3597,6 +4007,7 @@ xmlReaderForDoc(const xmlChar * cur, const char *URL, const char *encoding, * @options: a combination of xmlParserOption(s) * * parse an XML file from the filesystem or the network. + * The parsing flags @options are a combination of xmlParserOption(s). * * Returns the new reader or NULL in case of error. */ @@ -3608,7 +4019,7 @@ xmlReaderForFile(const char *filename, const char *encoding, int options) reader = xmlNewTextReaderFilename(filename); if (reader == NULL) return (NULL); - xmlTextReaderSetup(reader, NULL, encoding, options); + xmlTextReaderSetup(reader, NULL, NULL, encoding, options); return (reader); } @@ -3621,6 +4032,7 @@ xmlReaderForFile(const char *filename, const char *encoding, int options) * @options: a combination of xmlParserOption(s) * * Create an xmltextReader for an XML in-memory document. + * The parsing flags @options are a combination of xmlParserOption(s). * * Returns the new reader or NULL in case of error. */ @@ -3642,7 +4054,8 @@ xmlReaderForMemory(const char *buffer, int size, const char *URL, xmlFreeParserInputBuffer(buf); return (NULL); } - xmlTextReaderSetup(reader, URL, encoding, options); + reader->allocs |= XML_TEXTREADER_INPUT; + xmlTextReaderSetup(reader, NULL, URL, encoding, options); return (reader); } @@ -3654,6 +4067,7 @@ xmlReaderForMemory(const char *buffer, int size, const char *URL, * @options: a combination of xmlParserOption(s) * * Create an xmltextReader for an XML from a file descriptor. + * The parsing flags @options are a combination of xmlParserOption(s). * * Returns the new reader or NULL in case of error. */ @@ -3674,7 +4088,8 @@ xmlReaderForFd(int fd, const char *URL, const char *encoding, int options) xmlFreeParserInputBuffer(input); return (NULL); } - xmlTextReaderSetup(reader, URL, encoding, options); + reader->allocs |= XML_TEXTREADER_INPUT; + xmlTextReaderSetup(reader, NULL, URL, encoding, options); return (reader); } @@ -3688,6 +4103,7 @@ xmlReaderForFd(int fd, const char *URL, const char *encoding, int options) * @options: a combination of xmlParserOption(s) * * Create an xmltextReader for an XML document from I/O functions and source. + * The parsing flags @options are a combination of xmlParserOption(s). * * Returns the new reader or NULL in case of error. */ @@ -3711,10 +4127,52 @@ xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, xmlFreeParserInputBuffer(input); return (NULL); } - xmlTextReaderSetup(reader, URL, encoding, options); + reader->allocs |= XML_TEXTREADER_INPUT; + xmlTextReaderSetup(reader, NULL, URL, encoding, options); return (reader); } +/** + * xmlReaderNewWalker: + * @reader: an XML reader + * @doc: a preparsed document + * + * Setup an xmltextReader to parse a preparsed XML document. + * This reuses the existing @reader xmlTextReader. + * + * Returns 0 in case of success and -1 in case of error + */ +int +xmlReaderNewWalker(xmlTextReaderPtr reader, xmlDocPtr doc) +{ + if (doc == NULL) + return (-1); + if (reader == NULL) + return (-1); + + if (reader->ctxt != NULL) { + xmlCtxtReset(reader->ctxt); + } + + reader->entNr = 0; + reader->input = NULL; + reader->mode = XML_TEXTREADER_MODE_INITIAL; + reader->node = NULL; + reader->curnode = NULL; + reader->base = 0; + reader->cur = 0; + reader->allocs = XML_TEXTREADER_CTXT; + reader->doc = doc; + reader->state = XML_TEXTREADER_START; + if (reader->dict == NULL) { + if ((reader->ctxt != NULL) && (reader->ctxt->dict != NULL)) + reader->dict = reader->ctxt->dict; + else + reader->dict = xmlDictCreate(); + } + return(0); +} + /** * xmlReaderNewDoc: * @reader: an XML reader @@ -3724,6 +4182,7 @@ xmlReaderForIO(xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, * @options: a combination of xmlParserOption(s) * * Setup an xmltextReader to parse an XML in-memory document. + * The parsing flags @options are a combination of xmlParserOption(s). * This reuses the existing @reader xmlTextReader. * * Returns 0 in case of success and -1 in case of error @@ -3732,21 +4191,17 @@ int xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur, const char *URL, const char *encoding, int options) { - xmlParserInputPtr stream; + + int len; if (cur == NULL) return (-1); - if ((reader == NULL) || (reader->ctxt == NULL)) + if (reader == NULL) return (-1); - xmlCtxtReset(reader->ctxt); - - stream = xmlNewStringInputStream(reader->ctxt, cur); - if (stream == NULL) { - return (-1); - } - inputPush(reader->ctxt, stream); - return (xmlTextReaderSetup(reader, URL, encoding, options)); + len = xmlStrlen(cur); + return (xmlReaderNewMemory(reader, (const char *)cur, len, + URL, encoding, options)); } /** @@ -3757,6 +4212,7 @@ xmlReaderNewDoc(xmlTextReaderPtr reader, const xmlChar * cur, * @options: a combination of xmlParserOption(s) * * parse an XML file from the filesystem or the network. + * The parsing flags @options are a combination of xmlParserOption(s). * This reuses the existing @reader xmlTextReader. * * Returns 0 in case of success and -1 in case of error @@ -3765,21 +4221,19 @@ int xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename, const char *encoding, int options) { - xmlParserInputPtr stream; + xmlParserInputBufferPtr input; if (filename == NULL) return (-1); - if ((reader == NULL) || (reader->ctxt == NULL)) + if (reader == NULL) return (-1); - xmlCtxtReset(reader->ctxt); - - stream = xmlNewInputFromFile(reader->ctxt, filename); - if (stream == NULL) { + input = + xmlParserInputBufferCreateFilename(filename, + XML_CHAR_ENCODING_NONE); + if (input == NULL) return (-1); - } - inputPush(reader->ctxt, stream); - return (xmlTextReaderSetup(reader, NULL, encoding, options)); + return (xmlTextReaderSetup(reader, input, filename, encoding, options)); } /** @@ -3792,6 +4246,7 @@ xmlReaderNewFile(xmlTextReaderPtr reader, const char *filename, * @options: a combination of xmlParserOption(s) * * Setup an xmltextReader to parse an XML in-memory document. + * The parsing flags @options are a combination of xmlParserOption(s). * This reuses the existing @reader xmlTextReader. * * Returns 0 in case of success and -1 in case of error @@ -3801,30 +4256,18 @@ xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size, const char *URL, const char *encoding, int options) { xmlParserInputBufferPtr input; - xmlParserInputPtr stream; - if ((reader == NULL) || (reader->ctxt == NULL)) + if (reader == NULL) return (-1); if (buffer == NULL) return (-1); - xmlCtxtReset(reader->ctxt); - - input = - xmlParserInputBufferCreateMem(buffer, size, + input = xmlParserInputBufferCreateMem(buffer, size, XML_CHAR_ENCODING_NONE); if (input == NULL) { return (-1); } - - stream = xmlNewIOInputStream(reader->ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - return (-1); - } - - inputPush(reader->ctxt, stream); - return (xmlTextReaderSetup(reader, URL, encoding, options)); + return (xmlTextReaderSetup(reader, input, URL, encoding, options)); } /** @@ -3836,6 +4279,7 @@ xmlReaderNewMemory(xmlTextReaderPtr reader, const char *buffer, int size, * @options: a combination of xmlParserOption(s) * * Setup an xmltextReader to parse an XML from a file descriptor. + * The parsing flags @options are a combination of xmlParserOption(s). * This reuses the existing @reader xmlTextReader. * * Returns 0 in case of success and -1 in case of error @@ -3845,26 +4289,16 @@ xmlReaderNewFd(xmlTextReaderPtr reader, int fd, const char *URL, const char *encoding, int options) { xmlParserInputBufferPtr input; - xmlParserInputPtr stream; if (fd < 0) return (-1); - if ((reader == NULL) || (reader->ctxt == NULL)) + if (reader == NULL) return (-1); - xmlCtxtReset(reader->ctxt); - - input = xmlParserInputBufferCreateFd(fd, XML_CHAR_ENCODING_NONE); if (input == NULL) return (-1); - stream = xmlNewIOInputStream(reader->ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - return (-1); - } - inputPush(reader->ctxt, stream); - return (xmlTextReaderSetup(reader, URL, encoding, options)); + return (xmlTextReaderSetup(reader, input, URL, encoding, options)); } /** @@ -3879,6 +4313,7 @@ xmlReaderNewFd(xmlTextReaderPtr reader, int fd, * * Setup an xmltextReader to parse an XML document from I/O functions * and source. + * The parsing flags @options are a combination of xmlParserOption(s). * This reuses the existing @reader xmlTextReader. * * Returns 0 in case of success and -1 in case of error @@ -3889,26 +4324,17 @@ xmlReaderNewIO(xmlTextReaderPtr reader, xmlInputReadCallback ioread, const char *URL, const char *encoding, int options) { xmlParserInputBufferPtr input; - xmlParserInputPtr stream; if (ioread == NULL) return (-1); - if ((reader == NULL) || (reader->ctxt == NULL)) + if (reader == NULL) return (-1); - xmlCtxtReset(reader->ctxt); - input = xmlParserInputBufferCreateIO(ioread, ioclose, ioctx, XML_CHAR_ENCODING_NONE); if (input == NULL) return (-1); - stream = xmlNewIOInputStream(reader->ctxt, input, XML_CHAR_ENCODING_NONE); - if (stream == NULL) { - xmlFreeParserInputBuffer(input); - return (-1); - } - inputPush(reader->ctxt, stream); - return (xmlTextReaderSetup(reader, URL, encoding, options)); + return (xmlTextReaderSetup(reader, input, URL, encoding, options)); } /************************************************************************ * *