added the close and getattribute methods of XmlTextReader. added the

* xmlreader.c doc/libxml2-api.xml: added the close and getattribute
  methods of XmlTextReader.
* python/generator.py python/libxml_wrap.h python/types.c
  python/libxml2class.txt: added the reader to the Python bindings
* python/tests/Makefile.am python/tests/reader.py: added a specific
  test for the Python bindings of the Reader APIs
* parser.c: small cleanup.
Daniel
This commit is contained in:
Daniel Veillard 2002-12-14 23:00:35 +00:00
parent 7ef0fcb8a8
commit 0eb38c7259
11 changed files with 394 additions and 5 deletions

View File

@ -1,3 +1,13 @@
Sat Dec 14 23:57:39 CET 2002 Daniel Veillard <daniel@veillard.com>
* xmlreader.c doc/libxml2-api.xml: added the close and getattribute
methods of XmlTextReader.
* python/generator.py python/libxml_wrap.h python/types.c
python/libxml2class.txt: added the reader to the Python bindings
* python/tests/Makefile.am python/tests/reader.py: added a specific
test for the Python bindings of the Reader APIs
* parser.c: small cleanup.
Fri Dec 13 11:39:44 CET 2002 Daniel Veillard <daniel@veillard.com>
* xinclude.c: fallback was only copying the first child not the

View File

@ -1093,7 +1093,11 @@
<exports symbol='xmlTextReader'/>
<exports symbol='xmlTextReaderAttributeCount'/>
<exports symbol='xmlTextReaderBaseUri'/>
<exports symbol='xmlTextReaderClose'/>
<exports symbol='xmlTextReaderDepth'/>
<exports symbol='xmlTextReaderGetAttribute'/>
<exports symbol='xmlTextReaderGetAttributeNo'/>
<exports symbol='xmlTextReaderGetAttributeNs'/>
<exports symbol='xmlTextReaderHasAttributes'/>
<exports symbol='xmlTextReaderHasValue'/>
<exports symbol='xmlTextReaderIsDefault'/>
@ -7876,11 +7880,35 @@ actually an xmlCharEncoding'/>
<return type='xmlChar *' info='the base URI or NULL if not available'/>
<arg name='reader' type='xmlTextReaderPtr' info='the xmlTextReaderPtr used'/>
</function>
<function name='xmlTextReaderClose' file='xmlreader'>
<info>This method releases any resources allocated by the current instance changes the state to Closed and close any underlying input.</info>
<return type='int' info='0 or -1 in case of error'/>
<arg name='reader' type='xmlTextReaderPtr' info='the xmlTextReaderPtr used'/>
</function>
<function name='xmlTextReaderDepth' file='xmlreader'>
<info>The depth of the node in the tree.</info>
<return type='int' info='the depth or -1 in case of error'/>
<arg name='reader' type='xmlTextReaderPtr' info='the xmlTextReaderPtr used'/>
</function>
<function name='xmlTextReaderGetAttribute' file='xmlreader'>
<info>Provides the value of the attribute with the specified qualified name.</info>
<return type='xmlChar *' info='a string containing the value of the specified attribute, or NULL in case of error. The string must be deallocated by the caller.'/>
<arg name='reader' type='xmlTextReaderPtr' info='the xmlTextReaderPtr used'/>
<arg name='name' type='const xmlChar *' info='the qualified name of the attribute.'/>
</function>
<function name='xmlTextReaderGetAttributeNo' file='xmlreader'>
<info>Provides the value of the attribute with the specified index relative to the containing element.</info>
<return type='xmlChar *' info='a string containing the value of the specified attribute, or NULL in case of error. The string must be deallocated by the caller.'/>
<arg name='reader' type='xmlTextReaderPtr' info='the xmlTextReaderPtr used'/>
<arg name='no' type='int' info='the zero-based index of the attribute relative to the containing element'/>
</function>
<function name='xmlTextReaderGetAttributeNs' file='xmlreader'>
<info>Provides the value of the specified attribute</info>
<return type='xmlChar *' info='a string containing the value of the specified attribute, or NULL in case of error. The string must be deallocated by the caller.'/>
<arg name='reader' type='xmlTextReaderPtr' info='the xmlTextReaderPtr used'/>
<arg name='localName' type='const xmlChar *' info='the local name of the attribute.'/>
<arg name='namespaceURI' type='const xmlChar *' info='the namespace URI of the attribute.'/>
</function>
<function name='xmlTextReaderHasAttributes' file='xmlreader'>
<info>Whether the node has attributes.</info>
<return type='int' info='1 if true, 0 if false, and -1 in case or error'/>

View File

@ -49,6 +49,18 @@ xmlChar * xmlTextReaderPrefix (xmlTextReaderPtr reader);
int xmlTextReaderQuoteChar (xmlTextReaderPtr reader);
xmlChar * xmlTextReaderValue (xmlTextReaderPtr reader);
xmlChar * xmlTextReaderXmlLang (xmlTextReaderPtr reader);
/*
* Methods of the XmlTextReader
*/
int xmlTextReaderClose (xmlTextReaderPtr reader);
xmlChar * xmlTextReaderGetAttributeNo (xmlTextReaderPtr reader,
int no);
xmlChar * xmlTextReaderGetAttribute (xmlTextReaderPtr reader,
const xmlChar *name);
xmlChar * xmlTextReaderGetAttributeNs (xmlTextReaderPtr reader,
const xmlChar *localName,
const xmlChar *namespaceURI);
#ifdef __cplusplus
}
#endif

View File

@ -1769,7 +1769,8 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
int first = CUR_SCHAR(cur, l);
if (!IS_LETTER(first) && (first != '_')) {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
if ((ctxt != NULL) && (ctxt->sax != NULL) &&
(ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"Name %s is not XML Namespace compliant\n",
name);
@ -1790,7 +1791,8 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
buffer = (xmlChar *) xmlMalloc(max * sizeof(xmlChar));
if (buffer == NULL) {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
if ((ctxt != NULL) && (ctxt->sax != NULL) &&
(ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlSplitQName: out of memory\n");
return(NULL);
@ -1802,7 +1804,8 @@ xmlSplitQName(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix) {
buffer = (xmlChar *) xmlRealloc(buffer,
max * sizeof(xmlChar));
if (buffer == NULL) {
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL))
if ((ctxt != NULL) && (ctxt->sax != NULL) &&
(ctxt->sax->error != NULL))
ctxt->sax->error(ctxt->userData,
"xmlSplitQName: out of memory\n");
return(NULL);

View File

@ -271,6 +271,7 @@ py_types = {
'xmlOutputBufferPtr': ('O', "outputBuffer", "xmlOutputBufferPtr", "xmlOutputBufferPtr"),
'xmlParserInputBufferPtr': ('O', "inputBuffer", "xmlParserInputBufferPtr", "xmlParserInputBufferPtr"),
'xmlRegexpPtr': ('O', "xmlReg", "xmlRegexpPtr", "xmlRegexpPtr"),
'xmlTextReaderPtr': ('O', "xmlTextReader", "xmlTextReaderPtr", "xmlTextReaderPtr"),
}
py_return_types = {
@ -597,6 +598,7 @@ classes_type = {
"xmlOutputBufferPtr": ("._o", "outputBuffer(_obj=%s)", "outputBuffer"),
"xmlParserInputBufferPtr": ("._o", "inputBuffer(_obj=%s)", "inputBuffer"),
"xmlRegexpPtr": ("._o", "xmlReg(_obj=%s)", "xmlReg"),
"xmlTextReaderPtr": ("._o", "xmlTextReader(_obj=%s)", "xmlTextReader"),
}
converter_type = {
@ -624,6 +626,7 @@ classes_destructors = {
# "outputBuffer": "xmlOutputBufferClose",
"inputBuffer": "xmlFreeParserInputBuffer",
"xmlReg": "xmlRegFreeRegexp",
"xmlTextReader": "xmlFreeTextReader",
}
functions_noexcept = {
@ -676,6 +679,9 @@ def nameFixup(name, classe, type, file):
func = "regexp" + name[9:]
elif name[0:6] == "xmlReg" and file == "xmlregexp":
func = "regexp" + name[6:]
elif name[0:13] == "xmlTextReader" and file == "xmlreader":
func = name[13:]
func = string.lower(func[0:1]) + func[1:]
elif name[0:11] == "xmlACatalog":
func = name[11:]
func = string.lower(func[0:1]) + func[1:]

View File

@ -165,6 +165,9 @@ registerDefaultInputCallbacks()
registerDefaultOutputCallbacks()
registerHTTPPostCallbacks()
# functions from module xmlreader
newTextReaderFilename()
# functions from module xmlregexp
regexpCompile()
@ -556,6 +559,30 @@ Class xmlAttr(xmlNode)
freeProp()
freePropList()
removeProp()
Class xmlTextReader()
# functions from module xmlreader
attributeCount()
baseUri()
close()
depth()
freeTextReader()
getAttribute()
getAttributeNo()
getAttributeNs()
hasAttributes()
hasValue()
isDefault()
isEmptyElement()
localName()
name()
namespaceUri()
nodeType()
prefix()
quoteChar()
read()
value()
xmlLang()
Class xmlReg()
# functions from module xmlregexp
@ -731,6 +758,9 @@ Class inputBuffer(ioReadWrapper)
push()
read()
# functions from module xmlreader
newTextReader()
Class outputBuffer(ioWriteWrapper)

View File

@ -17,6 +17,26 @@
#include <libxml/xmlunicode.h>
#include <libxml/xmlregexp.h>
#include <libxml/xmlautomata.h>
#include <libxml/xmlreader.h>
/**
* ATTRIBUTE_UNUSED:
*
* Macro used to signal to GCC unused function parameters
* Repeated here since the definition is not available when
* compiled outside the libxml2 build tree.
*/
#ifdef __GNUC__
#ifdef ATTRIBUTE_UNUSED
#undef ATTRIBUTE_UNUSED
#endif
#include <ansidecl.h>
#ifndef ATTRIBUTE_UNUSED
#define ATTRIBUTE_UNUSED
#endif
#else
#define ATTRIBUTE_UNUSED
#endif
#define PyxmlNode_Get(v) (((v) == Py_None) ? NULL : \
(((PyxmlNode_Object *)(v))->obj))
@ -66,6 +86,14 @@ typedef struct {
xmlRegexpPtr obj;
} PyxmlReg_Object;
#define PyxmlTextReader_Get(v) (((v) == Py_None) ? NULL : \
(((PyxmlTextReader_Object *)(v))->obj))
typedef struct {
PyObject_HEAD
xmlTextReaderPtr obj;
} PyxmlTextReader_Object;
#define PyURI_Get(v) (((v) == Py_None) ? NULL : \
(((PyURI_Object *)(v))->obj))
@ -119,5 +147,6 @@ PyObject * libxml_xmlURIPtrWrap(xmlURIPtr uri);
PyObject * libxml_xmlOutputBufferPtrWrap(xmlOutputBufferPtr buffer);
PyObject * libxml_xmlParserInputBufferPtrWrap(xmlParserInputBufferPtr buffer);
PyObject * libxml_xmlRegexpPtrWrap(xmlRegexpPtr regexp);
PyObject * libxml_xmlTextReaderPtrWrap(xmlTextReaderPtr reader);
xmlXPathObjectPtr libxml_xmlXPathObjectPtrConvert(PyObject * obj);

View File

@ -19,7 +19,8 @@ PYTESTS= \
outbuf.py \
inbuf.py \
resolver.py \
regexp.py
regexp.py \
reader.py
XMLS= \
tst.xml \

94
python/tests/reader.py Executable file
View File

@ -0,0 +1,94 @@
#!/usr/bin/python -u
import libxml2
import StringIO
import sys
# Memory debug specific
libxml2.debugMemory(1)
f = StringIO.StringIO("""<a><b b1="b1"/><c>content of c</c></a>""")
input = libxml2.inputBuffer(f)
reader = input.newTextReader()
ret = reader.read()
if ret != 1:
print "Error reading to first element"
sys.exit(1)
if reader.name() != "a" or reader.isEmptyElement() != 0 or \
reader.nodeType() != 1 or reader.hasAttributes() != 0:
print "Error reading the first element"
sys.exit(1)
ret = reader.read()
if ret != 1:
print "Error reading to second element"
sys.exit(1)
if reader.name() != "b" or reader.isEmptyElement() != 1 or \
reader.nodeType() != 1 or reader.hasAttributes() != 1:
print "Error reading the second element"
sys.exit(1)
ret = reader.read()
if ret != 1:
print "Error reading to third element"
sys.exit(1)
if reader.name() != "c" or reader.isEmptyElement() != 0 or \
reader.nodeType() != 1 or reader.hasAttributes() != 0:
print "Error reading the third element"
sys.exit(1)
ret = reader.read()
if ret != 1:
print "Error reading to text node"
sys.exit(1)
if reader.name() != "#text" or reader.isEmptyElement() != 0 or \
reader.nodeType() != 3 or reader.hasAttributes() != 0 or \
reader.value() != "content of c":
print "Error reading the text node"
sys.exit(1)
ret = reader.read()
if ret != 1:
print "Error reading to end of third element"
sys.exit(1)
if reader.name() != "c" or reader.isEmptyElement() != 0 or \
reader.nodeType() != 15 or reader.hasAttributes() != 0:
print "Error reading the end of third element"
sys.exit(1)
ret = reader.read()
if ret != 1:
print "Error reading to end of first element"
sys.exit(1)
if reader.name() != "a" or reader.isEmptyElement() != 0 or \
reader.nodeType() != 15 or reader.hasAttributes() != 0:
print "Error reading the end of first element"
sys.exit(1)
ret = reader.read()
if ret != 0:
print "Error reading to end of document"
sys.exit(1)
#
# example from the XmlTextReader docs
#
f = StringIO.StringIO("""<test xmlns:dt="urn:datatypes" dt:type="int"/>""")
input = libxml2.inputBuffer(f)
reader = input.newTextReader()
ret = reader.read()
if ret != 1:
print "Error reading test element"
sys.exit(1)
if reader.getAttributeNo(0) != "urn:datatypes" or \
reader.getAttributeNo(1) != "int" or \
reader.getAttributeNs("type", "urn:datatypes") != "int" or \
reader.getAttribute("dt:type") != "int":
print "error reading test attributes"
sys.exit(1)
del f
del input
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()

View File

@ -547,3 +547,21 @@ libxml_xmlRegexpPtrWrap(xmlRegexpPtr regexp)
(char *) "xmlRegexpPtr", NULL);
return (ret);
}
PyObject *
libxml_xmlTextReaderPtrWrap(xmlTextReaderPtr reader)
{
PyObject *ret;
#ifdef DEBUG
printf("libxml_xmlTextReaderPtrWrap: reader = %p\n", reader);
#endif
if (reader == NULL) {
Py_INCREF(Py_None);
return (Py_None);
}
ret =
PyCObject_FromVoidPtrAndDesc((void *) reader,
(char *) "xmlTextReaderPtr", NULL);
return (ret);
}

View File

@ -53,7 +53,8 @@
typedef enum {
XML_TEXTREADER_MODE_NORMAL = 0,
XML_TEXTREADER_MODE_EOF = 1
XML_TEXTREADER_MODE_EOF = 1,
XML_TEXTREADER_MODE_CLOSED = 1
} xmlTextReaderMode;
typedef enum {
@ -473,6 +474,163 @@ xmlFreeTextReader(xmlTextReaderPtr reader) {
xmlFree(reader);
}
/************************************************************************
* *
* Methods for XmlTextReader *
* *
************************************************************************/
/**
* xmlTextReaderClose:
* @reader: the xmlTextReaderPtr used
*
* This method releases any resources allocated by the current instance
* changes the state to Closed and close any underlying input.
*
* Returns 0 or -1 in case of error
*/
int
xmlTextReaderClose(xmlTextReaderPtr reader) {
if (reader == NULL)
return(-1);
reader->node = NULL;
reader->mode = XML_TEXTREADER_MODE_CLOSED;
if (reader->ctxt != NULL) {
if (reader->ctxt->myDoc != NULL) {
xmlFreeDoc(reader->ctxt->myDoc);
reader->ctxt->myDoc = NULL;
}
if (reader->allocs & XML_TEXTREADER_CTXT) {
xmlFreeParserCtxt(reader->ctxt);
reader->allocs -= XML_TEXTREADER_CTXT;
}
}
if (reader->sax != NULL) {
xmlFree(reader->sax);
reader->sax = NULL;
}
if ((reader->input != NULL) && (reader->allocs & XML_TEXTREADER_INPUT)) {
xmlFreeParserInputBuffer(reader->input);
reader->allocs -= XML_TEXTREADER_INPUT;
}
return(0);
}
/**
* xmlTextReaderGetAttributeNo:
* @reader: the xmlTextReaderPtr used
* @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 *
xmlTextReaderGetAttributeNo(xmlTextReaderPtr reader, int no) {
xmlChar *ret;
int i;
xmlAttrPtr cur;
xmlNsPtr ns;
if (reader == NULL)
return(NULL);
if (reader->node == NULL)
return(NULL);
/* TODO: handle the xmlDecl */
if (reader->node->type != XML_ELEMENT_NODE)
return(NULL);
ns = reader->node->nsDef;
for (i = 0;(i < no) && (ns != NULL);i++) {
ns = ns->next;
}
if (ns != NULL)
return(xmlStrdup(ns->href));
cur = reader->node->properties;
if (cur == NULL)
return(NULL);
for (;i < no;i++) {
cur = cur->next;
if (cur == NULL)
return(NULL);
}
/* TODO walk the DTD if present */
ret = xmlNodeListGetString(reader->node->doc, cur->children, 1);
if (ret == NULL) return(xmlStrdup((xmlChar *)""));
return(ret);
}
/**
* xmlTextReaderGetAttribute:
* @reader: the xmlTextReaderPtr used
* @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 *
xmlTextReaderGetAttribute(xmlTextReaderPtr reader, const xmlChar *name) {
xmlChar *prefix = NULL;
xmlChar *localname;
xmlNsPtr ns;
xmlChar *ret = NULL;
if ((reader == NULL) || (name == NULL))
return(NULL);
if (reader->node == NULL)
return(NULL);
/* TODO: handle the xmlDecl */
if (reader->node->type != XML_ELEMENT_NODE)
return(NULL);
localname = xmlSplitQName2(name, &prefix);
if (localname == NULL)
return(xmlGetProp(reader->node, name));
ns = xmlSearchNs(reader->node->doc, reader->node, prefix);
if (ns != NULL)
ret = xmlGetNsProp(reader->node, localname, ns->href);
if (localname != NULL)
xmlFree(localname);
if (prefix != NULL)
xmlFree(prefix);
return(ret);
}
/**
* xmlTextReaderGetAttributeNs:
* @reader: the xmlTextReaderPtr used
* @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 *
xmlTextReaderGetAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName,
const xmlChar *namespaceURI) {
if ((reader == NULL) || (localName == NULL))
return(NULL);
if (reader->node == NULL)
return(NULL);
/* TODO: handle the xmlDecl */
if (reader->node->type != XML_ELEMENT_NODE)
return(NULL);
return(xmlGetNsProp(reader->node, localName, namespaceURI));
}
/************************************************************************
* *
* Acces API to the current node *