generated from sethub/template
[libxml2]Add libxml2 library
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
/gen_prog
|
||||
/libxml2-export.c
|
||||
/libxml2-py.c
|
||||
/libxml2-py.h
|
||||
/libxml2.py
|
||||
/setup.py
|
||||
/tests/tmp.xml
|
||||
@@ -0,0 +1,48 @@
|
||||
# Makefile for libxml2 python library
|
||||
|
||||
# We use a rule with multiple output files which creates problems with
|
||||
# parallel builds.
|
||||
.NOTPARALLEL:
|
||||
|
||||
SUBDIRS = . tests
|
||||
|
||||
EXTRA_DIST = \
|
||||
generator.py \
|
||||
libxml.py \
|
||||
pyproject.toml \
|
||||
meson.build
|
||||
|
||||
if WITH_PYTHON
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_builddir)/include \
|
||||
-I$(top_srcdir)/include \
|
||||
$(PYTHON_CFLAGS)
|
||||
|
||||
pyexec_LTLIBRARIES = libxml2mod.la
|
||||
|
||||
libxml2mod_la_SOURCES = libxml.c libxml_wrap.h types.c
|
||||
nodist_libxml2mod_la_SOURCES = libxml2-py.h libxml2-py.c
|
||||
libxml2mod_la_LDFLAGS = $(AM_LDFLAGS) $(PYTHON_LDFLAGS) -module -avoid-version
|
||||
libxml2mod_la_LIBADD = $(top_builddir)/libxml2.la $(PYTHON_LIBS)
|
||||
|
||||
BUILT_SOURCES = libxml2-export.c libxml2-py.h libxml2-py.c
|
||||
|
||||
python_PYTHON = drv_libxml2.py
|
||||
nodist_python_PYTHON = libxml2.py
|
||||
|
||||
API_DESC = ../doc/html.stamp
|
||||
GENERATED = libxml2.py $(BUILT_SOURCES)
|
||||
CLEANFILES = $(GENERATED)
|
||||
|
||||
all-local: libxml2.py
|
||||
|
||||
$(GENERATED): $(srcdir)/generator.py $(API_DESC)
|
||||
$(PYTHON) $(srcdir)/generator.py $(builddir)
|
||||
|
||||
# libxml.c #includes libxml2-export.c
|
||||
libxml.$(OBJEXT): libxml2-export.c
|
||||
|
||||
clean-local:
|
||||
rm -rf __pycache__ *.pyc
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,37 @@
|
||||
Module libxml2-python
|
||||
=====================
|
||||
|
||||
DEPRECATION WARNING: It is planned to remove the libxml2 Python
|
||||
bindings from the libxml2 repo.
|
||||
|
||||
This is the libxml2 python module, providing access to the
|
||||
libxml2 and libxslt (if available) libraries. For general
|
||||
informationss on those XML and XSLT libraries check their
|
||||
web pages at:
|
||||
https://gitlab.gnome.org/GNOME/libxml2/-/wikis/home
|
||||
and
|
||||
https://gitlab.gnome.org/GNOME/libxslt/-/wikis/home
|
||||
|
||||
The latest version of the sources for this module and the
|
||||
associated libraries can be found at:
|
||||
https://gitlab.gnome.org/GNOME/libxml2/-/releases
|
||||
|
||||
Binaries packages of the libxml2 and libxslt libraries can
|
||||
be found either on the FTP site for Linux, from external
|
||||
sources linked from the web pages, or as part of your set of
|
||||
packages provided with your operating system.
|
||||
|
||||
NOTE:
|
||||
this module distribution is not the primary distribution
|
||||
of the libxml2 and libxslt Python binding code, but as
|
||||
the Python way of packaging those for non-Linux systems.
|
||||
The main sources are the libxml2 and libxslt tar.gz found on
|
||||
the site. One side effect is that the official RPM packages for
|
||||
those modules are not generated from the libxml2-python
|
||||
distributions but as part of the normal RPM packaging of
|
||||
those two libraries.
|
||||
The RPM packages can be found at:
|
||||
http://rpmfind.net/linux/rpm2html/search.php?query=libxml2-python
|
||||
http://rpmfind.net/linux/rpm2html/search.php?query=libxslt-python
|
||||
|
||||
Daniel Veillard
|
||||
@@ -0,0 +1,382 @@
|
||||
# -*- coding: iso-8859-1 -*-
|
||||
""" A SAX2 driver for libxml2, on top of it's XmlReader API
|
||||
|
||||
USAGE
|
||||
# put this file (drv_libxml2.py) in PYTHONPATH
|
||||
import xml.sax
|
||||
reader = xml.sax.make_parser(["drv_libxml2"])
|
||||
# ...and the rest is standard python sax.
|
||||
|
||||
CAVEATS
|
||||
- Lexical handlers are supported, except for start/endEntity
|
||||
(waiting for XmlReader.ResolveEntity) and start/endDTD
|
||||
- Error callbacks are not exactly synchronous, they tend
|
||||
to be invoked before the corresponding content callback,
|
||||
because the underlying reader interface parses
|
||||
data by chunks of 512 bytes
|
||||
|
||||
TODO
|
||||
- search for TODO
|
||||
- some ErrorHandler events (warning)
|
||||
- some ContentHandler events (setDocumentLocator, skippedEntity)
|
||||
- EntityResolver (using libxml2.?)
|
||||
- DTDHandler (if/when libxml2 exposes such node types)
|
||||
- DeclHandler (if/when libxml2 exposes such node types)
|
||||
- property_xml_string?
|
||||
- feature_string_interning?
|
||||
- Incremental parser
|
||||
- additional performance tuning:
|
||||
- one might cache callbacks to avoid some name lookups
|
||||
- one might implement a smarter way to pass attributes to startElement
|
||||
(some kind of lazy evaluation?)
|
||||
- there might be room for improvement in start/endPrefixMapping
|
||||
- other?
|
||||
|
||||
"""
|
||||
|
||||
__author__ = "Stéphane Bidoul <sbi@skynet.be>"
|
||||
__version__ = "0.3"
|
||||
|
||||
import sys
|
||||
import codecs
|
||||
|
||||
if sys.version_info[0] < 3:
|
||||
__author__ = codecs.unicode_escape_decode(__author__)[0]
|
||||
|
||||
StringTypes = (str, unicode)
|
||||
# libxml2 returns strings as UTF8
|
||||
_decoder = codecs.lookup("utf8")[1]
|
||||
def _d(s):
|
||||
if s is None:
|
||||
return s
|
||||
else:
|
||||
return _decoder(s)[0]
|
||||
else:
|
||||
StringTypes = str
|
||||
# s is Unicode `str` already
|
||||
def _d(s):
|
||||
return s
|
||||
|
||||
from xml.sax._exceptions import *
|
||||
from xml.sax import xmlreader, saxutils
|
||||
from xml.sax.handler import \
|
||||
feature_namespaces, \
|
||||
feature_namespace_prefixes, \
|
||||
feature_string_interning, \
|
||||
feature_validation, \
|
||||
feature_external_ges, \
|
||||
feature_external_pes, \
|
||||
property_lexical_handler, \
|
||||
property_declaration_handler, \
|
||||
property_dom_node, \
|
||||
property_xml_string
|
||||
|
||||
try:
|
||||
import libxml2
|
||||
except ImportError:
|
||||
raise SAXReaderNotAvailable("libxml2 not available: " \
|
||||
"import error was: %s" % sys.exc_info()[1])
|
||||
|
||||
class Locator(xmlreader.Locator):
|
||||
"""SAX Locator adapter for libxml2.xmlTextReaderLocator"""
|
||||
|
||||
def __init__(self,locator):
|
||||
self.__locator = locator
|
||||
|
||||
def getColumnNumber(self):
|
||||
"Return the column number where the current event ends."
|
||||
return -1
|
||||
|
||||
def getLineNumber(self):
|
||||
"Return the line number where the current event ends."
|
||||
return self.__locator.LineNumber()
|
||||
|
||||
def getPublicId(self):
|
||||
"Return the public identifier for the current event."
|
||||
return None
|
||||
|
||||
def getSystemId(self):
|
||||
"Return the system identifier for the current event."
|
||||
return self.__locator.BaseURI()
|
||||
|
||||
class LibXml2Reader(xmlreader.XMLReader):
|
||||
|
||||
def __init__(self):
|
||||
xmlreader.XMLReader.__init__(self)
|
||||
# features
|
||||
self.__ns = 0
|
||||
self.__nspfx = 0
|
||||
self.__validate = 0
|
||||
self.__extparams = 1
|
||||
# parsing flag
|
||||
self.__parsing = 0
|
||||
# additional handlers
|
||||
self.__lex_handler = None
|
||||
self.__decl_handler = None
|
||||
# error messages accumulator
|
||||
self.__errors = None
|
||||
|
||||
def _errorHandler(self,arg,msg,severity,locator):
|
||||
if self.__errors is None:
|
||||
self.__errors = []
|
||||
self.__errors.append((severity,
|
||||
SAXParseException(msg,None,
|
||||
Locator(locator))))
|
||||
|
||||
def _reportErrors(self,fatal):
|
||||
for severity,exception in self.__errors:
|
||||
if severity in (libxml2.PARSER_SEVERITY_VALIDITY_WARNING,
|
||||
libxml2.PARSER_SEVERITY_WARNING):
|
||||
self._err_handler.warning(exception)
|
||||
else:
|
||||
# when fatal is set, the parse will stop;
|
||||
# we consider that the last error reported
|
||||
# is the fatal one.
|
||||
if fatal and exception is self.__errors[-1][1]:
|
||||
self._err_handler.fatalError(exception)
|
||||
else:
|
||||
self._err_handler.error(exception)
|
||||
self.__errors = None
|
||||
|
||||
def parse(self, source):
|
||||
self.__parsing = 1
|
||||
try:
|
||||
# prepare source and create reader
|
||||
if isinstance(source, StringTypes):
|
||||
reader = libxml2.newTextReaderFilename(source)
|
||||
else:
|
||||
source = saxutils.prepare_input_source(source)
|
||||
stream = source.getCharacterStream()
|
||||
if stream is None:
|
||||
stream = source.getByteStream()
|
||||
input = libxml2.inputBuffer(stream)
|
||||
reader = input.newTextReader(source.getSystemId())
|
||||
reader.SetErrorHandler(self._errorHandler,None)
|
||||
# configure reader
|
||||
if self.__extparams:
|
||||
reader.SetParserProp(libxml2.PARSER_LOADDTD,1)
|
||||
reader.SetParserProp(libxml2.PARSER_DEFAULTATTRS,1)
|
||||
reader.SetParserProp(libxml2.PARSER_SUBST_ENTITIES,1)
|
||||
reader.SetParserProp(libxml2.PARSER_VALIDATE,self.__validate)
|
||||
else:
|
||||
reader.SetParserProp(libxml2.PARSER_LOADDTD, 0)
|
||||
# we reuse attribute maps (for a slight performance gain)
|
||||
if self.__ns:
|
||||
attributesNSImpl = xmlreader.AttributesNSImpl({},{})
|
||||
else:
|
||||
attributesImpl = xmlreader.AttributesImpl({})
|
||||
# prefixes to pop (for endPrefixMapping)
|
||||
prefixes = []
|
||||
# start loop
|
||||
self._cont_handler.startDocument()
|
||||
while 1:
|
||||
r = reader.Read()
|
||||
# check for errors
|
||||
if r == 1:
|
||||
if not self.__errors is None:
|
||||
self._reportErrors(0)
|
||||
elif r == 0:
|
||||
if not self.__errors is None:
|
||||
self._reportErrors(0)
|
||||
break # end of parse
|
||||
else:
|
||||
if not self.__errors is None:
|
||||
self._reportErrors(1)
|
||||
else:
|
||||
self._err_handler.fatalError(\
|
||||
SAXException("Read failed (no details available)"))
|
||||
break # fatal parse error
|
||||
# get node type
|
||||
nodeType = reader.NodeType()
|
||||
# Element
|
||||
if nodeType == 1:
|
||||
if self.__ns:
|
||||
eltName = (_d(reader.NamespaceUri()),\
|
||||
_d(reader.LocalName()))
|
||||
eltQName = _d(reader.Name())
|
||||
attributesNSImpl._attrs = attrs = {}
|
||||
attributesNSImpl._qnames = qnames = {}
|
||||
newPrefixes = []
|
||||
while reader.MoveToNextAttribute():
|
||||
qname = _d(reader.Name())
|
||||
value = _d(reader.Value())
|
||||
if qname.startswith("xmlns"):
|
||||
if len(qname) > 5:
|
||||
newPrefix = qname[6:]
|
||||
else:
|
||||
newPrefix = None
|
||||
newPrefixes.append(newPrefix)
|
||||
self._cont_handler.startPrefixMapping(\
|
||||
newPrefix,value)
|
||||
if not self.__nspfx:
|
||||
continue # don't report xmlns attribute
|
||||
attName = (_d(reader.NamespaceUri()),
|
||||
_d(reader.LocalName()))
|
||||
qnames[attName] = qname
|
||||
attrs[attName] = value
|
||||
reader.MoveToElement()
|
||||
self._cont_handler.startElementNS( \
|
||||
eltName,eltQName,attributesNSImpl)
|
||||
if reader.IsEmptyElement():
|
||||
self._cont_handler.endElementNS(eltName,eltQName)
|
||||
for newPrefix in newPrefixes:
|
||||
self._cont_handler.endPrefixMapping(newPrefix)
|
||||
else:
|
||||
prefixes.append(newPrefixes)
|
||||
else:
|
||||
eltName = _d(reader.Name())
|
||||
attributesImpl._attrs = attrs = {}
|
||||
while reader.MoveToNextAttribute():
|
||||
attName = _d(reader.Name())
|
||||
attrs[attName] = _d(reader.Value())
|
||||
reader.MoveToElement()
|
||||
self._cont_handler.startElement( \
|
||||
eltName,attributesImpl)
|
||||
if reader.IsEmptyElement():
|
||||
self._cont_handler.endElement(eltName)
|
||||
# EndElement
|
||||
elif nodeType == 15:
|
||||
if self.__ns:
|
||||
self._cont_handler.endElementNS( \
|
||||
(_d(reader.NamespaceUri()),_d(reader.LocalName())),
|
||||
_d(reader.Name()))
|
||||
for prefix in prefixes.pop():
|
||||
self._cont_handler.endPrefixMapping(prefix)
|
||||
else:
|
||||
self._cont_handler.endElement(_d(reader.Name()))
|
||||
# Text
|
||||
elif nodeType == 3:
|
||||
self._cont_handler.characters(_d(reader.Value()))
|
||||
# Whitespace
|
||||
elif nodeType == 13:
|
||||
self._cont_handler.ignorableWhitespace(_d(reader.Value()))
|
||||
# SignificantWhitespace
|
||||
elif nodeType == 14:
|
||||
self._cont_handler.characters(_d(reader.Value()))
|
||||
# CDATA
|
||||
elif nodeType == 4:
|
||||
if not self.__lex_handler is None:
|
||||
self.__lex_handler.startCDATA()
|
||||
self._cont_handler.characters(_d(reader.Value()))
|
||||
if not self.__lex_handler is None:
|
||||
self.__lex_handler.endCDATA()
|
||||
# EntityReference
|
||||
elif nodeType == 5:
|
||||
if not self.__lex_handler is None:
|
||||
self.startEntity(_d(reader.Name()))
|
||||
reader.ResolveEntity()
|
||||
# EndEntity
|
||||
elif nodeType == 16:
|
||||
if not self.__lex_handler is None:
|
||||
self.endEntity(_d(reader.Name()))
|
||||
# ProcessingInstruction
|
||||
elif nodeType == 7:
|
||||
self._cont_handler.processingInstruction( \
|
||||
_d(reader.Name()),_d(reader.Value()))
|
||||
# Comment
|
||||
elif nodeType == 8:
|
||||
if not self.__lex_handler is None:
|
||||
self.__lex_handler.comment(_d(reader.Value()))
|
||||
# DocumentType
|
||||
elif nodeType == 10:
|
||||
#if not self.__lex_handler is None:
|
||||
# self.__lex_handler.startDTD()
|
||||
pass # TODO (how to detect endDTD? on first non-dtd event?)
|
||||
# XmlDeclaration
|
||||
elif nodeType == 17:
|
||||
pass # TODO
|
||||
# Entity
|
||||
elif nodeType == 6:
|
||||
pass # TODO (entity decl)
|
||||
# Notation (decl)
|
||||
elif nodeType == 12:
|
||||
pass # TODO
|
||||
# Attribute (never in this loop)
|
||||
#elif nodeType == 2:
|
||||
# pass
|
||||
# Document (not exposed)
|
||||
#elif nodeType == 9:
|
||||
# pass
|
||||
# DocumentFragment (never returned by XmlReader)
|
||||
#elif nodeType == 11:
|
||||
# pass
|
||||
# None
|
||||
#elif nodeType == 0:
|
||||
# pass
|
||||
# -
|
||||
else:
|
||||
raise SAXException("Unexpected node type %d" % nodeType)
|
||||
if r == 0:
|
||||
self._cont_handler.endDocument()
|
||||
reader.Close()
|
||||
finally:
|
||||
self.__parsing = 0
|
||||
|
||||
def setDTDHandler(self, handler):
|
||||
# TODO (when supported, the inherited method works just fine)
|
||||
raise SAXNotSupportedException("DTDHandler not supported")
|
||||
|
||||
def setEntityResolver(self, resolver):
|
||||
# TODO (when supported, the inherited method works just fine)
|
||||
raise SAXNotSupportedException("EntityResolver not supported")
|
||||
|
||||
def getFeature(self, name):
|
||||
if name == feature_namespaces:
|
||||
return self.__ns
|
||||
elif name == feature_namespace_prefixes:
|
||||
return self.__nspfx
|
||||
elif name == feature_validation:
|
||||
return self.__validate
|
||||
elif name == feature_external_ges:
|
||||
return 1 # TODO (does that relate to PARSER_LOADDTD)?
|
||||
elif name == feature_external_pes:
|
||||
return self.__extparams
|
||||
else:
|
||||
raise SAXNotRecognizedException("Feature '%s' not recognized" % \
|
||||
name)
|
||||
|
||||
def setFeature(self, name, state):
|
||||
if self.__parsing:
|
||||
raise SAXNotSupportedException("Cannot set feature %s " \
|
||||
"while parsing" % name)
|
||||
if name == feature_namespaces:
|
||||
self.__ns = state
|
||||
elif name == feature_namespace_prefixes:
|
||||
self.__nspfx = state
|
||||
elif name == feature_validation:
|
||||
self.__validate = state
|
||||
elif name == feature_external_ges:
|
||||
if state == 0:
|
||||
# TODO (does that relate to PARSER_LOADDTD)?
|
||||
raise SAXNotSupportedException("Feature '%s' not supported" % \
|
||||
name)
|
||||
elif name == feature_external_pes:
|
||||
self.__extparams = state
|
||||
else:
|
||||
raise SAXNotRecognizedException("Feature '%s' not recognized" % \
|
||||
name)
|
||||
|
||||
def getProperty(self, name):
|
||||
if name == property_lexical_handler:
|
||||
return self.__lex_handler
|
||||
elif name == property_declaration_handler:
|
||||
return self.__decl_handler
|
||||
else:
|
||||
raise SAXNotRecognizedException("Property '%s' not recognized" % \
|
||||
name)
|
||||
|
||||
def setProperty(self, name, value):
|
||||
if name == property_lexical_handler:
|
||||
self.__lex_handler = value
|
||||
elif name == property_declaration_handler:
|
||||
# TODO: remove if/when libxml2 supports dtd events
|
||||
raise SAXNotSupportedException("Property '%s' not supported" % \
|
||||
name)
|
||||
self.__decl_handler = value
|
||||
else:
|
||||
raise SAXNotRecognizedException("Property '%s' not recognized" % \
|
||||
name)
|
||||
|
||||
def create_parser():
|
||||
return LibXml2Reader()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,794 @@
|
||||
import libxml2mod
|
||||
import types
|
||||
import sys
|
||||
|
||||
# The root of all libxml2 errors.
|
||||
class libxmlError(Exception): pass
|
||||
|
||||
# Type of the wrapper class for the C objects wrappers
|
||||
def checkWrapper(obj):
|
||||
try:
|
||||
n = type(_obj).__name__
|
||||
if n != 'PyCObject' and n != 'PyCapsule':
|
||||
return 1
|
||||
except:
|
||||
return 0
|
||||
return 0
|
||||
|
||||
#
|
||||
# id() is sometimes negative ...
|
||||
#
|
||||
def pos_id(o):
|
||||
i = id(o)
|
||||
if (i < 0):
|
||||
return (sys.maxsize - i)
|
||||
return i
|
||||
|
||||
#
|
||||
# Errors raised by the wrappers when some tree handling failed.
|
||||
#
|
||||
class treeError(libxmlError):
|
||||
def __init__(self, msg):
|
||||
self.msg = msg
|
||||
def __str__(self):
|
||||
return self.msg
|
||||
|
||||
class parserError(libxmlError):
|
||||
def __init__(self, msg):
|
||||
self.msg = msg
|
||||
def __str__(self):
|
||||
return self.msg
|
||||
|
||||
class uriError(libxmlError):
|
||||
def __init__(self, msg):
|
||||
self.msg = msg
|
||||
def __str__(self):
|
||||
return self.msg
|
||||
|
||||
class xpathError(libxmlError):
|
||||
def __init__(self, msg):
|
||||
self.msg = msg
|
||||
def __str__(self):
|
||||
return self.msg
|
||||
|
||||
class ioWrapper:
|
||||
def __init__(self, _obj):
|
||||
self.__io = _obj
|
||||
self._o = None
|
||||
|
||||
def io_close(self):
|
||||
if self.__io == None:
|
||||
return(-1)
|
||||
self.__io.close()
|
||||
self.__io = None
|
||||
return(0)
|
||||
|
||||
def io_flush(self):
|
||||
if self.__io == None:
|
||||
return(-1)
|
||||
self.__io.flush()
|
||||
return(0)
|
||||
|
||||
def io_read(self, len = -1):
|
||||
if self.__io == None:
|
||||
return(-1)
|
||||
try:
|
||||
if len < 0:
|
||||
ret = self.__io.read()
|
||||
else:
|
||||
ret = self.__io.read(len)
|
||||
except Exception:
|
||||
import sys
|
||||
e = sys.exc_info()[1]
|
||||
print("failed to read from Python:", type(e))
|
||||
print("on IO:", self.__io)
|
||||
self.__io == None
|
||||
return(-1)
|
||||
|
||||
return(ret)
|
||||
|
||||
def io_write(self, str, len = -1):
|
||||
if self.__io == None:
|
||||
return(-1)
|
||||
if len < 0:
|
||||
return(self.__io.write(str))
|
||||
return(self.__io.write(str, len))
|
||||
|
||||
class ioReadWrapper(ioWrapper):
|
||||
def __init__(self, _obj, enc = ""):
|
||||
ioWrapper.__init__(self, _obj)
|
||||
self._o = libxml2mod.xmlCreateInputBuffer(self, enc)
|
||||
|
||||
def __del__(self):
|
||||
print("__del__")
|
||||
self.io_close()
|
||||
if self._o != None:
|
||||
libxml2mod.xmlFreeParserInputBuffer(self._o)
|
||||
self._o = None
|
||||
|
||||
def close(self):
|
||||
self.io_close()
|
||||
if self._o != None:
|
||||
libxml2mod.xmlFreeParserInputBuffer(self._o)
|
||||
self._o = None
|
||||
|
||||
class ioWriteWrapper(ioWrapper):
|
||||
def __init__(self, _obj, enc = ""):
|
||||
# print "ioWriteWrapper.__init__", _obj
|
||||
if type(_obj) == type(''):
|
||||
print("write io from a string")
|
||||
self.o = None
|
||||
elif type(_obj).__name__ == 'PyCapsule':
|
||||
file = libxml2mod.outputBufferGetPythonFile(_obj)
|
||||
if file != None:
|
||||
ioWrapper.__init__(self, file)
|
||||
else:
|
||||
ioWrapper.__init__(self, _obj)
|
||||
self._o = _obj
|
||||
# elif type(_obj) == types.InstanceType:
|
||||
# print(("write io from instance of %s" % (_obj.__class__)))
|
||||
# ioWrapper.__init__(self, _obj)
|
||||
# self._o = libxml2mod.xmlCreateOutputBuffer(self, enc)
|
||||
else:
|
||||
file = libxml2mod.outputBufferGetPythonFile(_obj)
|
||||
if file != None:
|
||||
ioWrapper.__init__(self, file)
|
||||
else:
|
||||
ioWrapper.__init__(self, _obj)
|
||||
self._o = _obj
|
||||
|
||||
def __del__(self):
|
||||
# print "__del__"
|
||||
self.io_close()
|
||||
if self._o != None:
|
||||
libxml2mod.xmlOutputBufferClose(self._o)
|
||||
self._o = None
|
||||
|
||||
def flush(self):
|
||||
self.io_flush()
|
||||
if self._o != None:
|
||||
libxml2mod.xmlOutputBufferClose(self._o)
|
||||
self._o = None
|
||||
|
||||
def close(self):
|
||||
self.io_flush()
|
||||
if self._o != None:
|
||||
libxml2mod.xmlOutputBufferClose(self._o)
|
||||
self._o = None
|
||||
|
||||
#
|
||||
# Example of a class to handle SAX events
|
||||
#
|
||||
class SAXCallback:
|
||||
"""Base class for SAX handlers"""
|
||||
def startDocument(self):
|
||||
"""called at the start of the document"""
|
||||
pass
|
||||
|
||||
def endDocument(self):
|
||||
"""called at the end of the document"""
|
||||
pass
|
||||
|
||||
def startElement(self, tag, attrs):
|
||||
"""called at the start of every element, tag is the name of
|
||||
the element, attrs is a dictionary of the element's attributes"""
|
||||
pass
|
||||
|
||||
def endElement(self, tag):
|
||||
"""called at the start of every element, tag is the name of
|
||||
the element"""
|
||||
pass
|
||||
|
||||
def characters(self, data):
|
||||
"""called when character data have been read, data is the string
|
||||
containing the data, multiple consecutive characters() callback
|
||||
are possible."""
|
||||
pass
|
||||
|
||||
def cdataBlock(self, data):
|
||||
"""called when CDATA section have been read, data is the string
|
||||
containing the data, multiple consecutive cdataBlock() callback
|
||||
are possible."""
|
||||
pass
|
||||
|
||||
def reference(self, name):
|
||||
"""called when an entity reference has been found"""
|
||||
pass
|
||||
|
||||
def ignorableWhitespace(self, data):
|
||||
"""called when potentially ignorable white spaces have been found"""
|
||||
pass
|
||||
|
||||
def processingInstruction(self, target, data):
|
||||
"""called when a PI has been found, target contains the PI name and
|
||||
data is the associated data in the PI"""
|
||||
pass
|
||||
|
||||
def comment(self, content):
|
||||
"""called when a comment has been found, content contains the comment"""
|
||||
pass
|
||||
|
||||
def externalSubset(self, name, externalID, systemID):
|
||||
"""called when a DOCTYPE declaration has been found, name is the
|
||||
DTD name and externalID, systemID are the DTD public and system
|
||||
identifier for that DTd if available"""
|
||||
pass
|
||||
|
||||
def internalSubset(self, name, externalID, systemID):
|
||||
"""called when a DOCTYPE declaration has been found, name is the
|
||||
DTD name and externalID, systemID are the DTD public and system
|
||||
identifier for that DTD if available"""
|
||||
pass
|
||||
|
||||
def entityDecl(self, name, type, externalID, systemID, content):
|
||||
"""called when an ENTITY declaration has been found, name is the
|
||||
entity name and externalID, systemID are the entity public and
|
||||
system identifier for that entity if available, type indicates
|
||||
the entity type, and content reports it's string content"""
|
||||
pass
|
||||
|
||||
def notationDecl(self, name, externalID, systemID):
|
||||
"""called when an NOTATION declaration has been found, name is the
|
||||
notation name and externalID, systemID are the notation public and
|
||||
system identifier for that notation if available"""
|
||||
pass
|
||||
|
||||
def attributeDecl(self, elem, name, type, defi, defaultValue, nameList):
|
||||
"""called when an ATTRIBUTE definition has been found"""
|
||||
pass
|
||||
|
||||
def elementDecl(self, name, type, content):
|
||||
"""called when an ELEMENT definition has been found"""
|
||||
pass
|
||||
|
||||
def entityDecl(self, name, publicId, systemID, notationName):
|
||||
"""called when an unparsed ENTITY declaration has been found,
|
||||
name is the entity name and publicId,, systemID are the entity
|
||||
public and system identifier for that entity if available,
|
||||
and notationName indicate the associated NOTATION"""
|
||||
pass
|
||||
|
||||
def warning(self, msg):
|
||||
#print msg
|
||||
pass
|
||||
|
||||
def error(self, msg):
|
||||
raise parserError(msg)
|
||||
|
||||
def fatalError(self, msg):
|
||||
raise parserError(msg)
|
||||
|
||||
#
|
||||
# This class is the ancestor of all the Node classes. It provides
|
||||
# the basic functionalities shared by all nodes (and handle
|
||||
# gracefylly the exception), like name, navigation in the tree,
|
||||
# doc reference, content access and serializing to a string or URI
|
||||
#
|
||||
class xmlCore:
|
||||
def __init__(self, _obj=None):
|
||||
if _obj != None:
|
||||
self._o = _obj;
|
||||
return
|
||||
self._o = None
|
||||
|
||||
def __eq__(self, other):
|
||||
if other == None:
|
||||
return False
|
||||
ret = libxml2mod.compareNodesEqual(self._o, other._o)
|
||||
if ret == None:
|
||||
return False
|
||||
return ret == True
|
||||
def __ne__(self, other):
|
||||
if other == None:
|
||||
return True
|
||||
ret = libxml2mod.compareNodesEqual(self._o, other._o)
|
||||
return not ret
|
||||
def __hash__(self):
|
||||
ret = libxml2mod.nodeHash(self._o)
|
||||
return ret
|
||||
|
||||
def __str__(self):
|
||||
return self.serialize()
|
||||
def get_parent(self):
|
||||
ret = libxml2mod.parent(self._o)
|
||||
if ret == None:
|
||||
return None
|
||||
return nodeWrap(ret)
|
||||
def get_children(self):
|
||||
ret = libxml2mod.children(self._o)
|
||||
if ret == None:
|
||||
return None
|
||||
return nodeWrap(ret)
|
||||
def get_last(self):
|
||||
ret = libxml2mod.last(self._o)
|
||||
if ret == None:
|
||||
return None
|
||||
return nodeWrap(ret)
|
||||
def get_next(self):
|
||||
ret = libxml2mod.next(self._o)
|
||||
if ret == None:
|
||||
return None
|
||||
return nodeWrap(ret)
|
||||
def get_properties(self):
|
||||
ret = libxml2mod.properties(self._o)
|
||||
if ret == None:
|
||||
return None
|
||||
return xmlAttr(_obj=ret)
|
||||
def get_prev(self):
|
||||
ret = libxml2mod.prev(self._o)
|
||||
if ret == None:
|
||||
return None
|
||||
return nodeWrap(ret)
|
||||
def get_content(self):
|
||||
return libxml2mod.xmlNodeGetContent(self._o)
|
||||
getContent = get_content # why is this duplicate naming needed ?
|
||||
def get_name(self):
|
||||
return libxml2mod.name(self._o)
|
||||
def get_type(self):
|
||||
return libxml2mod.type(self._o)
|
||||
def get_doc(self):
|
||||
ret = libxml2mod.doc(self._o)
|
||||
if ret == None:
|
||||
if self.type in ["document_xml", "document_html"]:
|
||||
return xmlDoc(_obj=self._o)
|
||||
else:
|
||||
return None
|
||||
return xmlDoc(_obj=ret)
|
||||
#
|
||||
# Those are common attributes to nearly all type of nodes
|
||||
# defined as python2 properties
|
||||
#
|
||||
import sys
|
||||
if float(sys.version[0:3]) < 2.2:
|
||||
def __getattr__(self, attr):
|
||||
if attr == "parent":
|
||||
ret = libxml2mod.parent(self._o)
|
||||
if ret == None:
|
||||
return None
|
||||
return nodeWrap(ret)
|
||||
elif attr == "properties":
|
||||
ret = libxml2mod.properties(self._o)
|
||||
if ret == None:
|
||||
return None
|
||||
return xmlAttr(_obj=ret)
|
||||
elif attr == "children":
|
||||
ret = libxml2mod.children(self._o)
|
||||
if ret == None:
|
||||
return None
|
||||
return nodeWrap(ret)
|
||||
elif attr == "last":
|
||||
ret = libxml2mod.last(self._o)
|
||||
if ret == None:
|
||||
return None
|
||||
return nodeWrap(ret)
|
||||
elif attr == "next":
|
||||
ret = libxml2mod.next(self._o)
|
||||
if ret == None:
|
||||
return None
|
||||
return nodeWrap(ret)
|
||||
elif attr == "prev":
|
||||
ret = libxml2mod.prev(self._o)
|
||||
if ret == None:
|
||||
return None
|
||||
return nodeWrap(ret)
|
||||
elif attr == "content":
|
||||
return libxml2mod.xmlNodeGetContent(self._o)
|
||||
elif attr == "name":
|
||||
return libxml2mod.name(self._o)
|
||||
elif attr == "type":
|
||||
return libxml2mod.type(self._o)
|
||||
elif attr == "doc":
|
||||
ret = libxml2mod.doc(self._o)
|
||||
if ret == None:
|
||||
if self.type == "document_xml" or self.type == "document_html":
|
||||
return xmlDoc(_obj=self._o)
|
||||
else:
|
||||
return None
|
||||
return xmlDoc(_obj=ret)
|
||||
raise AttributeError(attr)
|
||||
else:
|
||||
parent = property(get_parent, None, None, "Parent node")
|
||||
children = property(get_children, None, None, "First child node")
|
||||
last = property(get_last, None, None, "Last sibling node")
|
||||
next = property(get_next, None, None, "Next sibling node")
|
||||
prev = property(get_prev, None, None, "Previous sibling node")
|
||||
properties = property(get_properties, None, None, "List of properties")
|
||||
content = property(get_content, None, None, "Content of this node")
|
||||
name = property(get_name, None, None, "Node name")
|
||||
type = property(get_type, None, None, "Node type")
|
||||
doc = property(get_doc, None, None, "The document this node belongs to")
|
||||
|
||||
#
|
||||
# Serialization routines, the optional arguments have the following
|
||||
# meaning:
|
||||
# encoding: string to ask saving in a specific encoding
|
||||
# indent: if 1 the serializer is asked to indent the output
|
||||
#
|
||||
def serialize(self, encoding = None, format = 0):
|
||||
return libxml2mod.serializeNode(self._o, encoding, format)
|
||||
def saveTo(self, file, encoding = None, format = 0):
|
||||
return libxml2mod.saveNodeTo(self._o, file, encoding, format)
|
||||
|
||||
#
|
||||
# Canonicalization routines:
|
||||
#
|
||||
# nodes: the node set (tuple or list) to be included in the
|
||||
# canonized image or None if all document nodes should be
|
||||
# included.
|
||||
# exclusive: the exclusive flag (0 - non-exclusive
|
||||
# canonicalization; otherwise - exclusive canonicalization)
|
||||
# prefixes: the list of inclusive namespace prefixes (strings),
|
||||
# or None if there is no inclusive namespaces (only for
|
||||
# exclusive canonicalization, ignored otherwise)
|
||||
# with_comments: include comments in the result (!=0) or not
|
||||
# (==0)
|
||||
def c14nMemory(self,
|
||||
nodes=None,
|
||||
exclusive=0,
|
||||
prefixes=None,
|
||||
with_comments=0):
|
||||
if nodes:
|
||||
nodes = [n._o for n in nodes]
|
||||
return libxml2mod.xmlC14NDocDumpMemory(
|
||||
self.get_doc()._o,
|
||||
nodes,
|
||||
exclusive != 0,
|
||||
prefixes,
|
||||
with_comments != 0)
|
||||
def c14nSaveTo(self,
|
||||
file,
|
||||
nodes=None,
|
||||
exclusive=0,
|
||||
prefixes=None,
|
||||
with_comments=0):
|
||||
if nodes:
|
||||
nodes = [n._o for n in nodes]
|
||||
return libxml2mod.xmlC14NDocSaveTo(
|
||||
self.get_doc()._o,
|
||||
nodes,
|
||||
exclusive != 0,
|
||||
prefixes,
|
||||
with_comments != 0,
|
||||
file)
|
||||
|
||||
#
|
||||
# Selecting nodes using XPath, a bit slow because the context
|
||||
# is allocated/freed every time but convenient.
|
||||
#
|
||||
def xpathEval(self, expr):
|
||||
doc = self.doc
|
||||
if doc == None:
|
||||
return None
|
||||
ctxt = doc.xpathNewContext()
|
||||
ctxt.setContextNode(self)
|
||||
res = ctxt.xpathEval(expr)
|
||||
ctxt.xpathFreeContext()
|
||||
return res
|
||||
|
||||
# #
|
||||
# # Selecting nodes using XPath, faster because the context
|
||||
# # is allocated just once per xmlDoc.
|
||||
# #
|
||||
# # Removed: DV memleaks c.f. #126735
|
||||
# #
|
||||
# def xpathEval2(self, expr):
|
||||
# doc = self.doc
|
||||
# if doc == None:
|
||||
# return None
|
||||
# try:
|
||||
# doc._ctxt.setContextNode(self)
|
||||
# except:
|
||||
# doc._ctxt = doc.xpathNewContext()
|
||||
# doc._ctxt.setContextNode(self)
|
||||
# res = doc._ctxt.xpathEval(expr)
|
||||
# return res
|
||||
def xpathEval2(self, expr):
|
||||
return self.xpathEval(expr)
|
||||
|
||||
# Remove namespaces
|
||||
def removeNsDef(self, href):
|
||||
"""
|
||||
Remove a namespace definition from a node. If href is None,
|
||||
remove all of the ns definitions on that node. The removed
|
||||
namespaces are returned as a linked list.
|
||||
|
||||
Note: If any child nodes referred to the removed namespaces,
|
||||
they will be left with dangling links. You should call
|
||||
renconciliateNs() to fix those pointers.
|
||||
|
||||
Note: This method does not free memory taken by the ns
|
||||
definitions. You will need to free it manually with the
|
||||
freeNsList() method on the returns xmlNs object.
|
||||
"""
|
||||
|
||||
ret = libxml2mod.xmlNodeRemoveNsDef(self._o, href)
|
||||
if ret is None:return None
|
||||
__tmp = xmlNs(_obj=ret)
|
||||
return __tmp
|
||||
|
||||
# support for python2 iterators
|
||||
def walk_depth_first(self):
|
||||
return xmlCoreDepthFirstItertor(self)
|
||||
def walk_breadth_first(self):
|
||||
return xmlCoreBreadthFirstItertor(self)
|
||||
__iter__ = walk_depth_first
|
||||
|
||||
def free(self):
|
||||
try:
|
||||
self.doc._ctxt.xpathFreeContext()
|
||||
except:
|
||||
pass
|
||||
libxml2mod.xmlFreeDoc(self._o)
|
||||
|
||||
|
||||
#
|
||||
# implements the depth-first iterator for libxml2 DOM tree
|
||||
#
|
||||
class xmlCoreDepthFirstItertor:
|
||||
def __init__(self, node):
|
||||
self.node = node
|
||||
self.parents = []
|
||||
def __iter__(self):
|
||||
return self
|
||||
def __next__(self):
|
||||
while 1:
|
||||
if self.node:
|
||||
ret = self.node
|
||||
self.parents.append(self.node)
|
||||
self.node = self.node.children
|
||||
return ret
|
||||
try:
|
||||
parent = self.parents.pop()
|
||||
except IndexError:
|
||||
raise StopIteration
|
||||
self.node = parent.next
|
||||
next = __next__
|
||||
|
||||
#
|
||||
# implements the breadth-first iterator for libxml2 DOM tree
|
||||
#
|
||||
class xmlCoreBreadthFirstItertor:
|
||||
def __init__(self, node):
|
||||
self.node = node
|
||||
self.parents = []
|
||||
def __iter__(self):
|
||||
return self
|
||||
def __next__(self):
|
||||
while 1:
|
||||
if self.node:
|
||||
ret = self.node
|
||||
self.parents.append(self.node)
|
||||
self.node = self.node.next
|
||||
return ret
|
||||
try:
|
||||
parent = self.parents.pop()
|
||||
except IndexError:
|
||||
raise StopIteration
|
||||
self.node = parent.children
|
||||
next = __next__
|
||||
|
||||
#
|
||||
# converters to present a nicer view of the XPath returns
|
||||
#
|
||||
def nodeWrap(o):
|
||||
# TODO try to cast to the most appropriate node class
|
||||
name = libxml2mod.type(o)
|
||||
if name == "element" or name == "text":
|
||||
return xmlNode(_obj=o)
|
||||
if name == "attribute":
|
||||
return xmlAttr(_obj=o)
|
||||
if name[0:8] == "document":
|
||||
return xmlDoc(_obj=o)
|
||||
if name == "namespace":
|
||||
return xmlNs(_obj=o)
|
||||
if name == "elem_decl":
|
||||
return xmlElement(_obj=o)
|
||||
if name == "attribute_decl":
|
||||
return xmlAttribute(_obj=o)
|
||||
if name == "entity_decl":
|
||||
return xmlEntity(_obj=o)
|
||||
if name == "dtd":
|
||||
return xmlDtd(_obj=o)
|
||||
return xmlNode(_obj=o)
|
||||
|
||||
def xpathObjectRet(o):
|
||||
otype = type(o)
|
||||
if otype == type([]):
|
||||
ret = list(map(xpathObjectRet, o))
|
||||
return ret
|
||||
elif otype == type(()):
|
||||
ret = list(map(xpathObjectRet, o))
|
||||
return tuple(ret)
|
||||
elif otype == type('') or otype == type(0) or otype == type(0.0):
|
||||
return o
|
||||
else:
|
||||
return nodeWrap(o)
|
||||
|
||||
#
|
||||
# register an XPath function
|
||||
#
|
||||
def registerXPathFunction(ctxt, name, ns_uri, f):
|
||||
ret = libxml2mod.xmlRegisterXPathFunction(ctxt, name, ns_uri, f)
|
||||
|
||||
#
|
||||
# For the xmlTextReader parser configuration
|
||||
#
|
||||
PARSER_LOADDTD=1
|
||||
PARSER_DEFAULTATTRS=2
|
||||
PARSER_VALIDATE=3
|
||||
PARSER_SUBST_ENTITIES=4
|
||||
|
||||
#
|
||||
# For the error callback severities
|
||||
#
|
||||
PARSER_SEVERITY_VALIDITY_WARNING=1
|
||||
PARSER_SEVERITY_VALIDITY_ERROR=2
|
||||
PARSER_SEVERITY_WARNING=3
|
||||
PARSER_SEVERITY_ERROR=4
|
||||
|
||||
#
|
||||
# register the libxml2 error handler
|
||||
#
|
||||
def registerErrorHandler(f, ctx):
|
||||
"""Register a Python written function to for error reporting.
|
||||
The function is called back as f(ctx, error). """
|
||||
import sys
|
||||
if 'libxslt' not in sys.modules:
|
||||
# normal behaviour when libxslt is not imported
|
||||
ret = libxml2mod.xmlRegisterErrorHandler(f,ctx)
|
||||
else:
|
||||
# when libxslt is already imported, one must
|
||||
# use libxst's error handler instead
|
||||
import libxslt
|
||||
ret = libxslt.registerErrorHandler(f,ctx)
|
||||
return ret
|
||||
|
||||
class parserCtxtCore:
|
||||
|
||||
def __init__(self, _obj=None):
|
||||
if _obj != None:
|
||||
self._o = _obj;
|
||||
return
|
||||
self._o = None
|
||||
|
||||
def __del__(self):
|
||||
if self._o != None:
|
||||
libxml2mod.xmlFreeParserCtxt(self._o)
|
||||
self._o = None
|
||||
|
||||
def setErrorHandler(self,f,arg):
|
||||
"""Register an error handler that will be called back as
|
||||
f(arg,msg,severity,reserved).
|
||||
|
||||
@reserved is currently always None."""
|
||||
libxml2mod.xmlParserCtxtSetErrorHandler(self._o,f,arg)
|
||||
|
||||
def getErrorHandler(self):
|
||||
"""Return (f,arg) as previously registered with setErrorHandler
|
||||
or (None,None)."""
|
||||
return libxml2mod.xmlParserCtxtGetErrorHandler(self._o)
|
||||
|
||||
def addLocalCatalog(self, uri):
|
||||
"""Register a local catalog with the parser"""
|
||||
return libxml2mod.addLocalCatalog(self._o, uri)
|
||||
|
||||
|
||||
class ValidCtxtCore:
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
pass
|
||||
|
||||
def setValidityErrorHandler(self, err_func, warn_func, arg=None):
|
||||
"""
|
||||
Register error and warning handlers for DTD validation.
|
||||
These will be called back as f(msg,arg)
|
||||
"""
|
||||
libxml2mod.xmlSetValidErrors(self._o, err_func, warn_func, arg)
|
||||
|
||||
|
||||
class SchemaValidCtxtCore:
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
pass
|
||||
|
||||
def setValidityErrorHandler(self, err_func, warn_func, arg=None):
|
||||
"""
|
||||
Register error and warning handlers for Schema validation.
|
||||
These will be called back as f(msg,arg)
|
||||
"""
|
||||
libxml2mod.xmlSchemaSetValidErrors(self._o, err_func, warn_func, arg)
|
||||
|
||||
|
||||
class relaxNgValidCtxtCore:
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
pass
|
||||
|
||||
def setValidityErrorHandler(self, err_func, warn_func, arg=None):
|
||||
"""
|
||||
Register error and warning handlers for RelaxNG validation.
|
||||
These will be called back as f(msg,arg)
|
||||
"""
|
||||
libxml2mod.xmlRelaxNGSetValidErrors(self._o, err_func, warn_func, arg)
|
||||
|
||||
|
||||
def _xmlTextReaderErrorFunc(xxx_todo_changeme,msg,severity,locator):
|
||||
"""Intermediate callback to wrap the locator"""
|
||||
(f,arg) = xxx_todo_changeme
|
||||
return f(arg,msg,severity,xmlTextReaderLocator(locator))
|
||||
|
||||
class xmlTextReaderCore:
|
||||
|
||||
def __init__(self, _obj=None):
|
||||
self.input = None
|
||||
if _obj != None:self._o = _obj;return
|
||||
self._o = None
|
||||
|
||||
def __del__(self):
|
||||
if self._o != None:
|
||||
libxml2mod.xmlFreeTextReader(self._o)
|
||||
self._o = None
|
||||
|
||||
def SetErrorHandler(self,f,arg):
|
||||
"""Register an error handler that will be called back as
|
||||
f(arg,msg,severity,locator)."""
|
||||
if f is None:
|
||||
libxml2mod.xmlTextReaderSetErrorHandler(\
|
||||
self._o,None,None)
|
||||
else:
|
||||
libxml2mod.xmlTextReaderSetErrorHandler(\
|
||||
self._o,_xmlTextReaderErrorFunc,(f,arg))
|
||||
|
||||
def GetErrorHandler(self):
|
||||
"""Return (f,arg) as previously registered with setErrorHandler
|
||||
or (None,None)."""
|
||||
f,arg = libxml2mod.xmlTextReaderGetErrorHandler(self._o)
|
||||
if f is None:
|
||||
return None,None
|
||||
else:
|
||||
# assert f is _xmlTextReaderErrorFunc
|
||||
return arg
|
||||
|
||||
#
|
||||
# The cleanup now goes though a wrapper in libxml.c
|
||||
#
|
||||
def cleanupParser():
|
||||
libxml2mod.xmlPythonCleanupParser()
|
||||
|
||||
#
|
||||
# The interface to xmlRegisterInputCallbacks.
|
||||
# Since this API does not allow to pass a data object along with
|
||||
# match/open callbacks, it is necessary to maintain a list of all
|
||||
# Python callbacks.
|
||||
#
|
||||
__input_callbacks = []
|
||||
def registerInputCallback(func):
|
||||
def findOpenCallback(URI):
|
||||
for cb in reversed(__input_callbacks):
|
||||
o = cb(URI)
|
||||
if o is not None:
|
||||
return o
|
||||
libxml2mod.xmlRegisterInputCallback(findOpenCallback)
|
||||
__input_callbacks.append(func)
|
||||
|
||||
def popInputCallbacks():
|
||||
# First pop python-level callbacks, when no more available - start
|
||||
# popping built-in ones.
|
||||
if len(__input_callbacks) > 0:
|
||||
__input_callbacks.pop()
|
||||
if len(__input_callbacks) == 0:
|
||||
libxml2mod.xmlUnregisterInputCallback()
|
||||
|
||||
#
|
||||
# Deprecated
|
||||
#
|
||||
def dumpMemory():
|
||||
"""DEPRECATED: This feature was removed."""
|
||||
|
||||
# WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
|
||||
#
|
||||
# Everything before this line comes from libxml.py
|
||||
# Everything after this line is automatically generated
|
||||
#
|
||||
# WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
#include <Python.h>
|
||||
#include <libxml/tree.h>
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/parserInternals.h>
|
||||
#include <libxml/catalog.h>
|
||||
#include <libxml/threads.h>
|
||||
#include <libxml/nanohttp.h>
|
||||
#include <libxml/uri.h>
|
||||
#include <libxml/xpath.h>
|
||||
#include <libxml/xpathInternals.h>
|
||||
#include <libxml/debugXML.h>
|
||||
#include <libxml/HTMLparser.h>
|
||||
#include <libxml/HTMLtree.h>
|
||||
#include <libxml/xinclude.h>
|
||||
#include <libxml/xpointer.h>
|
||||
#include <libxml/xmlregexp.h>
|
||||
#include <libxml/xmlautomata.h>
|
||||
#include <libxml/xmlreader.h>
|
||||
#include <libxml/xmlsave.h>
|
||||
#ifdef LIBXML_RELAXNG_ENABLED
|
||||
#include <libxml/relaxng.h>
|
||||
#endif
|
||||
#ifdef LIBXML_SCHEMAS_ENABLED
|
||||
#include <libxml/xmlschemas.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* for older versions of Python, we don't use PyBytes, but keep PyString
|
||||
* and don't use Capsule but CObjects
|
||||
*/
|
||||
#if PY_VERSION_HEX < 0x02070000
|
||||
#ifndef PyBytes_Check
|
||||
#define PyBytes_Check PyString_Check
|
||||
#define PyBytes_Size PyString_Size
|
||||
#define PyBytes_AsString PyString_AsString
|
||||
#define PyBytes_AS_STRING PyString_AS_STRING
|
||||
#define PyBytes_GET_SIZE PyString_GET_SIZE
|
||||
#endif
|
||||
#ifndef PyCapsule_New
|
||||
#define PyCapsule_New PyCObject_FromVoidPtrAndDesc
|
||||
#define PyCapsule_CheckExact PyCObject_Check
|
||||
#define PyCapsule_GetPointer(o, n) PyCObject_GetDesc((o))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#ifdef ATTRIBUTE_UNUSED
|
||||
#undef ATTRIBUTE_UNUSED
|
||||
#endif
|
||||
#ifndef ATTRIBUTE_UNUSED
|
||||
#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
|
||||
#endif /* ATTRIBUTE_UNUSED */
|
||||
#else
|
||||
#define ATTRIBUTE_UNUSED
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macros to ignore deprecation warnings
|
||||
*/
|
||||
#if defined(__LCC__)
|
||||
#define XML_IGNORE_DEPRECATION_WARNINGS _Pragma("diag_suppress 1215")
|
||||
#define XML_POP_WARNINGS _Pragma("diag_default 1215")
|
||||
#elif defined(__clang__) || \
|
||||
(defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406))
|
||||
#define XML_IGNORE_DEPRECATION_WARNINGS \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
|
||||
#define XML_POP_WARNINGS _Pragma("GCC diagnostic pop")
|
||||
#elif defined (_MSC_VER) && (_MSC_VER >= 1400)
|
||||
#define XML_IGNORE_DEPRECATION_WARNINGS \
|
||||
__pragma(warning(push)) \
|
||||
__pragma(warning(disable : 4996))
|
||||
#define XML_POP_WARNINGS __pragma(warning(pop))
|
||||
#else
|
||||
#define XML_IGNORE_DEPRECATION_WARNINGS
|
||||
#define XML_POP_WARNINGS
|
||||
#endif
|
||||
|
||||
#define PyxmlNode_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyxmlNode_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlNodePtr obj;
|
||||
} PyxmlNode_Object;
|
||||
|
||||
#ifdef LIBXML_XPATH_ENABLED
|
||||
#define PyxmlXPathContext_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyxmlXPathContext_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlXPathContextPtr obj;
|
||||
} PyxmlXPathContext_Object;
|
||||
|
||||
#define PyxmlXPathParserContext_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyxmlXPathParserContext_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlXPathParserContextPtr obj;
|
||||
} PyxmlXPathParserContext_Object;
|
||||
#endif /* LIBXML_XPATH_ENABLED */
|
||||
|
||||
#define PyparserCtxt_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyparserCtxt_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlParserCtxtPtr obj;
|
||||
} PyparserCtxt_Object;
|
||||
|
||||
#define PyValidCtxt_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyValidCtxt_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlValidCtxtPtr obj;
|
||||
} PyValidCtxt_Object;
|
||||
|
||||
#ifdef LIBXML_CATALOG_ENABLED
|
||||
#define Pycatalog_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((Pycatalog_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlCatalogPtr obj;
|
||||
} Pycatalog_Object;
|
||||
#endif /* LIBXML_CATALOG_ENABLED */
|
||||
|
||||
#ifdef LIBXML_REGEXP_ENABLED
|
||||
#define PyxmlReg_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyxmlReg_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlRegexpPtr obj;
|
||||
} PyxmlReg_Object;
|
||||
#endif /* LIBXML_REGEXP_ENABLED */
|
||||
|
||||
#ifdef LIBXML_READER_ENABLED
|
||||
#define PyxmlTextReader_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyxmlTextReader_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlTextReaderPtr obj;
|
||||
} PyxmlTextReader_Object;
|
||||
|
||||
#define PyxmlTextReaderLocator_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyxmlTextReaderLocator_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlTextReaderLocatorPtr obj;
|
||||
} PyxmlTextReaderLocator_Object;
|
||||
#endif
|
||||
|
||||
#define PyURI_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyURI_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlErrorPtr obj;
|
||||
} PyError_Object;
|
||||
|
||||
#define PyError_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyError_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlOutputBufferPtr obj;
|
||||
} PyoutputBuffer_Object;
|
||||
|
||||
#define PyoutputBuffer_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyoutputBuffer_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlParserInputBufferPtr obj;
|
||||
} PyinputBuffer_Object;
|
||||
|
||||
#define PyinputBuffer_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyinputBuffer_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlURIPtr obj;
|
||||
} PyURI_Object;
|
||||
|
||||
/* FILE * have their own internal representation */
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
FILE *libxml_PyFileGet(PyObject *f);
|
||||
void libxml_PyFileRelease(FILE *f);
|
||||
#define PyFile_Get(v) (((v) == Py_None) ? NULL : libxml_PyFileGet(v))
|
||||
#define PyFile_Release(f) libxml_PyFileRelease(f)
|
||||
#else
|
||||
#define PyFile_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(PyFile_Check(v) ? (PyFile_AsFile(v)) : stdout))
|
||||
#define PyFile_Release(f)
|
||||
#endif
|
||||
|
||||
#ifdef LIBXML_RELAXNG_ENABLED
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlRelaxNGPtr obj;
|
||||
} PyrelaxNgSchema_Object;
|
||||
|
||||
#define PyrelaxNgSchema_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyrelaxNgSchema_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlRelaxNGParserCtxtPtr obj;
|
||||
} PyrelaxNgParserCtxt_Object;
|
||||
|
||||
#define PyrelaxNgParserCtxt_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyrelaxNgParserCtxt_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlRelaxNGValidCtxtPtr obj;
|
||||
} PyrelaxNgValidCtxt_Object;
|
||||
|
||||
#define PyrelaxNgValidCtxt_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PyrelaxNgValidCtxt_Object *)(v))->obj))
|
||||
|
||||
#endif /* LIBXML_RELAXNG_ENABLED */
|
||||
|
||||
#ifdef LIBXML_SCHEMAS_ENABLED
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlSchemaPtr obj;
|
||||
} PySchema_Object;
|
||||
|
||||
#define PySchema_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PySchema_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlSchemaParserCtxtPtr obj;
|
||||
} PySchemaParserCtxt_Object;
|
||||
|
||||
#define PySchemaParserCtxt_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PySchemaParserCtxt_Object *)(v))->obj))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
xmlSchemaValidCtxtPtr obj;
|
||||
} PySchemaValidCtxt_Object;
|
||||
|
||||
#define PySchemaValidCtxt_Get(v) (((v) == Py_None) ? NULL : \
|
||||
(((PySchemaValidCtxt_Object *)(v))->obj))
|
||||
|
||||
#endif /* LIBXML_SCHEMAS_ENABLED */
|
||||
|
||||
PyObject * libxml_intWrap(int val);
|
||||
PyObject * libxml_longWrap(long val);
|
||||
PyObject * libxml_xmlCharPtrWrap(xmlChar *str);
|
||||
PyObject * libxml_constxmlCharPtrWrap(const xmlChar *str);
|
||||
PyObject * libxml_charPtrWrap(char *str);
|
||||
PyObject * libxml_constcharPtrWrap(const char *str);
|
||||
PyObject * libxml_charPtrConstWrap(const char *str);
|
||||
PyObject * libxml_xmlCharPtrConstWrap(const xmlChar *str);
|
||||
PyObject * libxml_xmlDocPtrWrap(xmlDocPtr doc);
|
||||
PyObject * libxml_xmlNodePtrWrap(xmlNodePtr node);
|
||||
PyObject * libxml_xmlAttrPtrWrap(xmlAttrPtr attr);
|
||||
PyObject * libxml_xmlNsPtrWrap(xmlNsPtr ns);
|
||||
PyObject * libxml_xmlAttributePtrWrap(xmlAttributePtr ns);
|
||||
PyObject * libxml_xmlElementPtrWrap(xmlElementPtr ns);
|
||||
PyObject * libxml_doubleWrap(double val);
|
||||
PyObject * libxml_xmlParserCtxtPtrWrap(xmlParserCtxtPtr ctxt);
|
||||
#ifdef LIBXML_XPATH_ENABLED
|
||||
PyObject * libxml_xmlXPathContextPtrWrap(xmlXPathContextPtr ctxt);
|
||||
PyObject * libxml_xmlXPathParserContextPtrWrap(xmlXPathParserContextPtr ctxt);
|
||||
PyObject * libxml_xmlXPathObjectPtrWrap(xmlXPathObjectPtr obj);
|
||||
xmlXPathObjectPtr libxml_xmlXPathObjectPtrConvert(PyObject * obj);
|
||||
#endif
|
||||
PyObject * libxml_xmlValidCtxtPtrWrap(xmlValidCtxtPtr valid);
|
||||
#ifdef LIBXML_CATALOG_ENABLED
|
||||
PyObject * libxml_xmlCatalogPtrWrap(xmlCatalogPtr obj);
|
||||
#endif
|
||||
PyObject * libxml_xmlURIPtrWrap(xmlURIPtr uri);
|
||||
PyObject * libxml_xmlOutputBufferPtrWrap(xmlOutputBufferPtr buffer);
|
||||
PyObject * libxml_xmlParserInputBufferPtrWrap(xmlParserInputBufferPtr buffer);
|
||||
#ifdef LIBXML_REGEXP_ENABLED
|
||||
PyObject * libxml_xmlRegexpPtrWrap(xmlRegexpPtr regexp);
|
||||
#endif /* LIBXML_REGEXP_ENABLED */
|
||||
#ifdef LIBXML_READER_ENABLED
|
||||
PyObject * libxml_xmlTextReaderPtrWrap(xmlTextReaderPtr reader);
|
||||
PyObject * libxml_xmlTextReaderLocatorPtrWrap(xmlTextReaderLocatorPtr locator);
|
||||
#endif
|
||||
|
||||
#ifdef LIBXML_RELAXNG_ENABLED
|
||||
PyObject * libxml_xmlRelaxNGPtrWrap(xmlRelaxNGPtr ctxt);
|
||||
PyObject * libxml_xmlRelaxNGParserCtxtPtrWrap(xmlRelaxNGParserCtxtPtr ctxt);
|
||||
PyObject * libxml_xmlRelaxNGValidCtxtPtrWrap(xmlRelaxNGValidCtxtPtr valid);
|
||||
#endif /* LIBXML_RELAXNG_ENABLED */
|
||||
#ifdef LIBXML_SCHEMAS_ENABLED
|
||||
PyObject * libxml_xmlSchemaPtrWrap(xmlSchemaPtr ctxt);
|
||||
PyObject * libxml_xmlSchemaParserCtxtPtrWrap(xmlSchemaParserCtxtPtr ctxt);
|
||||
PyObject * libxml_xmlSchemaValidCtxtPtrWrap(xmlSchemaValidCtxtPtr valid);
|
||||
#endif /* LIBXML_SCHEMAS_ENABLED */
|
||||
PyObject * libxml_xmlErrorPtrWrap(const xmlError *error);
|
||||
PyObject * libxml_xmlSchemaSetValidErrors(PyObject * self, PyObject * args);
|
||||
PyObject * libxml_xmlRegisterInputCallback(PyObject *self, PyObject *args);
|
||||
PyObject * libxml_xmlUnregisterInputCallback(PyObject *self, PyObject *args);
|
||||
PyObject * libxml_xmlNodeRemoveNsDef(PyObject * self, PyObject * args);
|
||||
|
||||
int libxml_deprecationWarning(const char *func);
|
||||
@@ -0,0 +1,113 @@
|
||||
|
||||
pymod = import('python')
|
||||
py = pymod.find_installation('python3', required: false)
|
||||
|
||||
if py.found() == true
|
||||
message('Installing python modules to', py.get_install_dir())
|
||||
|
||||
pygenerated = custom_target(
|
||||
'Python generated files',
|
||||
input: doxygen_docs[1],
|
||||
output: [
|
||||
'libxml2-py.h',
|
||||
'libxml2-export.c',
|
||||
'libxml2-py.c',
|
||||
'libxml2.py',
|
||||
],
|
||||
command: [ py, files('generator.py'), meson.current_build_dir() ],
|
||||
install: true,
|
||||
install_dir: [ false, false, false, py.get_install_dir() ],
|
||||
)
|
||||
pygenerated_dep = declare_dependency(
|
||||
sources : [pygenerated[0]],
|
||||
)
|
||||
|
||||
libxml2mod_src = [
|
||||
files('libxml.c', 'types.c'),
|
||||
pygenerated[2],
|
||||
]
|
||||
|
||||
py.extension_module(
|
||||
'libxml2mod',
|
||||
libxml2mod_src,
|
||||
dependencies: [
|
||||
py.dependency(),
|
||||
xml_dep,
|
||||
pygenerated_dep,
|
||||
],
|
||||
include_directories: [config_dir, '.'],
|
||||
install: true,
|
||||
)
|
||||
|
||||
py.install_sources(files('drv_libxml2.py'))
|
||||
|
||||
setup_py = configuration_data()
|
||||
setup_py.set('prefix', get_option('prefix'))
|
||||
setup_py.set('LIBXML_VERSION', meson.project_version())
|
||||
setup_py.set('WITH_ICONV', want_iconv.to_int())
|
||||
setup_py.set('WITH_ICU', want_icu.to_int())
|
||||
setup_py.set('WITH_ZLIB', want_zlib.to_int())
|
||||
setup_py.set('WITH_THREADS', want_threads.to_int())
|
||||
configure_file(
|
||||
input: 'setup.py.in',
|
||||
output: 'setup.py',
|
||||
configuration: setup_py,
|
||||
)
|
||||
|
||||
python_tests = [
|
||||
'attribs.py',
|
||||
'build.py',
|
||||
'compareNodes.py',
|
||||
'ctxterror.py',
|
||||
'cutnpaste.py',
|
||||
'dtdvalid.py',
|
||||
'error.py',
|
||||
'inbuf.py',
|
||||
'indexes.py',
|
||||
'input_callback.py',
|
||||
'nsdel.py',
|
||||
'outbuf.py',
|
||||
'push.py',
|
||||
'pushSAX.py',
|
||||
'pushSAXhtml.py',
|
||||
'reader.py',
|
||||
'reader2.py',
|
||||
'reader3.py',
|
||||
'reader4.py',
|
||||
'reader5.py',
|
||||
'reader6.py',
|
||||
'reader7.py',
|
||||
'reader8.py',
|
||||
'readererr.py',
|
||||
'readernext.py',
|
||||
'regexp.py',
|
||||
'relaxng.py',
|
||||
'resolver.py',
|
||||
'schema.py',
|
||||
'serialize.py',
|
||||
'sync.py',
|
||||
'thread2.py',
|
||||
'tst.py',
|
||||
'tstLastError.py',
|
||||
'tstURI.py',
|
||||
'tstmem.py',
|
||||
'tstxpath.py',
|
||||
'unicode.py',
|
||||
'validDTD.py',
|
||||
'validRNG.py',
|
||||
'validSchemas.py',
|
||||
'validate.py',
|
||||
'walker.py',
|
||||
'xpath.py',
|
||||
'xpathext.py',
|
||||
'xpathleak.py',
|
||||
'xpathns.py',
|
||||
'xpathret.py',
|
||||
]
|
||||
|
||||
foreach file : python_tests
|
||||
test(file, py, args: [ file ],
|
||||
workdir: meson.current_source_dir() / 'tests',
|
||||
env: { 'PYTHONPATH': meson.current_build_dir() })
|
||||
endforeach
|
||||
endif
|
||||
@@ -0,0 +1,3 @@
|
||||
[build-system]
|
||||
requires = ["setuptools"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
@@ -0,0 +1,255 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Setup script for libxml2 and libxslt if found
|
||||
#
|
||||
import sys, os
|
||||
|
||||
try:
|
||||
from setuptools import setup, Extension
|
||||
except ImportError:
|
||||
try:
|
||||
# Using distutils, for python < 3.12
|
||||
from distutils.core import setup, Extension
|
||||
except ImportError:
|
||||
# distutils is not present in python 3.12 and greater
|
||||
print("setuptools is required for python >= 3.12")
|
||||
sys.exit(1)
|
||||
|
||||
# Below ROOT, we expect to find include, include/libxml2, lib and bin.
|
||||
# On *nix, it is not needed (but should not harm),
|
||||
# on Windows, it is set by configure.js.
|
||||
ROOT = r'@prefix@'
|
||||
|
||||
# Thread-enabled libxml2
|
||||
with_threads = @WITH_THREADS@
|
||||
|
||||
# Features of libxml2 requiring external DLLs
|
||||
with_iconv = @WITH_ICONV@
|
||||
with_zlib = @WITH_ZLIB@
|
||||
with_icu = @WITH_ICU@
|
||||
|
||||
icu_series = 69
|
||||
|
||||
if icu_series is not None:
|
||||
icu_series_s = str(icu_series)
|
||||
else:
|
||||
icu_series_s = ''
|
||||
|
||||
# If bundling DLLs, check the following to ensure things are correct
|
||||
# (Check the value of `icu_series` above as well)
|
||||
iconv_dll = 'iconv.dll'
|
||||
zlib_dll = 'zlib1.dll'
|
||||
icu_dlls = ['icuuc%s.dll' % icu_series_s, 'icudt%s.dll' % icu_series_s]
|
||||
|
||||
# If this flag is set (windows only),
|
||||
# a private copy of the dlls are included in the package.
|
||||
# If this flag is not set, the libxml2 and libxslt
|
||||
# dlls must be found somewhere in the PATH at runtime.
|
||||
WITHDLLS = 1 and sys.platform.startswith('win')
|
||||
|
||||
if WITHDLLS:
|
||||
def altImport(s):
|
||||
s = s.replace("import libxml2mod","from libxmlmods import libxml2mod")
|
||||
return s
|
||||
|
||||
def missing(file):
|
||||
if os.access(file, os.R_OK) == 0:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
try:
|
||||
HOME = os.environ['HOME']
|
||||
except:
|
||||
HOME="C:"
|
||||
|
||||
if sys.platform.startswith('win'):
|
||||
libraryPrefix = 'lib'
|
||||
platformLibs = []
|
||||
else:
|
||||
libraryPrefix = ''
|
||||
platformLibs = ["m","z"]
|
||||
|
||||
# those are examined to find
|
||||
# - libxml2/libxml/tree.h
|
||||
# - libxslt/xsltconfig.h
|
||||
includes_dir = [
|
||||
"/usr/include",
|
||||
"/usr/local/include",
|
||||
"/opt/include",
|
||||
os.path.join(ROOT,'include'),
|
||||
HOME
|
||||
];
|
||||
|
||||
xml_includes=""
|
||||
for dir in includes_dir:
|
||||
if not missing(dir + "/libxml2/libxml/tree.h"):
|
||||
xml_includes=dir + "/libxml2"
|
||||
break;
|
||||
|
||||
if xml_includes == "":
|
||||
print("failed to find headers for libxml2: update includes_dir")
|
||||
sys.exit(1)
|
||||
|
||||
# those are added in the linker search path for libraries
|
||||
libdirs = [
|
||||
os.path.join(ROOT,'lib'),
|
||||
]
|
||||
|
||||
xml_files = ["libxml.c", "libxml.py", "libxml_wrap.h", "types.c",
|
||||
"xmlgenerator.py", "README", "TODO", "drv_libxml2.py"]
|
||||
|
||||
xslt_files = ["libxslt-api.xml", "libxslt-python-api.xml",
|
||||
"libxslt.c", "libxsl.py", "libxslt_wrap.h",
|
||||
"xsltgenerator.py"]
|
||||
|
||||
if missing("libxml2-py.c") or missing("libxml2.py"):
|
||||
try:
|
||||
try:
|
||||
import xmlgenerator
|
||||
except:
|
||||
import generator
|
||||
except:
|
||||
print("failed to find and generate stubs for libxml2, aborting ...")
|
||||
print(sys.exc_info()[0], sys.exc_info()[1])
|
||||
sys.exit(1)
|
||||
|
||||
with_xslt=0
|
||||
if missing("libxslt-py.c") or missing("libxslt.py"):
|
||||
if missing("xsltgenerator.py") or missing("libxslt-api.xml"):
|
||||
print("libxslt stub generator not found, libxslt not built")
|
||||
else:
|
||||
try:
|
||||
import xsltgenerator
|
||||
except:
|
||||
print("failed to generate stubs for libxslt, aborting ...")
|
||||
print(sys.exc_info()[0], sys.exc_info()[1])
|
||||
else:
|
||||
head = open("libxsl.py", "r")
|
||||
generated = open("libxsltclass.py", "r")
|
||||
result = open("libxslt.py", "w")
|
||||
for line in head.readlines():
|
||||
if WITHDLLS:
|
||||
result.write(altImport(line))
|
||||
else:
|
||||
result.write(line)
|
||||
for line in generated.readlines():
|
||||
result.write(line)
|
||||
head.close()
|
||||
generated.close()
|
||||
result.close()
|
||||
with_xslt=1
|
||||
else:
|
||||
with_xslt=1
|
||||
|
||||
if with_xslt == 1:
|
||||
xslt_includes=""
|
||||
for dir in includes_dir:
|
||||
if not missing(dir + "/libxslt/xsltconfig.h"):
|
||||
xslt_includes=dir + "/libxslt"
|
||||
break;
|
||||
|
||||
if xslt_includes == "":
|
||||
print("failed to find headers for libxslt: update includes_dir")
|
||||
with_xslt = 0
|
||||
|
||||
if WITHDLLS:
|
||||
# libxml dlls (expected in ROOT/bin)
|
||||
dlls = [ 'libxml2.dll' ]
|
||||
|
||||
if with_zlib == 1:
|
||||
dlls.append(zlib_dll)
|
||||
if with_iconv == 1:
|
||||
dlls.append(iconv_dll)
|
||||
if with_icu == 1:
|
||||
dlls += icu_dlls
|
||||
if with_xslt == 1:
|
||||
dlls += ['libxslt.dll','libexslt.dll']
|
||||
|
||||
packaged_dlls = [os.path.join(ROOT,'bin',dll) for dll in dlls]
|
||||
|
||||
# create __init__.py for the libxmlmods package
|
||||
if not os.path.exists("libxmlmods"):
|
||||
os.mkdir("libxmlmods")
|
||||
open("libxmlmods/__init__.py","w").close()
|
||||
|
||||
packaged_dlls = [os.path.join(ROOT,'bin',dll) for dll in dlls]
|
||||
|
||||
descr = "libxml2 package"
|
||||
modules = [ 'libxml2', 'drv_libxml2' ]
|
||||
if WITHDLLS:
|
||||
modules.append('libxmlmods.__init__')
|
||||
c_files = ['libxml2-py.c', 'libxml.c', 'types.c' ]
|
||||
includes= [xml_includes]
|
||||
libs = [libraryPrefix + "xml2"] + platformLibs
|
||||
macros = []
|
||||
if with_threads:
|
||||
macros.append(('_REENTRANT','1'))
|
||||
if with_xslt == 1:
|
||||
descr = "libxml2 and libxslt package"
|
||||
if not sys.platform.startswith('win'):
|
||||
#
|
||||
# We are gonna build 2 identical shared libs with merge initializing
|
||||
# both libxml2mod and libxsltmod
|
||||
#
|
||||
c_files = c_files + ['libxslt-py.c', 'libxslt.c']
|
||||
xslt_c_files = c_files
|
||||
macros.append(('MERGED_MODULES', '1'))
|
||||
else:
|
||||
#
|
||||
# On windows the MERGED_MODULE option is not needed
|
||||
# (and does not work)
|
||||
#
|
||||
xslt_c_files = ['libxslt-py.c', 'libxslt.c', 'types.c']
|
||||
libs.insert(0, libraryPrefix + 'exslt')
|
||||
libs.insert(0, libraryPrefix + 'xslt')
|
||||
includes.append(xslt_includes)
|
||||
modules.append('libxslt')
|
||||
|
||||
|
||||
extens=[Extension('libxml2mod', c_files, include_dirs=includes,
|
||||
library_dirs=libdirs,
|
||||
libraries=libs, define_macros=macros)]
|
||||
if with_xslt == 1:
|
||||
extens.append(Extension('libxsltmod', xslt_c_files, include_dirs=includes,
|
||||
library_dirs=libdirs,
|
||||
libraries=libs, define_macros=macros))
|
||||
|
||||
if missing("MANIFEST"):
|
||||
|
||||
manifest = open("MANIFEST", "w")
|
||||
manifest.write("setup.py\n")
|
||||
for file in xml_files:
|
||||
manifest.write(file + "\n")
|
||||
if with_xslt == 1:
|
||||
for file in xslt_files:
|
||||
manifest.write(file + "\n")
|
||||
manifest.close()
|
||||
|
||||
if WITHDLLS:
|
||||
ext_package = "libxmlmods"
|
||||
if sys.version >= "2.2":
|
||||
base = "lib/site-packages/"
|
||||
else:
|
||||
base = ""
|
||||
data_files = [(base+"libxmlmods",packaged_dlls)]
|
||||
else:
|
||||
ext_package = None
|
||||
data_files = []
|
||||
|
||||
setup (name = "libxml2-python",
|
||||
# On *nix, the version number is created from setup.py.in
|
||||
# On windows, it is set by configure.js
|
||||
version = "@LIBXML_VERSION@",
|
||||
description = descr,
|
||||
author = "Daniel Veillard",
|
||||
author_email = "veillard@redhat.com",
|
||||
url = "https://gitlab.gnome.org/GNOME/libxml2",
|
||||
license="MIT License",
|
||||
py_modules=modules,
|
||||
ext_modules=extens,
|
||||
ext_package=ext_package,
|
||||
data_files=data_files,
|
||||
)
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
PYTESTS= \
|
||||
build.py \
|
||||
attribs.py \
|
||||
tst.py \
|
||||
tstxpath.py \
|
||||
xpathext.py \
|
||||
push.py \
|
||||
pushSAX.py \
|
||||
pushSAXhtml.py \
|
||||
error.py \
|
||||
serialize.py\
|
||||
validate.py \
|
||||
tstURI.py \
|
||||
cutnpaste.py\
|
||||
xpathret.py \
|
||||
xpath.py \
|
||||
outbuf.py \
|
||||
inbuf.py \
|
||||
input_callback.py \
|
||||
resolver.py \
|
||||
regexp.py \
|
||||
reader.py \
|
||||
reader2.py \
|
||||
reader3.py \
|
||||
reader4.py \
|
||||
reader5.py \
|
||||
reader6.py \
|
||||
reader7.py \
|
||||
reader8.py \
|
||||
readernext.py \
|
||||
walker.py \
|
||||
nsdel.py \
|
||||
ctxterror.py\
|
||||
readererr.py\
|
||||
relaxng.py \
|
||||
schema.py \
|
||||
thread2.py \
|
||||
sync.py \
|
||||
tstLastError.py \
|
||||
indexes.py \
|
||||
dtdvalid.py \
|
||||
tstmem.py \
|
||||
validDTD.py \
|
||||
validSchemas.py \
|
||||
validRNG.py \
|
||||
compareNodes.py \
|
||||
xpathns.py \
|
||||
xpathleak.py \
|
||||
unicode.py
|
||||
|
||||
XMLS= \
|
||||
tst.xml \
|
||||
valid.xml \
|
||||
invalid.xml \
|
||||
test.dtd
|
||||
|
||||
EXTRA_DIST = $(PYTESTS) $(XMLS) setup_test.py
|
||||
|
||||
CLEANFILES = core tmp.xml *.pyc
|
||||
|
||||
if WITH_PYTHON
|
||||
check-local:
|
||||
@for f in $(XMLS) ; do test -f $$f || $(LN_S) $(srcdir)/$$f . ; done
|
||||
@echo "## running Python regression tests"
|
||||
@(export PYTHONPATH="..:../.libs:$(srcdir)/..:$$PYTHONPATH" ; \
|
||||
export LD_LIBRARY_PATH="$(top_builddir)/.libs:$$LD_LIBRARY_PATH" ; \
|
||||
export DYLD_LIBRARY_PATH="$(top_builddir)/.libs:$$DYLD_LIBRARY_PATH" ; \
|
||||
export PATH="$(top_builddir)/.libs:$$PATH" ; \
|
||||
for test in $(PYTESTS) ; do \
|
||||
log=`$(PYTHON) $(srcdir)/$$test` ; \
|
||||
if [ "$$?" -ne 0 ] ; then \
|
||||
echo "-- $$test" ; \
|
||||
echo "$$log" ; \
|
||||
exit 1 ; \
|
||||
fi ; \
|
||||
done)
|
||||
endif
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
#
|
||||
# Testing XML document serialization
|
||||
#
|
||||
doc = libxml2.readDoc(
|
||||
"""<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!DOCTYPE test [
|
||||
<!ELEMENT test (#PCDATA) >
|
||||
<!ATTLIST test xmlns:abc CDATA #FIXED "http://abc.org" >
|
||||
<!ATTLIST test abc:attr CDATA #FIXED "def" >
|
||||
]>
|
||||
<test />
|
||||
""", None, None, libxml2.XML_PARSE_DTDATTR)
|
||||
elem = doc.getRootElement()
|
||||
attr = elem.hasNsProp('attr', 'http://abc.org')
|
||||
print(attr.serialize())
|
||||
if attr == None:
|
||||
print("Failed to find defaulted attribute abc:attr")
|
||||
sys.exit(1)
|
||||
|
||||
doc.freeDoc()
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python3
|
||||
import setup_test
|
||||
import libxml2
|
||||
import sys
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
doc = libxml2.newDoc("1.0")
|
||||
comment = doc.newDocComment("This is a generated document")
|
||||
doc.addChild(comment)
|
||||
pi = libxml2.newPI("test", "PI content")
|
||||
doc.addChild(pi)
|
||||
root = doc.newChild(None, "doc", None)
|
||||
ns = root.newNs("http://example.com/doc", "my")
|
||||
root.setNs(ns)
|
||||
elem = root.newChild(None, "foo", "bar")
|
||||
elem.setBase("http://example.com/imgs")
|
||||
elem.setProp("img", "image.gif")
|
||||
doc.saveFile("tmp.xml")
|
||||
doc.freeDoc()
|
||||
|
||||
doc = libxml2.parseFile("tmp.xml")
|
||||
comment = doc.children
|
||||
if comment.type != "comment" or \
|
||||
comment.content != "This is a generated document":
|
||||
print("error rereading comment")
|
||||
sys.exit(1)
|
||||
pi = comment.next
|
||||
if pi.type != "pi" or pi.name != "test" or pi.content != "PI content":
|
||||
print("error rereading PI")
|
||||
sys.exit(1)
|
||||
root = pi.next
|
||||
if root.name != "doc":
|
||||
print("error rereading root")
|
||||
sys.exit(1)
|
||||
ns = root.ns()
|
||||
if ns.name != "my" or ns.content != "http://example.com/doc":
|
||||
print("error rereading namespace")
|
||||
sys.exit(1)
|
||||
elem = root.children
|
||||
if elem.name != "foo":
|
||||
print("error rereading elem")
|
||||
sys.exit(1)
|
||||
if elem.getBase(None) != "http://example.com/imgs":
|
||||
print("error rereading base")
|
||||
sys.exit(1)
|
||||
if elem.prop("img") != "image.gif":
|
||||
print("error rereading property")
|
||||
sys.exit(1)
|
||||
|
||||
doc.freeDoc()
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
#
|
||||
# Testing XML Node comparison and Node hash-value
|
||||
#
|
||||
doc = libxml2.parseDoc("""<root><foo/></root>""")
|
||||
root = doc.getRootElement()
|
||||
|
||||
# Create two different objects which point to foo
|
||||
foonode1 = root.children
|
||||
foonode2 = root.children
|
||||
|
||||
# Now check that [in]equality tests work ok
|
||||
if not ( foonode1 == foonode2 ):
|
||||
print("Error comparing nodes with ==, nodes should be equal but are unequal")
|
||||
sys.exit(1)
|
||||
if not ( foonode1 != root ):
|
||||
print("Error comparing nodes with ==, nodes should not be equal but are equal")
|
||||
sys.exit(1)
|
||||
if not ( foonode1 != root ):
|
||||
print("Error comparing nodes with !=, nodes should not be equal but are equal")
|
||||
if ( foonode1 != foonode2 ):
|
||||
print("Error comparing nodes with !=, nodes should be equal but are unequal")
|
||||
|
||||
# Next check that the hash function for the objects also works ok
|
||||
if not (hash(foonode1) == hash(foonode2)):
|
||||
print("Error hash values for two equal nodes are different")
|
||||
sys.exit(1)
|
||||
if not (hash(foonode1) != hash(root)):
|
||||
print("Error hash values for two unequal nodes are not different")
|
||||
sys.exit(1)
|
||||
if hash(foonode1) == hash(root):
|
||||
print("Error hash values for two unequal nodes are equal")
|
||||
sys.exit(1)
|
||||
|
||||
# Basic tests successful
|
||||
doc.freeDoc()
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# This test exercise the redirection of error messages with a
|
||||
# functions defined in Python.
|
||||
#
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
expect="""--> (3) xmlns: URI foo is not absolute
|
||||
--> (4) Opening and ending tag mismatch: x line 1 and y
|
||||
"""
|
||||
|
||||
err=""
|
||||
def callback(arg,msg,severity,reserved):
|
||||
global err
|
||||
err = err + "%s (%d) %s" % (arg,severity,msg)
|
||||
|
||||
s = """<x xmlns="foo"></y>"""
|
||||
|
||||
parserCtxt = libxml2.createPushParser(None,"",0,"test.xml")
|
||||
parserCtxt.setErrorHandler(callback, "-->")
|
||||
if parserCtxt.getErrorHandler() != (callback,"-->"):
|
||||
print("getErrorHandler failed")
|
||||
sys.exit(1)
|
||||
parserCtxt.parseChunk(s,len(s),1)
|
||||
doc = parserCtxt.doc()
|
||||
doc.freeDoc()
|
||||
parserCtxt = None
|
||||
|
||||
if err != expect:
|
||||
print("error")
|
||||
print("received %s" %(err))
|
||||
print("expected %s" %(expect))
|
||||
sys.exit(1)
|
||||
|
||||
i = 10000
|
||||
while i > 0:
|
||||
parserCtxt = libxml2.createPushParser(None,"",0,"test.xml")
|
||||
parserCtxt.setErrorHandler(callback, "-->")
|
||||
parserCtxt.parseChunk(s,len(s),1)
|
||||
doc = parserCtxt.doc()
|
||||
doc.freeDoc()
|
||||
parserCtxt = None
|
||||
err = ""
|
||||
i = i - 1
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
#
|
||||
# Testing XML document serialization
|
||||
#
|
||||
source = libxml2.parseDoc("""<?xml version="1.0"?>
|
||||
<root xmlns:foo="http://example.org/foo"
|
||||
xmlns:bar="http://example.org/bar">
|
||||
<include xmlns="http://example.org/include">
|
||||
<fragment><foo:elem bar="tricky"/></fragment>
|
||||
</include>
|
||||
</root>
|
||||
""")
|
||||
|
||||
target = libxml2.parseDoc("""<?xml version="1.0"?>
|
||||
<root xmlns:foobar="http://example.org/bar"/>""")
|
||||
|
||||
fragment = source.xpathEval("//*[name()='fragment']")[0]
|
||||
dest = target.getRootElement()
|
||||
|
||||
# do a cut and paste operation
|
||||
fragment.unlinkNode()
|
||||
dest.addChild(fragment)
|
||||
# do the namespace fixup
|
||||
dest.reconciliateNs(target)
|
||||
|
||||
# The source tree can be freed at that point
|
||||
source.freeDoc()
|
||||
|
||||
# check the resulting tree
|
||||
str = dest.serialize()
|
||||
if str != """<root xmlns:foobar="http://example.org/bar" xmlns:default="http://example.org/include" xmlns:foo="http://example.org/foo"><default:fragment><foo:elem bar="tricky"/></default:fragment></root>""":
|
||||
print("reconciliateNs() failed")
|
||||
sys.exit(1)
|
||||
target.freeDoc()
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python3
|
||||
import setup_test
|
||||
import libxml2
|
||||
import sys
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
dtd="""<!ELEMENT foo EMPTY>"""
|
||||
instance="""<?xml version="1.0"?>
|
||||
<foo></foo>"""
|
||||
|
||||
dtd = libxml2.parseDTD(None, 'test.dtd')
|
||||
ctxt = libxml2.newValidCtxt()
|
||||
doc = libxml2.parseDoc(instance)
|
||||
ret = doc.validateDtd(ctxt, dtd)
|
||||
if ret != 1:
|
||||
print("error doing DTD validation")
|
||||
sys.exit(1)
|
||||
|
||||
doc.freeDoc()
|
||||
dtd.freeDtd()
|
||||
del dtd
|
||||
del ctxt
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# This test exercise the redirection of error messages with a
|
||||
# functions defined in Python.
|
||||
#
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
expect='--> I/O --> warning : --> failed to load "missing.xml": No such file or directory\n'
|
||||
err=""
|
||||
def callback(ctx, str):
|
||||
global err
|
||||
|
||||
err = err + "%s %s" % (ctx, str)
|
||||
|
||||
got_exc = 0
|
||||
libxml2.registerErrorHandler(callback, "-->")
|
||||
try:
|
||||
doc = libxml2.parseFile("missing.xml")
|
||||
except libxml2.parserError:
|
||||
got_exc = 1
|
||||
|
||||
if got_exc == 0:
|
||||
print("Failed to get a parser exception")
|
||||
sys.exit(1)
|
||||
|
||||
if err != expect:
|
||||
print("error")
|
||||
print("received %s" %(err))
|
||||
print("expected %s" %(expect))
|
||||
sys.exit(1)
|
||||
|
||||
i = 10000
|
||||
while i > 0:
|
||||
try:
|
||||
doc = libxml2.parseFile("missing.xml")
|
||||
except libxml2.parserError:
|
||||
got_exc = 1
|
||||
err = ""
|
||||
i = i - 1
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
try:
|
||||
import StringIO
|
||||
str_io = StringIO.StringIO
|
||||
except:
|
||||
import io
|
||||
str_io = io.StringIO
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
i = 0
|
||||
while i < 5000:
|
||||
f = str_io("foobar")
|
||||
buf = libxml2.inputBuffer(f)
|
||||
i = i + 1
|
||||
|
||||
del f
|
||||
del buf
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: ISO-8859-1 -*-
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
ctxt = None
|
||||
|
||||
class callback:
|
||||
def __init__(self, startd, starte, ende, delta, endd):
|
||||
self.startd = startd
|
||||
self.starte = starte
|
||||
self.ende = ende
|
||||
self.endd = endd
|
||||
self.delta = delta
|
||||
self.count = 0
|
||||
|
||||
def startDocument(self):
|
||||
global ctxt
|
||||
if ctxt.byteConsumed() != self.startd:
|
||||
print("document start at wrong index: %d expecting %d\n" % (
|
||||
ctxt.byteConsumed(), self.startd))
|
||||
sys.exit(1)
|
||||
|
||||
def endDocument(self):
|
||||
global ctxt
|
||||
expect = self.ende + self.delta * (self.count - 1) + self.endd
|
||||
if ctxt.byteConsumed() != expect:
|
||||
print("document end at wrong index: %d expecting %d\n" % (
|
||||
ctxt.byteConsumed(), expect))
|
||||
sys.exit(1)
|
||||
|
||||
def startElement(self, tag, attrs):
|
||||
global ctxt
|
||||
if tag == "bar1":
|
||||
expect = self.starte + self.delta * self.count
|
||||
if ctxt.byteConsumed() != expect:
|
||||
print("element start at wrong index: %d expecting %d\n" % (
|
||||
ctxt.byteConsumed(), expect))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def endElement(self, tag):
|
||||
global ctxt
|
||||
if tag == "bar1":
|
||||
expect = self.ende + self.delta * self.count
|
||||
if ctxt.byteConsumed() != expect:
|
||||
print("element end at wrong index: %d expecting %d\n" % (
|
||||
ctxt.byteConsumed(), expect))
|
||||
sys.exit(1)
|
||||
self.count = self.count + 1
|
||||
|
||||
def characters(self, data):
|
||||
pass
|
||||
|
||||
#
|
||||
# First run a pure UTF-8 test
|
||||
#
|
||||
handler = callback(0, 13, 27, 198, 183)
|
||||
ctxt = libxml2.createPushParser(handler, "<foo>\n", 6, "test.xml")
|
||||
chunk = """ <bar1>chars1</bar1>
|
||||
<bar2>chars2</bar2>
|
||||
<bar3>chars3</bar3>
|
||||
<bar4>chars4</bar4>
|
||||
<bar5>chars5</bar5>
|
||||
<bar6><s6</bar6>
|
||||
<bar7>chars7</bar7>
|
||||
<bar8>&8</bar8>
|
||||
<bar9>chars9</bar9>
|
||||
"""
|
||||
i = 0
|
||||
while i < 10000:
|
||||
ctxt.parseChunk(chunk, len(chunk), 0)
|
||||
i = i + 1
|
||||
chunk = "</foo>"
|
||||
ctxt.parseChunk(chunk, len(chunk), 1)
|
||||
ctxt=None
|
||||
|
||||
#
|
||||
# Then run a test relying on ISO-Latin-1
|
||||
#
|
||||
handler = callback(43, 57, 71, 198, 183)
|
||||
chunk="""<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<foo>
|
||||
"""
|
||||
ctxt = libxml2.createPushParser(handler, chunk, len(chunk), "test.xml")
|
||||
chunk = """ <bar1>chars1</bar1>
|
||||
<bar2>chars2</bar2>
|
||||
<bar3>chars3</bar3>
|
||||
<bar4>chàrs4</bar4>
|
||||
<bar5>chars5</bar5>
|
||||
<bar6><s6</bar6>
|
||||
<bar7>chars7</bar7>
|
||||
<bar8>&8</bar8>
|
||||
<bar9>très 9</bar9>
|
||||
"""
|
||||
i = 0
|
||||
while i < 10000:
|
||||
ctxt.parseChunk(chunk, len(chunk), 0)
|
||||
i = i + 1
|
||||
chunk = "</foo>"
|
||||
ctxt.parseChunk(chunk, len(chunk), 1)
|
||||
ctxt=None
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,149 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# This tests custom input callbacks
|
||||
#
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
try:
|
||||
import StringIO
|
||||
str_io = StringIO.StringIO
|
||||
except:
|
||||
import io
|
||||
str_io = io.StringIO
|
||||
|
||||
# We implement a new scheme, py://strings/ that will reference this dictionary
|
||||
pystrings = {
|
||||
'catalogs/catalog.xml' :
|
||||
'''<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE catalog PUBLIC "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN" "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
|
||||
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
|
||||
<rewriteSystem systemIdStartString="http://example.com/dtds/" rewritePrefix="../dtds/"/>
|
||||
</catalog>''',
|
||||
|
||||
'xml/sample.xml' :
|
||||
'''<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE root SYSTEM "http://example.com/dtds/sample.dtd">
|
||||
<root>&sample.entity;</root>''',
|
||||
|
||||
'dtds/sample.dtd' :
|
||||
'''
|
||||
<!ELEMENT root (#PCDATA)>
|
||||
<!ENTITY sample.entity "replacement text">'''
|
||||
}
|
||||
|
||||
prefix = "py://strings/"
|
||||
startURL = prefix + "xml/sample.xml"
|
||||
catURL = prefix + "catalogs/catalog.xml"
|
||||
|
||||
def my_input_cb(URI):
|
||||
if not(URI.startswith(prefix)):
|
||||
return None
|
||||
path = URI[len(prefix):]
|
||||
if path not in pystrings:
|
||||
return None
|
||||
return str_io(pystrings[path])
|
||||
|
||||
|
||||
def run_test(desc, docpath, catalog, exp_status="verified", exp_err=[], test_callback=None,
|
||||
root_name="root", root_content="replacement text"):
|
||||
opts = libxml2.XML_PARSE_DTDLOAD | libxml2.XML_PARSE_NONET | libxml2.XML_PARSE_COMPACT
|
||||
actual_err = []
|
||||
|
||||
def my_global_error_cb(ctx, msg):
|
||||
actual_err.append((-1, msg))
|
||||
def my_ctx_error_cb(arg, msg, severity, reserved):
|
||||
actual_err.append((severity, msg))
|
||||
|
||||
libxml2.registerErrorHandler(my_global_error_cb, None)
|
||||
try:
|
||||
parser = libxml2.createURLParserCtxt(docpath, opts)
|
||||
parser.setErrorHandler(my_ctx_error_cb, None)
|
||||
if catalog is not None:
|
||||
parser.addLocalCatalog(catalog)
|
||||
if test_callback is not None:
|
||||
test_callback()
|
||||
parser.parseDocument()
|
||||
doc = parser.doc()
|
||||
actual_status = "loaded"
|
||||
e = doc.getRootElement()
|
||||
if e.name == root_name and e.content == root_content:
|
||||
actual_status = "verified"
|
||||
doc.freeDoc()
|
||||
except libxml2.parserError:
|
||||
actual_status = "not loaded"
|
||||
|
||||
if actual_status != exp_status:
|
||||
print("Test '%s' failed: expect status '%s', actual '%s'" % (desc, exp_status, actual_status))
|
||||
sys.exit(1)
|
||||
elif actual_err != exp_err:
|
||||
print("Test '%s' failed" % desc)
|
||||
print("Expect errors:")
|
||||
for s,m in exp_err: print(" [%2d] '%s'" % (s,m))
|
||||
print("Actual errors:")
|
||||
for s,m in actual_err: print(" [%2d] '%s'" % (s,m))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# Check that we cannot read custom schema without custom callback
|
||||
run_test(desc="Loading entity without custom callback",
|
||||
docpath=startURL, catalog=None,
|
||||
exp_status="not loaded", exp_err=[
|
||||
(-1, "I/O "),
|
||||
(-1, "warning : "),
|
||||
(-1, "failed to load \"py://strings/xml/sample.xml\": No such file or directory\n")
|
||||
])
|
||||
|
||||
# Register handler and try to load the same entity
|
||||
libxml2.registerInputCallback(my_input_cb)
|
||||
run_test(desc="Loading entity with custom callback",
|
||||
docpath=startURL, catalog=None,
|
||||
exp_status="loaded", exp_err=[
|
||||
( 4, 'failed to load "http://example.com/dtds/sample.dtd": Attempt to load network entity\n'),
|
||||
( 4, "Entity 'sample.entity' not defined\n")
|
||||
])
|
||||
|
||||
# Register a catalog (also accessible via pystr://) and retry
|
||||
run_test(desc="Loading entity with custom callback and catalog",
|
||||
docpath=startURL, catalog=catURL)
|
||||
|
||||
# Unregister custom callback when parser is already created
|
||||
run_test(desc="Loading entity and unregistering callback",
|
||||
docpath=startURL, catalog=catURL,
|
||||
test_callback=lambda: libxml2.popInputCallbacks(),
|
||||
exp_status="loaded", exp_err=[
|
||||
( 3, "failed to load \"py://strings/dtds/sample.dtd\": No such file or directory\n"),
|
||||
( 4, "Entity 'sample.entity' not defined\n")
|
||||
])
|
||||
|
||||
# Try to load the document again
|
||||
run_test(desc="Retry loading document after unregistering callback",
|
||||
docpath=startURL, catalog=catURL,
|
||||
exp_status="not loaded", exp_err=[
|
||||
(-1, "I/O "),
|
||||
(-1, "warning : "),
|
||||
(-1, "failed to load \"py://strings/xml/sample.xml\": No such file or directory\n")
|
||||
])
|
||||
|
||||
# But should be able to read standard I/O yet...
|
||||
run_test(desc="Loading using standard i/o after unregistering callback",
|
||||
docpath="tst.xml", catalog=None,
|
||||
root_name='doc', root_content='bar')
|
||||
|
||||
# Now pop ALL input callbacks, should fail to load even standard I/O
|
||||
try:
|
||||
while True:
|
||||
libxml2.popInputCallbacks()
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
run_test(desc="Loading using standard i/o after unregistering all callbacks",
|
||||
docpath="tst.xml", catalog=None,
|
||||
exp_status="not loaded", exp_err=[
|
||||
(-1, "I/O "),
|
||||
(-1, "warning : "),
|
||||
(-1, "failed to load \"tst.xml\": No such file or directory\n")
|
||||
])
|
||||
|
||||
print("OK")
|
||||
sys.exit(0);
|
||||
@@ -0,0 +1,6 @@
|
||||
<!DOCTYPE doc [
|
||||
<!ELEMENT doc (a, b, a)>
|
||||
<!ELEMENT a EMPTY>
|
||||
<!ELEMENT b EMPTY>
|
||||
]>
|
||||
<doc><b/><a/><b/></doc>
|
||||
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# this test exercise the XPath basic engine, parser, etc, and
|
||||
# allows to detect memory leaks
|
||||
#
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
instance="""<?xml version="1.0"?>
|
||||
<tag xmlns:foo='urn:foo' xmlns:bar='urn:bar' xmlns:baz='urn:baz' />"""
|
||||
|
||||
def namespaceDefs(node):
|
||||
n = node.nsDefs()
|
||||
while n:
|
||||
yield n
|
||||
n = n.next
|
||||
|
||||
def checkNamespaceDefs(node, count):
|
||||
nsList = list(namespaceDefs(node))
|
||||
#print nsList
|
||||
if len(nsList) != count :
|
||||
raise Exception("Error: saw %d namespace declarations. Expected %d" % (len(nsList), count))
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
# Remove single namespace
|
||||
doc = libxml2.parseDoc(instance)
|
||||
node = doc.getRootElement()
|
||||
checkNamespaceDefs(node, 3)
|
||||
ns = node.removeNsDef('urn:bar')
|
||||
checkNamespaceDefs(node, 2)
|
||||
ns.freeNsList()
|
||||
doc.freeDoc()
|
||||
|
||||
# Remove all namespaces
|
||||
doc = libxml2.parseDoc(instance)
|
||||
node = doc.getRootElement()
|
||||
checkNamespaceDefs(node, 3)
|
||||
ns = node.removeNsDef(None)
|
||||
checkNamespaceDefs(node, 0)
|
||||
ns.freeNsList()
|
||||
doc.freeDoc()
|
||||
|
||||
# Remove a namespace referred to by a child
|
||||
doc = libxml2.newDoc("1.0")
|
||||
root = doc.newChild(None, "root", None)
|
||||
namespace = root.newNs("http://example.com/sample", "s")
|
||||
child = root.newChild(namespace, "child", None)
|
||||
root.removeNsDef("http://example.com/sample")
|
||||
doc.reconciliateNs(root)
|
||||
namespace.freeNsList()
|
||||
doc.serialize() # This should not segfault
|
||||
doc.freeDoc()
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
try:
|
||||
import StringIO
|
||||
str_io = StringIO.StringIO
|
||||
except:
|
||||
import io
|
||||
str_io = io.StringIO
|
||||
|
||||
def testSimpleBufferWrites():
|
||||
f = str_io()
|
||||
buf = libxml2.createOutputBuffer(f, "ISO-8859-1")
|
||||
buf.write(3, "foo")
|
||||
buf.writeString("bar")
|
||||
buf.close()
|
||||
|
||||
if f.getvalue() != "foobar":
|
||||
print("Failed to save to StringIO")
|
||||
sys.exit(1)
|
||||
|
||||
def testSaveDocToBuffer():
|
||||
"""
|
||||
Regression test for bug #154294.
|
||||
"""
|
||||
input = '<foo>Hello</foo>'
|
||||
expected = '''\
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<foo>Hello</foo>
|
||||
'''
|
||||
f = str_io()
|
||||
buf = libxml2.createOutputBuffer(f, 'UTF-8')
|
||||
doc = libxml2.parseDoc(input)
|
||||
doc.saveFileTo(buf, 'UTF-8')
|
||||
doc.freeDoc()
|
||||
if f.getvalue() != expected:
|
||||
print('xmlDoc.saveFileTo() call failed.')
|
||||
print(' got: %s' % repr(f.getvalue()))
|
||||
print('expected: %s' % repr(expected))
|
||||
sys.exit(1)
|
||||
|
||||
def testSaveFormattedDocToBuffer():
|
||||
input = '<outer><inner>Some text</inner><inner/></outer>'
|
||||
# The formatted and non-formatted versions of the output.
|
||||
expected = ('''\
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<outer><inner>Some text</inner><inner/></outer>
|
||||
''', '''\
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<outer>
|
||||
<inner>Some text</inner>
|
||||
<inner/>
|
||||
</outer>
|
||||
''')
|
||||
doc = libxml2.parseDoc(input)
|
||||
for i in (0, 1):
|
||||
f = str_io()
|
||||
buf = libxml2.createOutputBuffer(f, 'UTF-8')
|
||||
doc.saveFormatFileTo(buf, 'UTF-8', i)
|
||||
if f.getvalue() != expected[i]:
|
||||
print('xmlDoc.saveFormatFileTo() call failed.')
|
||||
print(' got: %s' % repr(f.getvalue()))
|
||||
print('expected: %s' % repr(expected[i]))
|
||||
sys.exit(1)
|
||||
doc.freeDoc()
|
||||
|
||||
def testSaveIntoOutputBuffer():
|
||||
"""
|
||||
Similar to the previous two tests, except this time we invoke the save
|
||||
methods on the output buffer object and pass in an XML node object.
|
||||
"""
|
||||
input = '<foo>Hello</foo>'
|
||||
expected = '''\
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<foo>Hello</foo>
|
||||
'''
|
||||
f = str_io()
|
||||
doc = libxml2.parseDoc(input)
|
||||
buf = libxml2.createOutputBuffer(f, 'UTF-8')
|
||||
buf.saveFileTo(doc, 'UTF-8')
|
||||
if f.getvalue() != expected:
|
||||
print('outputBuffer.saveFileTo() call failed.')
|
||||
print(' got: %s' % repr(f.getvalue()))
|
||||
print('expected: %s' % repr(expected))
|
||||
sys.exit(1)
|
||||
f = str_io()
|
||||
buf = libxml2.createOutputBuffer(f, 'UTF-8')
|
||||
buf.saveFormatFileTo(doc, 'UTF-8', 1)
|
||||
if f.getvalue() != expected:
|
||||
print('outputBuffer.saveFormatFileTo() call failed.')
|
||||
print(' got: %s' % repr(f.getvalue()))
|
||||
print('expected: %s' % repr(expected))
|
||||
sys.exit(1)
|
||||
doc.freeDoc()
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
testSimpleBufferWrites()
|
||||
testSaveDocToBuffer()
|
||||
testSaveFormattedDocToBuffer()
|
||||
testSaveIntoOutputBuffer()
|
||||
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
ctxt = libxml2.createPushParser(None, "<foo", 4, "test.xml")
|
||||
ctxt.parseChunk("/>", 2, 1)
|
||||
doc = ctxt.doc()
|
||||
ctxt=None
|
||||
if doc.name != "test.xml":
|
||||
print("document name error")
|
||||
sys.exit(1)
|
||||
root = doc.children
|
||||
if root.name != "foo":
|
||||
print("root element name error")
|
||||
sys.exit(1)
|
||||
doc.freeDoc()
|
||||
i = 10000
|
||||
while i > 0:
|
||||
ctxt = libxml2.createPushParser(None, "<foo", 4, "test.xml")
|
||||
ctxt.parseChunk("/>", 2, 1)
|
||||
doc = ctxt.doc()
|
||||
doc.freeDoc()
|
||||
i = i -1
|
||||
ctxt=None
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
log = ""
|
||||
|
||||
class callback:
|
||||
def startDocument(self):
|
||||
global log
|
||||
log = log + "startDocument:"
|
||||
|
||||
def endDocument(self):
|
||||
global log
|
||||
log = log + "endDocument:"
|
||||
|
||||
def startElement(self, tag, attrs):
|
||||
global log
|
||||
log = log + "startElement %s %s:" % (tag, attrs)
|
||||
|
||||
def endElement(self, tag):
|
||||
global log
|
||||
log = log + "endElement %s:" % (tag)
|
||||
|
||||
def characters(self, data):
|
||||
global log
|
||||
log = log + "characters: %s:" % (data)
|
||||
|
||||
def warning(self, msg):
|
||||
global log
|
||||
log = log + "warning: %s:" % (msg)
|
||||
|
||||
def error(self, msg):
|
||||
global log
|
||||
log = log + "error: %s:" % (msg)
|
||||
|
||||
def fatalError(self, msg):
|
||||
global log
|
||||
log = log + "fatalError: %s:" % (msg)
|
||||
|
||||
handler = callback()
|
||||
|
||||
ctxt = libxml2.createPushParser(handler, "<foo", 4, "test.xml")
|
||||
chunk = " url='tst'>b"
|
||||
ctxt.parseChunk(chunk, len(chunk), 0)
|
||||
chunk = "ar</foo>"
|
||||
ctxt.parseChunk(chunk, len(chunk), 1)
|
||||
ctxt=None
|
||||
|
||||
reference = "startDocument:startElement foo {'url': 'tst'}:characters: bar:endElement foo:endDocument:"
|
||||
if log != reference:
|
||||
print("Error got: %s" % log)
|
||||
print("Exprected: %s" % reference)
|
||||
sys.exit(1)
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
log = ""
|
||||
|
||||
class callback:
|
||||
def startDocument(self):
|
||||
global log
|
||||
log = log + "startDocument:"
|
||||
|
||||
def endDocument(self):
|
||||
global log
|
||||
log = log + "endDocument:"
|
||||
|
||||
def startElement(self, tag, attrs):
|
||||
global log
|
||||
log = log + "startElement %s %s:" % (tag, attrs)
|
||||
|
||||
def endElement(self, tag):
|
||||
global log
|
||||
log = log + "endElement %s:" % (tag)
|
||||
|
||||
def characters(self, data):
|
||||
global log
|
||||
log = log + "characters: %s:" % (data)
|
||||
|
||||
def warning(self, msg):
|
||||
global log
|
||||
log = log + "warning: %s:" % (msg)
|
||||
|
||||
def error(self, msg):
|
||||
global log
|
||||
log = log + "error: %s:" % (msg)
|
||||
|
||||
def fatalError(self, msg):
|
||||
global log
|
||||
log = log + "fatalError: %s:" % (msg)
|
||||
|
||||
handler = callback()
|
||||
|
||||
ctxt = libxml2.htmlCreatePushParser(handler, "<foo", 4, "test.xml")
|
||||
chunk = " url='tst'>b"
|
||||
ctxt.htmlParseChunk(chunk, len(chunk), 0)
|
||||
chunk = "ar</foo>"
|
||||
ctxt.htmlParseChunk(chunk, len(chunk), 1)
|
||||
ctxt=None
|
||||
|
||||
reference = """startDocument:startElement html None:startElement body None:startElement foo {'url': 'tst'}:characters: bar:endElement foo:endElement body:endElement html:endDocument:"""
|
||||
if log != reference:
|
||||
print("Error got: %s" % log)
|
||||
print("Exprected: %s" % reference)
|
||||
sys.exit(1)
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,446 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: ISO-8859-1 -*-
|
||||
#
|
||||
# this tests the basic APIs of the XmlTextReader interface
|
||||
#
|
||||
import setup_test
|
||||
import libxml2
|
||||
import sys
|
||||
try:
|
||||
import StringIO
|
||||
str_io = StringIO.StringIO
|
||||
except:
|
||||
import io
|
||||
str_io = io.StringIO
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
f = str_io("""<a><b b1="b1"/><c>content of c</c></a>""")
|
||||
input = libxml2.inputBuffer(f)
|
||||
reader = input.newTextReader("test1")
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("test1: 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("test1: Error reading the first element")
|
||||
sys.exit(1)
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("test1: 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("test1: Error reading the second element")
|
||||
sys.exit(1)
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("test1: 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("test1: Error reading the third element")
|
||||
sys.exit(1)
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("test1: 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("test1: Error reading the text node")
|
||||
sys.exit(1)
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("test1: 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("test1: Error reading the end of third element")
|
||||
sys.exit(1)
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("test1: 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("test1: Error reading the end of first element")
|
||||
sys.exit(1)
|
||||
ret = reader.Read()
|
||||
if ret != 0:
|
||||
print("test1: Error reading to end of document")
|
||||
sys.exit(1)
|
||||
|
||||
#
|
||||
# example from the XmlTextReader docs
|
||||
#
|
||||
f = str_io("""<test xmlns:dt="urn:datatypes" dt:type="int"/>""")
|
||||
input = libxml2.inputBuffer(f)
|
||||
reader = input.newTextReader("test2")
|
||||
|
||||
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)
|
||||
|
||||
#
|
||||
# example from the XmlTextReader docs
|
||||
#
|
||||
f = str_io("""<root xmlns:a="urn:456">
|
||||
<item>
|
||||
<ref href="a:b"/>
|
||||
</item>
|
||||
</root>""")
|
||||
input = libxml2.inputBuffer(f)
|
||||
reader = input.newTextReader("test3")
|
||||
|
||||
ret = reader.Read()
|
||||
while ret == 1:
|
||||
if reader.Name() == "ref":
|
||||
if reader.LookupNamespace("a") != "urn:456":
|
||||
print("error resolving namespace prefix")
|
||||
sys.exit(1)
|
||||
break
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("Error finding the ref element")
|
||||
sys.exit(1)
|
||||
|
||||
#
|
||||
# Home made example for the various attribute access functions
|
||||
#
|
||||
f = str_io("""<testattr xmlns="urn:1" xmlns:a="urn:2" b="b" a:b="a:b"/>""")
|
||||
input = libxml2.inputBuffer(f)
|
||||
reader = input.newTextReader("test4")
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("Error reading the testattr element")
|
||||
sys.exit(1)
|
||||
#
|
||||
# Attribute exploration by index
|
||||
#
|
||||
if reader.MoveToAttributeNo(0) != 1:
|
||||
print("Failed moveToAttribute(0)")
|
||||
sys.exit(1)
|
||||
if reader.Value() != "urn:1":
|
||||
print("Failed to read attribute(0)")
|
||||
sys.exit(1)
|
||||
if reader.Name() != "xmlns":
|
||||
print("Failed to read attribute(0) name")
|
||||
sys.exit(1)
|
||||
if reader.MoveToAttributeNo(1) != 1:
|
||||
print("Failed moveToAttribute(1)")
|
||||
sys.exit(1)
|
||||
if reader.Value() != "urn:2":
|
||||
print("Failed to read attribute(1)")
|
||||
sys.exit(1)
|
||||
if reader.Name() != "xmlns:a":
|
||||
print("Failed to read attribute(1) name")
|
||||
sys.exit(1)
|
||||
if reader.MoveToAttributeNo(2) != 1:
|
||||
print("Failed moveToAttribute(2)")
|
||||
sys.exit(1)
|
||||
if reader.Value() != "b":
|
||||
print("Failed to read attribute(2)")
|
||||
sys.exit(1)
|
||||
if reader.Name() != "b":
|
||||
print("Failed to read attribute(2) name")
|
||||
sys.exit(1)
|
||||
if reader.MoveToAttributeNo(3) != 1:
|
||||
print("Failed moveToAttribute(3)")
|
||||
sys.exit(1)
|
||||
if reader.Value() != "a:b":
|
||||
print("Failed to read attribute(3)")
|
||||
sys.exit(1)
|
||||
if reader.Name() != "a:b":
|
||||
print("Failed to read attribute(3) name")
|
||||
sys.exit(1)
|
||||
#
|
||||
# Attribute exploration by name
|
||||
#
|
||||
if reader.MoveToAttribute("xmlns") != 1:
|
||||
print("Failed moveToAttribute('xmlns')")
|
||||
sys.exit(1)
|
||||
if reader.Value() != "urn:1":
|
||||
print("Failed to read attribute('xmlns')")
|
||||
sys.exit(1)
|
||||
if reader.MoveToAttribute("xmlns:a") != 1:
|
||||
print("Failed moveToAttribute('xmlns')")
|
||||
sys.exit(1)
|
||||
if reader.Value() != "urn:2":
|
||||
print("Failed to read attribute('xmlns:a')")
|
||||
sys.exit(1)
|
||||
if reader.MoveToAttribute("b") != 1:
|
||||
print("Failed moveToAttribute('b')")
|
||||
sys.exit(1)
|
||||
if reader.Value() != "b":
|
||||
print("Failed to read attribute('b')")
|
||||
sys.exit(1)
|
||||
if reader.MoveToAttribute("a:b") != 1:
|
||||
print("Failed moveToAttribute('a:b')")
|
||||
sys.exit(1)
|
||||
if reader.Value() != "a:b":
|
||||
print("Failed to read attribute('a:b')")
|
||||
sys.exit(1)
|
||||
if reader.MoveToAttributeNs("b", "urn:2") != 1:
|
||||
print("Failed moveToAttribute('b', 'urn:2')")
|
||||
sys.exit(1)
|
||||
if reader.Value() != "a:b":
|
||||
print("Failed to read attribute('b', 'urn:2')")
|
||||
sys.exit(1)
|
||||
#
|
||||
# Go back and read in sequence
|
||||
#
|
||||
if reader.MoveToElement() != 1:
|
||||
print("Failed to move back to element")
|
||||
sys.exit(1)
|
||||
if reader.MoveToFirstAttribute() != 1:
|
||||
print("Failed to move to first attribute")
|
||||
sys.exit(1)
|
||||
if reader.Value() != "urn:1":
|
||||
print("Failed to read attribute(0)")
|
||||
sys.exit(1)
|
||||
if reader.Name() != "xmlns":
|
||||
print("Failed to read attribute(0) name")
|
||||
sys.exit(1)
|
||||
if reader.MoveToNextAttribute() != 1:
|
||||
print("Failed to move to next attribute")
|
||||
sys.exit(1)
|
||||
if reader.Value() != "urn:2":
|
||||
print("Failed to read attribute(1)")
|
||||
sys.exit(1)
|
||||
if reader.Name() != "xmlns:a":
|
||||
print("Failed to read attribute(1) name")
|
||||
sys.exit(1)
|
||||
if reader.MoveToNextAttribute() != 1:
|
||||
print("Failed to move to next attribute")
|
||||
sys.exit(1)
|
||||
if reader.Value() != "b":
|
||||
print("Failed to read attribute(2)")
|
||||
sys.exit(1)
|
||||
if reader.Name() != "b":
|
||||
print("Failed to read attribute(2) name")
|
||||
sys.exit(1)
|
||||
if reader.MoveToNextAttribute() != 1:
|
||||
print("Failed to move to next attribute")
|
||||
sys.exit(1)
|
||||
if reader.Value() != "a:b":
|
||||
print("Failed to read attribute(3)")
|
||||
sys.exit(1)
|
||||
if reader.Name() != "a:b":
|
||||
print("Failed to read attribute(3) name")
|
||||
sys.exit(1)
|
||||
if reader.MoveToNextAttribute() != 0:
|
||||
print("Failed to detect last attribute")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
#
|
||||
# a couple of tests for namespace nodes
|
||||
#
|
||||
f = str_io("""<a xmlns="http://example.com/foo"/>""")
|
||||
input = libxml2.inputBuffer(f)
|
||||
reader = input.newTextReader("test6")
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("test6: failed to Read()")
|
||||
sys.exit(1)
|
||||
ret = reader.MoveToFirstAttribute()
|
||||
if ret != 1:
|
||||
print("test6: failed to MoveToFirstAttribute()")
|
||||
sys.exit(1)
|
||||
if reader.NamespaceUri() != "http://www.w3.org/2000/xmlns/" or \
|
||||
reader.LocalName() != "xmlns" or reader.Name() != "xmlns" or \
|
||||
reader.Value() != "http://example.com/foo" or reader.NodeType() != 2:
|
||||
print("test6: failed to read the namespace node")
|
||||
sys.exit(1)
|
||||
|
||||
f = str_io("""<a xmlns:prefix="http://example.com/foo"/>""")
|
||||
input = libxml2.inputBuffer(f)
|
||||
reader = input.newTextReader("test7")
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("test7: failed to Read()")
|
||||
sys.exit(1)
|
||||
ret = reader.MoveToFirstAttribute()
|
||||
if ret != 1:
|
||||
print("test7: failed to MoveToFirstAttribute()")
|
||||
sys.exit(1)
|
||||
if reader.NamespaceUri() != "http://www.w3.org/2000/xmlns/" or \
|
||||
reader.LocalName() != "prefix" or reader.Name() != "xmlns:prefix" or \
|
||||
reader.Value() != "http://example.com/foo" or reader.NodeType() != 2:
|
||||
print("test7: failed to read the namespace node")
|
||||
sys.exit(1)
|
||||
|
||||
#
|
||||
# Test for a limit case:
|
||||
#
|
||||
f = str_io("""<a/>""")
|
||||
input = libxml2.inputBuffer(f)
|
||||
reader = input.newTextReader("test8")
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("test8: failed to read the node")
|
||||
sys.exit(1)
|
||||
if reader.Name() != "a" or reader.IsEmptyElement() != 1:
|
||||
print("test8: failed to analyze the node")
|
||||
sys.exit(1)
|
||||
ret = reader.Read()
|
||||
if ret != 0:
|
||||
print("test8: failed to detect the EOF")
|
||||
sys.exit(1)
|
||||
|
||||
#
|
||||
# Another test provided by Stéphane Bidoul and checked with C#
|
||||
#
|
||||
def tst_reader(s):
|
||||
f = str_io(s)
|
||||
input = libxml2.inputBuffer(f)
|
||||
reader = input.newTextReader("tst")
|
||||
res = ""
|
||||
while reader.Read():
|
||||
res=res + "%s (%s) [%s] %d %d\n" % (reader.NodeType(),reader.Name(),
|
||||
reader.Value(), reader.IsEmptyElement(),
|
||||
reader.Depth())
|
||||
if reader.NodeType() == 1: # Element
|
||||
while reader.MoveToNextAttribute():
|
||||
res = res + "-- %s (%s) [%s] %d %d\n" % (reader.NodeType(),
|
||||
reader.Name(),reader.Value(),
|
||||
reader.IsEmptyElement(), reader.Depth())
|
||||
return res
|
||||
|
||||
doc="""<a><b b1="b1"/><c>content of c</c></a>"""
|
||||
expect="""1 (a) [None] 0 0
|
||||
1 (b) [None] 1 1
|
||||
-- 2 (b1) [b1] 0 2
|
||||
1 (c) [None] 0 1
|
||||
3 (#text) [content of c] 0 2
|
||||
15 (c) [None] 0 1
|
||||
15 (a) [None] 0 0
|
||||
"""
|
||||
res = tst_reader(doc)
|
||||
if res != expect:
|
||||
print("test5 failed")
|
||||
print(res)
|
||||
sys.exit(1)
|
||||
|
||||
doc="""<test><b/><c/></test>"""
|
||||
expect="""1 (test) [None] 0 0
|
||||
1 (b) [None] 1 1
|
||||
1 (c) [None] 1 1
|
||||
15 (test) [None] 0 0
|
||||
"""
|
||||
res = tst_reader(doc)
|
||||
if res != expect:
|
||||
print("test9 failed")
|
||||
print(res)
|
||||
sys.exit(1)
|
||||
|
||||
doc="""<a><b>bbb</b><c>ccc</c></a>"""
|
||||
expect="""1 (a) [None] 0 0
|
||||
1 (b) [None] 0 1
|
||||
3 (#text) [bbb] 0 2
|
||||
15 (b) [None] 0 1
|
||||
1 (c) [None] 0 1
|
||||
3 (#text) [ccc] 0 2
|
||||
15 (c) [None] 0 1
|
||||
15 (a) [None] 0 0
|
||||
"""
|
||||
res = tst_reader(doc)
|
||||
if res != expect:
|
||||
print("test10 failed")
|
||||
print(res)
|
||||
sys.exit(1)
|
||||
|
||||
doc="""<test a="a"/>"""
|
||||
expect="""1 (test) [None] 1 0
|
||||
-- 2 (a) [a] 0 1
|
||||
"""
|
||||
res = tst_reader(doc)
|
||||
if res != expect:
|
||||
print("test11 failed")
|
||||
print(res)
|
||||
sys.exit(1)
|
||||
|
||||
doc="""<test><a>aaa</a><b/></test>"""
|
||||
expect="""1 (test) [None] 0 0
|
||||
1 (a) [None] 0 1
|
||||
3 (#text) [aaa] 0 2
|
||||
15 (a) [None] 0 1
|
||||
1 (b) [None] 1 1
|
||||
15 (test) [None] 0 0
|
||||
"""
|
||||
res = tst_reader(doc)
|
||||
if res != expect:
|
||||
print("test12 failed")
|
||||
print(res)
|
||||
sys.exit(1)
|
||||
|
||||
doc="""<test><p></p></test>"""
|
||||
expect="""1 (test) [None] 0 0
|
||||
1 (p) [None] 0 1
|
||||
15 (p) [None] 0 1
|
||||
15 (test) [None] 0 0
|
||||
"""
|
||||
res = tst_reader(doc)
|
||||
if res != expect:
|
||||
print("test13 failed")
|
||||
print(res)
|
||||
sys.exit(1)
|
||||
|
||||
doc="""<p></p>"""
|
||||
expect="""1 (p) [None] 0 0
|
||||
15 (p) [None] 0 0
|
||||
"""
|
||||
res = tst_reader(doc)
|
||||
if res != expect:
|
||||
print("test14 failed")
|
||||
print(res)
|
||||
sys.exit(1)
|
||||
|
||||
#
|
||||
# test from bug #108801
|
||||
#
|
||||
doc="""<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
|
||||
]>
|
||||
|
||||
<article>
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
</article>
|
||||
"""
|
||||
expect="""10 (article) [None] 0 0
|
||||
1 (article) [None] 0 0
|
||||
3 (#text) [
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
] 0 1
|
||||
15 (article) [None] 0 0
|
||||
"""
|
||||
res = tst_reader(doc)
|
||||
if res != expect:
|
||||
print("test15 failed")
|
||||
print(res)
|
||||
sys.exit(1)
|
||||
|
||||
#
|
||||
# cleanup for memory allocation counting
|
||||
#
|
||||
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)))
|
||||
@@ -0,0 +1,337 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# this tests the DTD validation with the XmlTextReader interface
|
||||
#
|
||||
import sys
|
||||
import glob
|
||||
import os
|
||||
import setup_test
|
||||
import libxml2
|
||||
try:
|
||||
import StringIO
|
||||
str_io = StringIO.StringIO
|
||||
except:
|
||||
import io
|
||||
str_io = io.StringIO
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
err = ""
|
||||
basedir = os.path.dirname(os.path.realpath(__file__))
|
||||
dir_prefix = os.path.realpath(os.path.join(basedir, "..", "..", "test", "valid"))
|
||||
|
||||
# This dictionary reflects the contents of the files
|
||||
# ../../test/valid/*.xml.err that are not empty, except that
|
||||
# the file paths in the messages start with ../../test/
|
||||
|
||||
expect = {
|
||||
'766956':
|
||||
"""{0}/dtds/766956.dtd:2: parser error : PEReference: expecting ';'
|
||||
%ä%ent;
|
||||
^
|
||||
{0}/dtds/766956.dtd:2: parser error : Content error in the external subset
|
||||
%ä%ent;
|
||||
^
|
||||
Entity: line 1:
|
||||
value
|
||||
^
|
||||
""".format(dir_prefix),
|
||||
'781333':
|
||||
"""{0}/781333.xml:4: element a: validity error : Element a content does not follow the DTD, expecting ( ..., got
|
||||
<a/>
|
||||
^
|
||||
{0}/781333.xml:5: element a: validity error : Element a content does not follow the DTD, Expecting more children
|
||||
|
||||
^
|
||||
""".format(dir_prefix),
|
||||
'cond_sect2':
|
||||
"""{0}/dtds/cond_sect2.dtd:15: parser error : Parameter entity must match extSubsetDecl
|
||||
%ent;
|
||||
^
|
||||
Entity: line 1:
|
||||
]]>
|
||||
^
|
||||
{0}/dtds/cond_sect2.dtd:15: parser error : Content error in the external subset
|
||||
%ent;
|
||||
^
|
||||
Entity: line 1:
|
||||
]]>
|
||||
^
|
||||
""".format(dir_prefix),
|
||||
'rss':
|
||||
"""{0}/rss.xml:177: element rss: validity error : Element rss does not carry attribute version
|
||||
</rss>
|
||||
^
|
||||
""".format(dir_prefix),
|
||||
't8':
|
||||
"""{0}/t8.xml:6: parser error : Content error in the internal subset
|
||||
%defroot; %defmiddle; %deftest;
|
||||
^
|
||||
Entity: line 1:
|
||||
<!ELEMENT root (middle) >
|
||||
^
|
||||
""".format(dir_prefix),
|
||||
't8a':
|
||||
"""{0}/t8a.xml:6: parser error : Content error in the internal subset
|
||||
%defroot;%defmiddle;%deftest;
|
||||
^
|
||||
Entity: line 1:
|
||||
<!ELEMENT root (middle) >
|
||||
^
|
||||
""".format(dir_prefix),
|
||||
'xlink':
|
||||
"""{0}/xlink.xml:450: element termdef: validity error : ID dt-arc already defined
|
||||
<p><termdef id="dt-arc" term="Arc">An <ter
|
||||
^
|
||||
validity error : attribute def line 199 references an unknown ID "dt-xlg"
|
||||
""".format(dir_prefix),
|
||||
}
|
||||
|
||||
# Add prefix_dir and extension to the keys
|
||||
expect = {os.path.join(dir_prefix, key + ".xml"): val for key, val in expect.items()}
|
||||
|
||||
def callback(ctx, str):
|
||||
global err
|
||||
err = err + "%s" % (str)
|
||||
libxml2.registerErrorHandler(callback, "")
|
||||
|
||||
parsing_error_files = ["766956", "cond_sect2", "t8", "t8a", "pe-in-text-decl"]
|
||||
expect_parsing_error = [os.path.join(dir_prefix, f + ".xml") for f in parsing_error_files]
|
||||
|
||||
valid_files = glob.glob(os.path.join(dir_prefix, "*.x*"))
|
||||
assert valid_files, "found no valid files in '{}'".format(dir_prefix)
|
||||
valid_files.sort()
|
||||
failures = 0
|
||||
for file in valid_files:
|
||||
err = ""
|
||||
reader = libxml2.newTextReaderFilename(file)
|
||||
#print "%s:" % (file)
|
||||
reader.SetParserProp(libxml2.PARSER_VALIDATE, 1)
|
||||
ret = reader.Read()
|
||||
while ret == 1:
|
||||
ret = reader.Read()
|
||||
if ret != 0 and file not in expect_parsing_error:
|
||||
print("Error parsing and validating %s" % (file))
|
||||
#sys.exit(1)
|
||||
if file in expect and err != expect[file]:
|
||||
failures += 1
|
||||
print("Error: ", err)
|
||||
if file in expect:
|
||||
print("Expected: ", expect[file])
|
||||
|
||||
if failures:
|
||||
print("Failed %d tests" % failures)
|
||||
sys.exit(1)
|
||||
|
||||
#
|
||||
# another separate test based on Stephane Bidoul one
|
||||
#
|
||||
s = """
|
||||
<!DOCTYPE test [
|
||||
<!ELEMENT test (x,b)>
|
||||
<!ELEMENT x (c)>
|
||||
<!ELEMENT b (#PCDATA)>
|
||||
<!ELEMENT c (#PCDATA)>
|
||||
<!ENTITY x "<x><c>xxx</c></x>">
|
||||
]>
|
||||
<test>
|
||||
&x;
|
||||
<b>bbb</b>
|
||||
</test>
|
||||
"""
|
||||
expect="""10,test
|
||||
1,test
|
||||
14,#text
|
||||
1,x
|
||||
1,c
|
||||
3,#text
|
||||
15,c
|
||||
15,x
|
||||
14,#text
|
||||
1,b
|
||||
3,#text
|
||||
15,b
|
||||
14,#text
|
||||
15,test
|
||||
"""
|
||||
res=""
|
||||
err=""
|
||||
|
||||
input = libxml2.inputBuffer(str_io(s))
|
||||
reader = input.newTextReader("test2")
|
||||
reader.SetParserProp(libxml2.PARSER_LOADDTD,1)
|
||||
reader.SetParserProp(libxml2.PARSER_DEFAULTATTRS,1)
|
||||
reader.SetParserProp(libxml2.PARSER_SUBST_ENTITIES,1)
|
||||
reader.SetParserProp(libxml2.PARSER_VALIDATE,1)
|
||||
while reader.Read() == 1:
|
||||
res = res + "%s,%s\n" % (reader.NodeType(),reader.Name())
|
||||
|
||||
if res != expect:
|
||||
print("test2 failed: unexpected output")
|
||||
print(res)
|
||||
sys.exit(1)
|
||||
if err != "":
|
||||
print("test2 failed: validation error found")
|
||||
print(err)
|
||||
sys.exit(1)
|
||||
|
||||
#
|
||||
# Another test for external entity parsing and validation
|
||||
#
|
||||
|
||||
s = """<!DOCTYPE test [
|
||||
<!ELEMENT test (x)>
|
||||
<!ELEMENT x (#PCDATA)>
|
||||
<!ENTITY e SYSTEM "tst.ent">
|
||||
]>
|
||||
<test>
|
||||
&e;
|
||||
</test>
|
||||
"""
|
||||
tst_ent = """<x>hello</x>"""
|
||||
expect="""10 test
|
||||
1 test
|
||||
14 #text
|
||||
1 x
|
||||
3 #text
|
||||
15 x
|
||||
14 #text
|
||||
15 test
|
||||
"""
|
||||
res=""
|
||||
|
||||
def myResolver(URL, ID, ctxt):
|
||||
if URL == "tst.ent":
|
||||
return(str_io(tst_ent))
|
||||
return None
|
||||
|
||||
libxml2.setEntityLoader(myResolver)
|
||||
|
||||
input = libxml2.inputBuffer(str_io(s))
|
||||
reader = input.newTextReader("test3")
|
||||
reader.SetParserProp(libxml2.PARSER_LOADDTD,1)
|
||||
reader.SetParserProp(libxml2.PARSER_DEFAULTATTRS,1)
|
||||
reader.SetParserProp(libxml2.PARSER_SUBST_ENTITIES,1)
|
||||
reader.SetParserProp(libxml2.PARSER_VALIDATE,1)
|
||||
while reader.Read() == 1:
|
||||
res = res + "%s %s\n" % (reader.NodeType(),reader.Name())
|
||||
|
||||
if res != expect:
|
||||
print("test3 failed: unexpected output")
|
||||
print(res)
|
||||
sys.exit(1)
|
||||
if err != "":
|
||||
print("test3 failed: validation error found")
|
||||
print(err)
|
||||
sys.exit(1)
|
||||
|
||||
#
|
||||
# Another test for recursive entity parsing, validation, and replacement of
|
||||
# entities, making sure the entity ref node doesn't show up in that case
|
||||
#
|
||||
|
||||
s = """<!DOCTYPE test [
|
||||
<!ELEMENT test (x, x)>
|
||||
<!ELEMENT x (y)>
|
||||
<!ELEMENT y (#PCDATA)>
|
||||
<!ENTITY x "<x>&y;</x>">
|
||||
<!ENTITY y "<y>yyy</y>">
|
||||
]>
|
||||
<test>
|
||||
&x;
|
||||
&x;
|
||||
</test>"""
|
||||
expect="""10 test 0
|
||||
1 test 0
|
||||
14 #text 1
|
||||
1 x 1
|
||||
1 y 2
|
||||
3 #text 3
|
||||
15 y 2
|
||||
15 x 1
|
||||
14 #text 1
|
||||
1 x 1
|
||||
1 y 2
|
||||
3 #text 3
|
||||
15 y 2
|
||||
15 x 1
|
||||
14 #text 1
|
||||
15 test 0
|
||||
"""
|
||||
res=""
|
||||
err=""
|
||||
|
||||
input = libxml2.inputBuffer(str_io(s))
|
||||
reader = input.newTextReader("test4")
|
||||
reader.SetParserProp(libxml2.PARSER_LOADDTD,1)
|
||||
reader.SetParserProp(libxml2.PARSER_DEFAULTATTRS,1)
|
||||
reader.SetParserProp(libxml2.PARSER_SUBST_ENTITIES,1)
|
||||
reader.SetParserProp(libxml2.PARSER_VALIDATE,1)
|
||||
while reader.Read() == 1:
|
||||
res = res + "%s %s %d\n" % (reader.NodeType(),reader.Name(),reader.Depth())
|
||||
|
||||
if res != expect:
|
||||
print("test4 failed: unexpected output")
|
||||
print(res)
|
||||
sys.exit(1)
|
||||
if err != "":
|
||||
print("test4 failed: validation error found")
|
||||
print(err)
|
||||
sys.exit(1)
|
||||
|
||||
#
|
||||
# The same test but without entity substitution this time
|
||||
#
|
||||
|
||||
s = """<!DOCTYPE test [
|
||||
<!ELEMENT test (x, x)>
|
||||
<!ELEMENT x (y)>
|
||||
<!ELEMENT y (#PCDATA)>
|
||||
<!ENTITY x "<x>&y;</x>">
|
||||
<!ENTITY y "<y>yyy</y>">
|
||||
]>
|
||||
<test>
|
||||
&x;
|
||||
&x;
|
||||
</test>"""
|
||||
expect="""10 test 0
|
||||
1 test 0
|
||||
14 #text 1
|
||||
5 x 1
|
||||
14 #text 1
|
||||
5 x 1
|
||||
14 #text 1
|
||||
15 test 0
|
||||
"""
|
||||
res=""
|
||||
err=""
|
||||
|
||||
input = libxml2.inputBuffer(str_io(s))
|
||||
reader = input.newTextReader("test5")
|
||||
reader.SetParserProp(libxml2.PARSER_VALIDATE,1)
|
||||
while reader.Read() == 1:
|
||||
res = res + "%s %s %d\n" % (reader.NodeType(),reader.Name(),reader.Depth())
|
||||
|
||||
if res != expect:
|
||||
print("test5 failed: unexpected output")
|
||||
print(res)
|
||||
sys.exit(1)
|
||||
if err != "":
|
||||
print("test5 failed: validation error found")
|
||||
print(err)
|
||||
sys.exit(1)
|
||||
|
||||
#
|
||||
# cleanup
|
||||
#
|
||||
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)))
|
||||
@@ -0,0 +1,160 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# this tests the entities substitutions with the XmlTextReader interface
|
||||
#
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
try:
|
||||
import StringIO
|
||||
str_io = StringIO.StringIO
|
||||
except:
|
||||
import io
|
||||
str_io = io.StringIO
|
||||
|
||||
docstr="""<?xml version='1.0'?>
|
||||
<!DOCTYPE doc [
|
||||
<!ENTITY tst "<p>test</p>">
|
||||
]>
|
||||
<doc>&tst;</doc>"""
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
#
|
||||
# First test, normal don't substitute entities.
|
||||
#
|
||||
f = str_io(docstr)
|
||||
input = libxml2.inputBuffer(f)
|
||||
reader = input.newTextReader("test_noent")
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("Error reading to root")
|
||||
sys.exit(1)
|
||||
if reader.Name() == "doc" or reader.NodeType() == 10:
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("Error reading to root")
|
||||
sys.exit(1)
|
||||
if reader.Name() != "doc" or reader.NodeType() != 1:
|
||||
print("test_normal: Error reading the root element")
|
||||
sys.exit(1)
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("test_normal: Error reading to the entity")
|
||||
sys.exit(1)
|
||||
if reader.Name() != "tst" or reader.NodeType() != 5:
|
||||
print("test_normal: Error reading the entity")
|
||||
sys.exit(1)
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("test_normal: Error reading to the end of root")
|
||||
sys.exit(1)
|
||||
if reader.Name() != "doc" or reader.NodeType() != 15:
|
||||
print("test_normal: Error reading the end of the root element")
|
||||
sys.exit(1)
|
||||
ret = reader.Read()
|
||||
if ret != 0:
|
||||
print("test_normal: Error detecting the end")
|
||||
sys.exit(1)
|
||||
|
||||
#
|
||||
# Second test, completely substitute the entities.
|
||||
#
|
||||
f = str_io(docstr)
|
||||
input = libxml2.inputBuffer(f)
|
||||
reader = input.newTextReader("test_noent")
|
||||
reader.SetParserProp(libxml2.PARSER_SUBST_ENTITIES, 1)
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("Error reading to root")
|
||||
sys.exit(1)
|
||||
if reader.Name() == "doc" or reader.NodeType() == 10:
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("Error reading to root")
|
||||
sys.exit(1)
|
||||
if reader.Name() != "doc" or reader.NodeType() != 1:
|
||||
print("test_noent: Error reading the root element")
|
||||
sys.exit(1)
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("test_noent: Error reading to the entity content")
|
||||
sys.exit(1)
|
||||
if reader.Name() != "p" or reader.NodeType() != 1:
|
||||
print("test_noent: Error reading the p element from entity")
|
||||
sys.exit(1)
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("test_noent: Error reading to the text node")
|
||||
sys.exit(1)
|
||||
if reader.NodeType() != 3 or reader.Value() != "test":
|
||||
print("test_noent: Error reading the text node")
|
||||
sys.exit(1)
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("test_noent: Error reading to the end of p element")
|
||||
sys.exit(1)
|
||||
if reader.Name() != "p" or reader.NodeType() != 15:
|
||||
print("test_noent: Error reading the end of the p element")
|
||||
sys.exit(1)
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("test_noent: Error reading to the end of root")
|
||||
sys.exit(1)
|
||||
if reader.Name() != "doc" or reader.NodeType() != 15:
|
||||
print("test_noent: Error reading the end of the root element")
|
||||
sys.exit(1)
|
||||
ret = reader.Read()
|
||||
if ret != 0:
|
||||
print("test_noent: Error detecting the end")
|
||||
sys.exit(1)
|
||||
|
||||
#
|
||||
# third test, crazy stuff about empty element in external parsed entities
|
||||
#
|
||||
s = """<!DOCTYPE struct [
|
||||
<!ENTITY simplestruct2.ent SYSTEM "simplestruct2.ent">
|
||||
]>
|
||||
<struct>&simplestruct2.ent;</struct>
|
||||
"""
|
||||
expect="""10 struct 0 0
|
||||
1 struct 0 0
|
||||
1 descr 1 1
|
||||
15 struct 0 0
|
||||
"""
|
||||
res=""
|
||||
simplestruct2_ent="""<descr/>"""
|
||||
|
||||
def myResolver(URL, ID, ctxt):
|
||||
if URL == "simplestruct2.ent":
|
||||
return(str_io(simplestruct2_ent))
|
||||
return None
|
||||
|
||||
libxml2.setEntityLoader(myResolver)
|
||||
|
||||
input = libxml2.inputBuffer(str_io(s))
|
||||
reader = input.newTextReader("test3")
|
||||
reader.SetParserProp(libxml2.PARSER_SUBST_ENTITIES,1)
|
||||
while reader.Read() == 1:
|
||||
res = res + "%s %s %d %d\n" % (reader.NodeType(),reader.Name(),
|
||||
reader.Depth(),reader.IsEmptyElement())
|
||||
|
||||
if res != expect:
|
||||
print("test3 failed: unexpected output")
|
||||
print(res)
|
||||
sys.exit(1)
|
||||
|
||||
#
|
||||
# cleanup
|
||||
#
|
||||
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)))
|
||||
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# this tests the basic APIs of the XmlTextReader interface
|
||||
#
|
||||
import setup_test
|
||||
import libxml2
|
||||
import sys
|
||||
try:
|
||||
import StringIO
|
||||
str_io = StringIO.StringIO
|
||||
except:
|
||||
import io
|
||||
str_io = io.StringIO
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
def tst_reader(s):
|
||||
f = str_io(s)
|
||||
input = libxml2.inputBuffer(f)
|
||||
reader = input.newTextReader("tst")
|
||||
res = ""
|
||||
while reader.Read():
|
||||
res=res + "%s (%s) [%s] %d\n" % (reader.NodeType(),reader.Name(),
|
||||
reader.Value(), reader.IsEmptyElement())
|
||||
if reader.NodeType() == 1: # Element
|
||||
while reader.MoveToNextAttribute():
|
||||
res = res + "-- %s (%s) [%s]\n" % (reader.NodeType(),
|
||||
reader.Name(),reader.Value())
|
||||
return res
|
||||
|
||||
expect="""1 (test) [None] 0
|
||||
1 (b) [None] 1
|
||||
1 (c) [None] 1
|
||||
15 (test) [None] 0
|
||||
"""
|
||||
|
||||
res = tst_reader("""<test><b/><c/></test>""")
|
||||
|
||||
if res != expect:
|
||||
print("Did not get the expected error message:")
|
||||
print(res)
|
||||
sys.exit(1)
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# this tests the Expand() API of the xmlTextReader interface
|
||||
# this extract the Dragon bibliography entries from the XML specification
|
||||
#
|
||||
import setup_test
|
||||
import libxml2
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
expect="""<bibl id="Aho" key="Aho/Ullman">Aho, Alfred V.,
|
||||
Ravi Sethi, and Jeffrey D. Ullman.
|
||||
<emph>Compilers: Principles, Techniques, and Tools</emph>.
|
||||
Reading: Addison-Wesley, 1986, rpt. corr. 1988.</bibl>"""
|
||||
|
||||
basedir = os.path.dirname(os.path.realpath(__file__))
|
||||
f = open(os.path.join(basedir, '../../test/valid/REC-xml-19980210.xml'), 'rb')
|
||||
input = libxml2.inputBuffer(f)
|
||||
reader = input.newTextReader("REC")
|
||||
res=""
|
||||
while reader.Read() > 0:
|
||||
while reader.Name() == 'bibl':
|
||||
node = reader.Expand() # expand the subtree
|
||||
if node.xpathEval("@id = 'Aho'"): # use XPath on it
|
||||
res = res + node.serialize()
|
||||
if reader.Next() != 1: # skip the subtree
|
||||
break;
|
||||
|
||||
if res != expect:
|
||||
print("Error: didn't get the expected output")
|
||||
print("got '%s'" % (res))
|
||||
print("expected '%s'" % (expect))
|
||||
|
||||
|
||||
#
|
||||
# cleanup
|
||||
#
|
||||
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)))
|
||||
@@ -0,0 +1,128 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# this tests the entities substitutions with the XmlTextReader interface
|
||||
#
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
try:
|
||||
import StringIO
|
||||
str_io = StringIO.StringIO
|
||||
except:
|
||||
import io
|
||||
str_io = io.StringIO
|
||||
|
||||
schema="""<element name="foo" xmlns="http://relaxng.org/ns/structure/1.0"
|
||||
datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
|
||||
<oneOrMore>
|
||||
<element name="label">
|
||||
<text/>
|
||||
</element>
|
||||
<optional>
|
||||
<element name="opt">
|
||||
<empty/>
|
||||
</element>
|
||||
</optional>
|
||||
<element name="item">
|
||||
<data type="byte"/>
|
||||
</element>
|
||||
</oneOrMore>
|
||||
</element>
|
||||
"""
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
#
|
||||
# Parse the Relax NG Schemas
|
||||
#
|
||||
rngp = libxml2.relaxNGNewMemParserCtxt(schema, len(schema))
|
||||
rngs = rngp.relaxNGParse()
|
||||
del rngp
|
||||
|
||||
#
|
||||
# Parse and validate the correct document
|
||||
#
|
||||
docstr="""<foo>
|
||||
<label>some text</label>
|
||||
<item>100</item>
|
||||
</foo>"""
|
||||
|
||||
f = str_io(docstr)
|
||||
input = libxml2.inputBuffer(f)
|
||||
reader = input.newTextReader("correct")
|
||||
reader.RelaxNGSetSchema(rngs)
|
||||
ret = reader.Read()
|
||||
while ret == 1:
|
||||
ret = reader.Read()
|
||||
|
||||
if ret != 0:
|
||||
print("Error parsing the document")
|
||||
sys.exit(1)
|
||||
|
||||
if reader.IsValid() != 1:
|
||||
print("Document failed to validate")
|
||||
sys.exit(1)
|
||||
|
||||
#
|
||||
# Parse and validate the incorrect document
|
||||
#
|
||||
docstr="""<foo>
|
||||
<label>some text</label>
|
||||
<item>1000</item>
|
||||
</foo>"""
|
||||
|
||||
err=""
|
||||
# RNG errors are not as good as before , TODO
|
||||
#expect="""RNG validity error: file error line 3 element text
|
||||
#Type byte doesn't allow value '1000'
|
||||
#RNG validity error: file error line 3 element text
|
||||
#Error validating datatype byte
|
||||
#RNG validity error: file error line 3 element text
|
||||
#Element item failed to validate content
|
||||
#"""
|
||||
expect="""Type byte doesn't allow value '1000'
|
||||
Error validating datatype byte
|
||||
Element item failed to validate content
|
||||
"""
|
||||
|
||||
def callback(ctx, str):
|
||||
global err
|
||||
err = err + "%s" % (str)
|
||||
libxml2.registerErrorHandler(callback, "")
|
||||
|
||||
f = str_io(docstr)
|
||||
input = libxml2.inputBuffer(f)
|
||||
reader = input.newTextReader("error")
|
||||
reader.RelaxNGSetSchema(rngs)
|
||||
ret = reader.Read()
|
||||
while ret == 1:
|
||||
ret = reader.Read()
|
||||
|
||||
if ret != 0:
|
||||
print("Error parsing the document")
|
||||
sys.exit(1)
|
||||
|
||||
if reader.IsValid() != 0:
|
||||
print("Document failed to detect the validation error")
|
||||
sys.exit(1)
|
||||
|
||||
if err != expect:
|
||||
print("Did not get the expected error message:")
|
||||
print(err)
|
||||
sys.exit(1)
|
||||
|
||||
#
|
||||
# cleanup
|
||||
#
|
||||
del f
|
||||
del input
|
||||
del reader
|
||||
del rngs
|
||||
libxml2.relaxNGCleanupTypes()
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# this tests the entities substitutions with the XmlTextReader interface
|
||||
#
|
||||
import sys
|
||||
import setup_test
|
||||
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="""<foo>
|
||||
<label>some text</label>
|
||||
<item>100</item>
|
||||
</foo>"""
|
||||
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="""<foo>
|
||||
<label>some text</label>
|
||||
<item>1000</item>
|
||||
</foo>"""
|
||||
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)))
|
||||
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# this tests the entities substitutions with the XmlTextReader interface
|
||||
#
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
#
|
||||
# Parse a document testing the Close() API
|
||||
#
|
||||
docstr="""<foo>
|
||||
<label>some text</label>
|
||||
<item>100</item>
|
||||
</foo>"""
|
||||
|
||||
reader = libxml2.readerForDoc(docstr, "test1", None, 0)
|
||||
ret = reader.Read()
|
||||
ret = reader.Read()
|
||||
ret = reader.Close()
|
||||
|
||||
if ret != 0:
|
||||
print("Error closing the document test1")
|
||||
sys.exit(1)
|
||||
|
||||
del reader
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# this tests the basic APIs of the XmlTextReader interface
|
||||
#
|
||||
import setup_test
|
||||
import libxml2
|
||||
import sys
|
||||
try:
|
||||
import StringIO
|
||||
str_io = StringIO.StringIO
|
||||
except:
|
||||
import io
|
||||
str_io = io.StringIO
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
expect="""--> (3) test1:1:xmlns: URI foo is not absolute
|
||||
--> (4) test1:1:Opening and ending tag mismatch: c line 1 and a
|
||||
"""
|
||||
err=""
|
||||
def myErrorHandler(arg,msg,severity,locator):
|
||||
global err
|
||||
err = err + "%s (%d) %s:%d:%s" % (arg,severity,locator.BaseURI(),locator.LineNumber(),msg)
|
||||
|
||||
f = str_io("""<a xmlns="foo"><b b1="b1"/><c>content of c</a>""")
|
||||
input = libxml2.inputBuffer(f)
|
||||
reader = input.newTextReader("test1")
|
||||
reader.SetErrorHandler(myErrorHandler,"-->")
|
||||
while reader.Read() == 1:
|
||||
pass
|
||||
|
||||
if err != expect:
|
||||
print("error")
|
||||
print("received %s" %(err))
|
||||
print("expected %s" %(expect))
|
||||
sys.exit(1)
|
||||
|
||||
reader.SetErrorHandler(None,None)
|
||||
if reader.GetErrorHandler() != (None,None):
|
||||
print("GetErrorHandler failed")
|
||||
sys.exit(1)
|
||||
|
||||
#
|
||||
# cleanup for memory allocation counting
|
||||
#
|
||||
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)))
|
||||
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: ISO-8859-1 -*-
|
||||
#
|
||||
# this tests the next API of the XmlTextReader interface
|
||||
#
|
||||
import setup_test
|
||||
import libxml2
|
||||
import sys
|
||||
try:
|
||||
import StringIO
|
||||
str_io = StringIO.StringIO
|
||||
except:
|
||||
import io
|
||||
str_io = io.StringIO
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
f = str_io("""<a><b><c /></b><d>content of d</d></a>""")
|
||||
input = libxml2.inputBuffer(f)
|
||||
reader = input.newTextReader("test_next")
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("test_next: 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("test_next: Error reading the first element")
|
||||
sys.exit(1)
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("test_next: Error reading to second element")
|
||||
sys.exit(1)
|
||||
if reader.Name() != "b" or reader.IsEmptyElement() != 0 or \
|
||||
reader.NodeType() != 1 or reader.HasAttributes() != 0:
|
||||
print("test_next: Error reading the second element")
|
||||
sys.exit(1)
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("test_next: Error reading to third element")
|
||||
sys.exit(1)
|
||||
if reader.Name() != "c" or reader.NodeType() != 1 or \
|
||||
reader.HasAttributes() != 0:
|
||||
print("test_next: Error reading the third element")
|
||||
sys.exit(1)
|
||||
ret = reader.Read()
|
||||
if ret != 1:
|
||||
print("test_next: Error reading to end of third element")
|
||||
sys.exit(1)
|
||||
if reader.Name() != "b" or reader.NodeType() != 15:
|
||||
print("test_next: Error reading to end of second element")
|
||||
sys.exit(1)
|
||||
ret = reader.Next()
|
||||
if ret != 1:
|
||||
print("test_next: Error moving to third element")
|
||||
sys.exit(1)
|
||||
if reader.Name() != "d" or reader.IsEmptyElement() != 0 or \
|
||||
reader.NodeType() != 1 or reader.HasAttributes() != 0:
|
||||
print("test_next: Error reading third element")
|
||||
sys.exit(1)
|
||||
ret = reader.Next()
|
||||
if ret != 1:
|
||||
print("test_next: 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("test_next: Error reading the end of first element")
|
||||
sys.exit(1)
|
||||
ret = reader.Read()
|
||||
if ret != 0:
|
||||
print("test_next: Error reading to end of document")
|
||||
sys.exit(1)
|
||||
|
||||
#
|
||||
# cleanup for memory allocation counting
|
||||
#
|
||||
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)))
|
||||
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
|
||||
def check_regex(regex, inside, outside):
|
||||
re = libxml2.regexpCompile(regex)
|
||||
for c in inside:
|
||||
if re.regexpExec(c) != 1:
|
||||
print("error checking inside", repr(regex), repr(c))
|
||||
sys.exit(1)
|
||||
for c in outside:
|
||||
if re.regexpExec(c) != 0:
|
||||
print("error checking outside", repr(regex), repr(c))
|
||||
sys.exit(1)
|
||||
if re.regexpIsDeterminist() != 1:
|
||||
print("error checking determinism")
|
||||
sys.exit(1)
|
||||
del re
|
||||
|
||||
|
||||
check_regex("a|b", "ab", ["ab", ""])
|
||||
# https://gitlab.gnome.org/GNOME/libxml2/-/issues/1086
|
||||
check_regex(r"[\t-\r]", "\t\n\r", ["a", "(", ""])
|
||||
check_regex("[\\t-\\r]", "\t\n\r", ["a", "(", ""])
|
||||
check_regex(r"[\[-\]]", "[]\\", "Z^")
|
||||
check_regex(r"[\*-/]", "*+,-./", "()0")
|
||||
# Non-standard escape sequences
|
||||
check_regex(r"[\u0041-\u005A]", "ABCMYZ", ["a", "0", "[", ""])
|
||||
check_regex(r"[\u0009\u0061-\u007A]", "\tabcmyz", ["A", "0", "{", "", "\n"])
|
||||
check_regex(r"[\!-\%]", '!"#$%', ["&", " ", "a", ""])
|
||||
check_regex(r"[\:-\>]", ':;<=>', ["?", "9", "@", ""])
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python3
|
||||
import setup_test
|
||||
import libxml2
|
||||
import sys
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
schema="""<?xml version="1.0"?>
|
||||
<element name="foo"
|
||||
xmlns="http://relaxng.org/ns/structure/1.0"
|
||||
xmlns:a="http://relaxng.org/ns/annotation/1.0"
|
||||
xmlns:ex1="http://www.example.com/n1"
|
||||
xmlns:ex2="http://www.example.com/n2">
|
||||
<a:documentation>A foo element.</a:documentation>
|
||||
<element name="ex1:bar1">
|
||||
<empty/>
|
||||
</element>
|
||||
<element name="ex2:bar2">
|
||||
<empty/>
|
||||
</element>
|
||||
</element>
|
||||
"""
|
||||
instance="""<?xml version="1.0"?>
|
||||
<foo><pre1:bar1 xmlns:pre1="http://www.example.com/n1"/><pre2:bar2 xmlns:pre2="http://www.example.com/n2"/></foo>"""
|
||||
|
||||
rngp = libxml2.relaxNGNewMemParserCtxt(schema, len(schema))
|
||||
rngs = rngp.relaxNGParse()
|
||||
ctxt = rngs.relaxNGNewValidCtxt()
|
||||
doc = libxml2.parseDoc(instance)
|
||||
ret = doc.relaxNGValidateDoc(ctxt)
|
||||
if ret != 0:
|
||||
print("error doing RelaxNG validation")
|
||||
sys.exit(1)
|
||||
|
||||
doc.freeDoc()
|
||||
del rngp
|
||||
del rngs
|
||||
del ctxt
|
||||
libxml2.relaxNGCleanupTypes()
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
try:
|
||||
import StringIO
|
||||
str_io = StringIO.StringIO
|
||||
except:
|
||||
import io
|
||||
str_io = io.StringIO
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
def myResolver(URL, ID, ctxt):
|
||||
return(str_io("<foo/>"))
|
||||
|
||||
libxml2.setEntityLoader(myResolver)
|
||||
|
||||
doc = libxml2.parseFile("doesnotexist.xml")
|
||||
root = doc.children
|
||||
if root.name != "foo":
|
||||
print("root element name error")
|
||||
sys.exit(1)
|
||||
doc.freeDoc()
|
||||
|
||||
i = 0
|
||||
while i < 5000:
|
||||
doc = libxml2.parseFile("doesnotexist.xml")
|
||||
root = doc.children
|
||||
if root.name != "foo":
|
||||
print("root element name error")
|
||||
sys.exit(1)
|
||||
doc.freeDoc()
|
||||
i = i + 1
|
||||
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
import setup_test
|
||||
import libxml2
|
||||
import sys
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
schema="""<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<schema xmlns = "http://www.w3.org/2001/XMLSchema">
|
||||
<element name = "Customer">
|
||||
<complexType>
|
||||
<sequence>
|
||||
<element name = "FirstName" type = "string" />
|
||||
<element name = "MiddleInitial" type = "string" />
|
||||
<element name = "LastName" type = "string" />
|
||||
</sequence>
|
||||
<attribute name = "customerID" type = "integer" />
|
||||
</complexType>
|
||||
</element>
|
||||
</schema>"""
|
||||
|
||||
instance="""<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<Customer customerID = "24332">
|
||||
<FirstName>Raymond</FirstName>
|
||||
<MiddleInitial>G</MiddleInitial>
|
||||
<LastName>Bayliss</LastName>
|
||||
</Customer>
|
||||
"""
|
||||
|
||||
ctxt_parser = libxml2.schemaNewMemParserCtxt(schema, len(schema))
|
||||
ctxt_schema = ctxt_parser.schemaParse()
|
||||
ctxt_valid = ctxt_schema.schemaNewValidCtxt()
|
||||
doc = libxml2.parseDoc(instance)
|
||||
ret = doc.schemaValidateDoc(ctxt_valid)
|
||||
if ret != 0:
|
||||
print("error doing schema validation")
|
||||
sys.exit(1)
|
||||
|
||||
doc.freeDoc()
|
||||
del ctxt_parser
|
||||
del ctxt_schema
|
||||
del ctxt_valid
|
||||
libxml2.schemaCleanupTypes()
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
#
|
||||
# Testing XML document serialization
|
||||
#
|
||||
doc = libxml2.parseDoc("""<root><foo>hello</foo></root>""")
|
||||
str = doc.serialize()
|
||||
if str != """<?xml version="1.0"?>
|
||||
<root><foo>hello</foo></root>
|
||||
""":
|
||||
print("error serializing XML document 1")
|
||||
sys.exit(1)
|
||||
str = doc.serialize("iso-8859-1")
|
||||
if str != """<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<root><foo>hello</foo></root>
|
||||
""":
|
||||
print("error serializing XML document 2")
|
||||
sys.exit(1)
|
||||
str = doc.serialize(format=1)
|
||||
if str != """<?xml version="1.0"?>
|
||||
<root>
|
||||
<foo>hello</foo>
|
||||
</root>
|
||||
""":
|
||||
print("error serializing XML document 3")
|
||||
sys.exit(1)
|
||||
str = doc.serialize("iso-8859-1", 1)
|
||||
if str != """<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<root>
|
||||
<foo>hello</foo>
|
||||
</root>
|
||||
""":
|
||||
print("error serializing XML document 4")
|
||||
sys.exit(1)
|
||||
|
||||
#
|
||||
# Test serializing a subnode
|
||||
#
|
||||
root = doc.getRootElement()
|
||||
str = root.serialize()
|
||||
if str != """<root><foo>hello</foo></root>""":
|
||||
print("error serializing XML root 1")
|
||||
sys.exit(1)
|
||||
str = root.serialize("iso-8859-1")
|
||||
if str != """<root><foo>hello</foo></root>""":
|
||||
print("error serializing XML root 2")
|
||||
sys.exit(1)
|
||||
str = root.serialize(format=1)
|
||||
if str != """<root>
|
||||
<foo>hello</foo>
|
||||
</root>""":
|
||||
print("error serializing XML root 3")
|
||||
sys.exit(1)
|
||||
str = root.serialize("iso-8859-1", 1)
|
||||
if str != """<root>
|
||||
<foo>hello</foo>
|
||||
</root>""":
|
||||
print("error serializing XML root 4")
|
||||
sys.exit(1)
|
||||
doc.freeDoc()
|
||||
|
||||
#
|
||||
# Testing HTML document serialization
|
||||
#
|
||||
doc = libxml2.htmlParseDoc("""<html><head><title>Hello</title><body><p>hello</body></html>""", None)
|
||||
str = doc.serialize()
|
||||
if str != """<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<html><head><title>Hello</title></head><body><p>hello</p></body></html>
|
||||
""":
|
||||
print("error serializing HTML document 1")
|
||||
sys.exit(1)
|
||||
str = doc.serialize("ISO-8859-1")
|
||||
if str != """<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<html><head><meta charset="ISO-8859-1"><title>Hello</title></head><body><p>hello</p></body></html>
|
||||
""":
|
||||
print("error serializing HTML document 2")
|
||||
sys.exit(1)
|
||||
str = doc.serialize(format=1)
|
||||
if str != """<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<html>
|
||||
<head><title>Hello</title></head>
|
||||
<body><p>hello</p></body>
|
||||
</html>
|
||||
""":
|
||||
print("error serializing HTML document 3")
|
||||
sys.exit(1)
|
||||
str = doc.serialize("iso-8859-1", 1)
|
||||
if str != """<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="iso-8859-1">
|
||||
<title>Hello</title>
|
||||
</head>
|
||||
<body><p>hello</p></body>
|
||||
</html>
|
||||
""":
|
||||
print("error serializing HTML document 4", str)
|
||||
sys.exit(1)
|
||||
|
||||
#
|
||||
# Test serializing a subnode
|
||||
#
|
||||
doc.htmlSetMetaEncoding(None)
|
||||
root = doc.getRootElement()
|
||||
str = root.serialize()
|
||||
if str != """<html><head><title>Hello</title></head><body><p>hello</p></body></html>""":
|
||||
print("error serializing HTML root 1")
|
||||
sys.exit(1)
|
||||
str = root.serialize("ISO-8859-1")
|
||||
if str != """<html><head><meta charset="ISO-8859-1"><title>Hello</title></head><body><p>hello</p></body></html>""":
|
||||
print("error serializing HTML root 2")
|
||||
sys.exit(1)
|
||||
str = root.serialize(format=1)
|
||||
if str != """<html>
|
||||
<head><title>Hello</title></head>
|
||||
<body><p>hello</p></body>
|
||||
</html>""":
|
||||
print("error serializing HTML root 3")
|
||||
sys.exit(1)
|
||||
str = root.serialize("iso-8859-1", 1)
|
||||
if str != """<html>
|
||||
<head>
|
||||
<meta charset="iso-8859-1">
|
||||
<title>Hello</title>
|
||||
</head>
|
||||
<body><p>hello</p></body>
|
||||
</html>""":
|
||||
print("error serializing HTML root 4")
|
||||
sys.exit(1)
|
||||
|
||||
doc.freeDoc()
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,5 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
if hasattr(os, 'add_dll_directory'):
|
||||
os.add_dll_directory(os.path.join(os.getcwd(), '..', '..', '.libs'))
|
||||
@@ -0,0 +1,138 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
log = ""
|
||||
|
||||
class callback:
|
||||
def startDocument(self):
|
||||
global log
|
||||
log = log + "startDocument:"
|
||||
|
||||
def endDocument(self):
|
||||
global log
|
||||
log = log + "endDocument:"
|
||||
|
||||
def startElement(self, tag, attrs):
|
||||
global log
|
||||
log = log + "startElement %s %s:" % (tag, attrs)
|
||||
|
||||
def endElement(self, tag):
|
||||
global log
|
||||
log = log + "endElement %s:" % (tag)
|
||||
|
||||
def characters(self, data):
|
||||
global log
|
||||
log = log + "characters: %s:" % (data)
|
||||
|
||||
def warning(self, msg):
|
||||
global log
|
||||
log = log + "warning: %s:" % (msg)
|
||||
|
||||
def error(self, msg):
|
||||
global log
|
||||
log = log + "error: %s:" % (msg)
|
||||
|
||||
def fatalError(self, msg):
|
||||
global log
|
||||
log = log + "fatalError: %s:" % (msg)
|
||||
|
||||
handler = callback()
|
||||
|
||||
log=""
|
||||
chunk="""<foo><bar2/>"""
|
||||
ctxt = libxml2.createPushParser(handler, None, 0, "test.xml")
|
||||
ctxt.parseChunk(chunk, len(chunk), 0)
|
||||
ctxt=None
|
||||
|
||||
reference = "startDocument:startElement foo None:startElement bar2 None:endElement bar2:"
|
||||
if log != reference:
|
||||
print("Error got: %s" % log)
|
||||
print("Expected: %s" % reference)
|
||||
sys.exit(1)
|
||||
|
||||
log=""
|
||||
chunk="""<foo><bar2></bar2>"""
|
||||
ctxt = libxml2.createPushParser(handler, None, 0, "test.xml")
|
||||
ctxt.parseChunk(chunk, len(chunk), 0)
|
||||
ctxt=None
|
||||
|
||||
reference = "startDocument:startElement foo None:startElement bar2 None:endElement bar2:"
|
||||
if log != reference:
|
||||
print("Error got: %s" % log)
|
||||
print("Expected: %s" % reference)
|
||||
sys.exit(1)
|
||||
|
||||
log=""
|
||||
chunk="""<foo><bar2>"""
|
||||
ctxt = libxml2.createPushParser(handler, None, 0, "test.xml")
|
||||
ctxt.parseChunk(chunk, len(chunk), 0)
|
||||
ctxt=None
|
||||
|
||||
reference = "startDocument:startElement foo None:startElement bar2 None:"
|
||||
if log != reference:
|
||||
print("Error got: %s" % log)
|
||||
print("Expected: %s" % reference)
|
||||
sys.exit(1)
|
||||
|
||||
log=""
|
||||
chunk="""<foo><bar2 a="1" b='2' />"""
|
||||
ctxt = libxml2.createPushParser(handler, None, 0, "test.xml")
|
||||
ctxt.parseChunk(chunk, len(chunk), 0)
|
||||
ctxt=None
|
||||
|
||||
reference1 = "startDocument:startElement foo None:startElement bar2 {'a': '1', 'b': '2'}:endElement bar2:"
|
||||
reference2 = "startDocument:startElement foo None:startElement bar2 {'b': '2', 'a': '1'}:endElement bar2:"
|
||||
if log not in (reference1, reference2):
|
||||
print("Error got: %s" % log)
|
||||
print("Expected: %s" % reference)
|
||||
sys.exit(1)
|
||||
|
||||
log=""
|
||||
chunk="""<foo><bar2 a="1" b='2' >"""
|
||||
ctxt = libxml2.createPushParser(handler, None, 0, "test.xml")
|
||||
ctxt.parseChunk(chunk, len(chunk), 0)
|
||||
ctxt=None
|
||||
|
||||
reference1 = "startDocument:startElement foo None:startElement bar2 {'a': '1', 'b': '2'}:"
|
||||
reference2 = "startDocument:startElement foo None:startElement bar2 {'b': '2', 'a': '1'}:"
|
||||
if log not in (reference1, reference2):
|
||||
print("Error got: %s" % log)
|
||||
print("Expected: %s" % reference)
|
||||
sys.exit(1)
|
||||
|
||||
log=""
|
||||
chunk="""<foo><bar2 a="1" b='2' ></bar2>"""
|
||||
ctxt = libxml2.createPushParser(handler, None, 0, "test.xml")
|
||||
ctxt.parseChunk(chunk, len(chunk), 0)
|
||||
ctxt=None
|
||||
|
||||
reference1 = "startDocument:startElement foo None:startElement bar2 {'a': '1', 'b': '2'}:endElement bar2:"
|
||||
reference2 = "startDocument:startElement foo None:startElement bar2 {'b': '2', 'a': '1'}:endElement bar2:"
|
||||
if log not in (reference1, reference2):
|
||||
print("Error got: %s" % log)
|
||||
print("Expected: %s" % reference)
|
||||
sys.exit(1)
|
||||
|
||||
log=""
|
||||
chunk="""<foo><bar2 a="b='1' />"""
|
||||
ctxt = libxml2.createPushParser(handler, None, 0, "test.xml")
|
||||
ctxt.parseChunk(chunk, len(chunk), 0)
|
||||
ctxt=None
|
||||
|
||||
reference = "startDocument:startElement foo None:"
|
||||
if log != reference:
|
||||
print("Error got: %s" % log)
|
||||
print("Expected: %s" % reference)
|
||||
sys.exit(1)
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1 @@
|
||||
<!ELEMENT foo EMPTY>
|
||||
@@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env python3
|
||||
import string, sys, time
|
||||
try:
|
||||
from _thread import get_ident
|
||||
except:
|
||||
from thread import get_ident
|
||||
from threading import Thread, Lock
|
||||
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
THREADS_COUNT = 15
|
||||
|
||||
failed = 0
|
||||
|
||||
class ErrorHandler:
|
||||
|
||||
def __init__(self):
|
||||
self.errors = []
|
||||
self.lock = Lock()
|
||||
|
||||
def handler(self,ctx,str):
|
||||
self.lock.acquire()
|
||||
self.errors.append(str)
|
||||
self.lock.release()
|
||||
|
||||
def getPedanticParserDefault():
|
||||
old = libxml2.pedanticParserDefault(0)
|
||||
libxml2.pedanticParserDefault(old)
|
||||
return old
|
||||
|
||||
def test(expectedPedanticParserDefault):
|
||||
time.sleep(1)
|
||||
global failed
|
||||
# check a per thread-global
|
||||
if expectedPedanticParserDefault != getPedanticParserDefault():
|
||||
failed = 1
|
||||
print("FAILED to obtain correct value for " \
|
||||
"pedanticParserDefault in thread %d" % get_ident())
|
||||
# check the global error handler
|
||||
# (which is NOT per-thread in the python bindings)
|
||||
try:
|
||||
doc = libxml2.parseFile("bad.xml")
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
assert "failed"
|
||||
|
||||
# global error handler
|
||||
eh = ErrorHandler()
|
||||
libxml2.registerErrorHandler(eh.handler,"")
|
||||
|
||||
# set on the main thread only
|
||||
libxml2.pedanticParserDefault(1)
|
||||
test(1)
|
||||
ec = len(eh.errors)
|
||||
if ec == 0:
|
||||
print("FAILED: should have obtained errors")
|
||||
sys.exit(1)
|
||||
|
||||
ts = []
|
||||
for i in range(THREADS_COUNT):
|
||||
# expect 0 for pedanticParserDefault because
|
||||
# the new value has been set on the main thread only
|
||||
ts.append(Thread(target=test,args=(0,)))
|
||||
for t in ts:
|
||||
t.start()
|
||||
for t in ts:
|
||||
t.join()
|
||||
|
||||
if len(eh.errors) != ec+THREADS_COUNT*ec:
|
||||
print("FAILED: did not obtain the correct number of errors")
|
||||
sys.exit(1)
|
||||
|
||||
# set pedanticParserDefault for future new threads
|
||||
libxml2.thrDefPedanticParserDefaultValue(1)
|
||||
ts = []
|
||||
for i in range(THREADS_COUNT):
|
||||
# expect 1 for pedanticParserDefault
|
||||
ts.append(Thread(target=test,args=(1,)))
|
||||
for t in ts:
|
||||
t.start()
|
||||
for t in ts:
|
||||
t.join()
|
||||
|
||||
if len(eh.errors) != ec+THREADS_COUNT*ec*2:
|
||||
print("FAILED: did not obtain the correct number of errors")
|
||||
sys.exit(1)
|
||||
|
||||
if failed:
|
||||
print("FAILED")
|
||||
sys.exit(1)
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
# Note that this can leak memory on Windows if the global state
|
||||
# destructors weren't run yet. They should be called eventually,
|
||||
# so this leak should be harmless.
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
doc = libxml2.parseFile("tst.xml")
|
||||
if doc.name != "tst.xml":
|
||||
print("doc.name failed")
|
||||
sys.exit(1)
|
||||
root = doc.children
|
||||
if root.name != "doc":
|
||||
print("root.name failed")
|
||||
sys.exit(1)
|
||||
child = root.children
|
||||
if child.name != "foo":
|
||||
print("child.name failed")
|
||||
sys.exit(1)
|
||||
doc.freeDoc()
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1 @@
|
||||
<doc><foo>bar</foo></doc>
|
||||
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys, unittest
|
||||
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
class TestCase(unittest.TestCase):
|
||||
|
||||
def runTest(self):
|
||||
self.test1()
|
||||
self.test2()
|
||||
|
||||
def setUp(self):
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
def tearDown(self):
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) != 0:
|
||||
self.fail("Memory leak %d bytes" % (libxml2.debugMemory(1),))
|
||||
else:
|
||||
print("OK")
|
||||
|
||||
def failUnlessXmlError(self,f,args,exc,domain,code,message,level,file,line):
|
||||
"""Run function f, with arguments args and expect an exception exc;
|
||||
when the exception is raised, check the libxml2.lastError for
|
||||
expected values."""
|
||||
# disable the default error handler
|
||||
def noerr(ctx, str):
|
||||
pass
|
||||
# None is not acceptable as function.
|
||||
libxml2.registerErrorHandler(noerr,None)
|
||||
try:
|
||||
f(*args)
|
||||
except exc:
|
||||
e = libxml2.lastError()
|
||||
if e is None:
|
||||
self.fail("lastError not set")
|
||||
if 0:
|
||||
print("domain = ",e.domain())
|
||||
print("code = ",e.code())
|
||||
print("message =",repr(e.message()))
|
||||
print("level =",e.level())
|
||||
print("file =",e.file())
|
||||
print("line =",e.line())
|
||||
print()
|
||||
self.assertEqual(domain,e.domain())
|
||||
self.assertEqual(code,e.code())
|
||||
self.assertEqual(message,e.message())
|
||||
self.assertEqual(level,e.level())
|
||||
self.assertEqual(file,e.file())
|
||||
self.assertEqual(line,e.line())
|
||||
else:
|
||||
self.fail("exception %s should have been raised" % exc)
|
||||
|
||||
def test1(self):
|
||||
"""Test readFile with a file that does not exist"""
|
||||
self.failUnlessXmlError(libxml2.readFile,
|
||||
("dummy.xml",None,0),
|
||||
libxml2.treeError,
|
||||
domain=libxml2.XML_FROM_IO,
|
||||
code=libxml2.XML_IO_ENOENT,
|
||||
message='failed to load "dummy.xml": No such file or directory\n',
|
||||
level=libxml2.XML_ERR_WARNING,
|
||||
file=None,
|
||||
line=0)
|
||||
|
||||
def test2(self):
|
||||
"""Test a well-formedness error: we get the last error only"""
|
||||
s = "<x>\n<a>\n</x>"
|
||||
self.failUnlessXmlError(libxml2.readMemory,
|
||||
(s,len(s),"dummy.xml",None,0),
|
||||
libxml2.treeError,
|
||||
domain=libxml2.XML_FROM_PARSER,
|
||||
code=libxml2.XML_ERR_TAG_NAME_MISMATCH,
|
||||
message='Opening and ending tag mismatch: a line 2 and x\n',
|
||||
level=libxml2.XML_ERR_FATAL,
|
||||
file='dummy.xml',
|
||||
line=3)
|
||||
|
||||
if __name__ == "__main__":
|
||||
test = TestCase()
|
||||
test.setUp()
|
||||
test.test1()
|
||||
test.test2()
|
||||
test.tearDown()
|
||||
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
uri = libxml2.parseURI("http://example.org:8088/foo/bar?query=simple#fragid")
|
||||
if uri.scheme() != 'http':
|
||||
print("Error parsing URI: wrong scheme")
|
||||
sys.exit(1)
|
||||
if uri.server() != 'example.org':
|
||||
print("Error parsing URI: wrong server")
|
||||
sys.exit(1)
|
||||
if uri.port() != 8088:
|
||||
print("Error parsing URI: wrong port")
|
||||
sys.exit(1)
|
||||
if uri.path() != '/foo/bar':
|
||||
print("Error parsing URI: wrong path")
|
||||
sys.exit(1)
|
||||
if uri.query() != 'query=simple':
|
||||
print("Error parsing URI: wrong query")
|
||||
sys.exit(1)
|
||||
if uri.fragment() != 'fragid':
|
||||
print("Error parsing URI: wrong query")
|
||||
sys.exit(1)
|
||||
uri.setScheme("https")
|
||||
uri.setPort(223)
|
||||
uri.setFragment(None)
|
||||
result=uri.saveUri()
|
||||
if result != "https://example.org:223/foo/bar?query=simple":
|
||||
print("Error modifying or saving the URI")
|
||||
uri = None
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python3
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
try:
|
||||
import libxml2mod
|
||||
except ModuleNotFoundError:
|
||||
from libxmlmods import libxml2mod
|
||||
|
||||
import sys
|
||||
|
||||
def error(msg, data):
|
||||
pass
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
dtd="""<!ELEMENT foo EMPTY>"""
|
||||
instance="""<?xml version="1.0"?>
|
||||
<foo></foo>"""
|
||||
|
||||
dtd = libxml2.parseDTD(None, 'test.dtd')
|
||||
ctxt = libxml2.newValidCtxt()
|
||||
libxml2mod.xmlSetValidErrors(ctxt._o, error, error)
|
||||
doc = libxml2.parseDoc(instance)
|
||||
ret = doc.validateDtd(ctxt, dtd)
|
||||
if ret != 1:
|
||||
print("error doing DTD validation")
|
||||
sys.exit(1)
|
||||
|
||||
doc.freeDoc()
|
||||
dtd.freeDtd()
|
||||
del dtd
|
||||
del ctxt
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
#memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
called = ""
|
||||
|
||||
def foo(ctx, x):
|
||||
global called
|
||||
|
||||
#
|
||||
# test that access to the XPath evaluation contexts
|
||||
#
|
||||
pctxt = libxml2.xpathParserContext(_obj=ctx)
|
||||
ctxt = pctxt.context()
|
||||
called = ctxt.function()
|
||||
return x + 1
|
||||
|
||||
def bar(ctxt, x):
|
||||
return "%d" % (x + 2)
|
||||
|
||||
doc = libxml2.parseFile("tst.xml")
|
||||
ctxt = doc.xpathNewContext()
|
||||
res = ctxt.xpathEval("//*")
|
||||
if len(res) != 2:
|
||||
print("xpath query: wrong node set size")
|
||||
sys.exit(1)
|
||||
if res[0].name != "doc" or res[1].name != "foo":
|
||||
print("xpath query: wrong node set value")
|
||||
sys.exit(1)
|
||||
libxml2.registerXPathFunction(ctxt._o, "foo", None, foo)
|
||||
libxml2.registerXPathFunction(ctxt._o, "bar", None, bar)
|
||||
i = 10000
|
||||
while i > 0:
|
||||
res = ctxt.xpathEval("foo(1)")
|
||||
if res != 2:
|
||||
print("xpath extension failure")
|
||||
sys.exit(1)
|
||||
i = i - 1
|
||||
i = 10000
|
||||
while i > 0:
|
||||
res = ctxt.xpathEval("bar(1)")
|
||||
if res != "3":
|
||||
print("xpath extension failure got %s expecting '3'")
|
||||
sys.exit(1)
|
||||
i = i - 1
|
||||
doc.freeDoc()
|
||||
ctxt.xpathFreeContext()
|
||||
|
||||
if called != "foo":
|
||||
print("xpath function: failed to access the context")
|
||||
print("xpath function: %s" % (called))
|
||||
sys.exit(1)
|
||||
|
||||
#memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,61 @@
|
||||
from io import BytesIO, StringIO
|
||||
import libxml2
|
||||
import sys
|
||||
from xml.sax.handler import ContentHandler
|
||||
from xml.sax.xmlreader import InputSource
|
||||
import xml.sax
|
||||
|
||||
|
||||
# Test data: an XML file with a 100,000 Unicode smileys, which expand
|
||||
# into 400,000 bytes after UTF-8 encoding.
|
||||
SMILEY = '\U0001f600'
|
||||
TEXT = 100_000 * SMILEY
|
||||
XML_STRING = '<?xml version="1.0" encoding="UTF-8" ?>\n<root>' + TEXT + '</root>'
|
||||
XML_BYTES = XML_STRING.encode('utf-8')
|
||||
|
||||
|
||||
def RunTest(test_name, source):
|
||||
expected = TEXT
|
||||
received = ''
|
||||
|
||||
class TestHandler(ContentHandler):
|
||||
def characters(self, content):
|
||||
nonlocal received
|
||||
received += content
|
||||
|
||||
reader = xml.sax.make_parser(['drv_libxml2'])
|
||||
reader.setContentHandler(TestHandler())
|
||||
reader.parse(source)
|
||||
if expected != received:
|
||||
print(test_name, 'failed!')
|
||||
print('Expected length:', len(expected))
|
||||
print('Received length:', len(received))
|
||||
print('Expected text: (prefix only)', expected[:100])
|
||||
print('Received text: (prefix only)', received[:100])
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def TestBytesInput():
|
||||
source = InputSource()
|
||||
source.setByteStream(BytesIO(XML_BYTES))
|
||||
RunTest('TestBytesInput', source)
|
||||
|
||||
|
||||
def TestStringInput():
|
||||
source = InputSource()
|
||||
source.setCharacterStream(StringIO(XML_STRING))
|
||||
RunTest('TestStringInput', source)
|
||||
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
TestBytesInput()
|
||||
TestStringInput()
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,4 @@
|
||||
<!DOCTYPE doc [
|
||||
<!ELEMENT doc EMPTY>
|
||||
]>
|
||||
<doc/>
|
||||
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python3
|
||||
import setup_test
|
||||
import libxml2
|
||||
import sys
|
||||
|
||||
ARG = 'test string'
|
||||
|
||||
class ErrorHandler:
|
||||
|
||||
def __init__(self):
|
||||
self.errors = []
|
||||
|
||||
def handler(self, msg, data):
|
||||
if data != ARG:
|
||||
raise Exception("Error handler did not receive correct argument")
|
||||
self.errors.append(msg)
|
||||
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
dtd="""<!ELEMENT foo EMPTY>"""
|
||||
valid="""<?xml version="1.0"?>
|
||||
<foo></foo>"""
|
||||
|
||||
invalid="""<?xml version="1.0"?>
|
||||
<foo><bar/></foo>"""
|
||||
|
||||
dtd = libxml2.parseDTD(None, 'test.dtd')
|
||||
ctxt = libxml2.newValidCtxt()
|
||||
e = ErrorHandler()
|
||||
ctxt.setValidityErrorHandler(e.handler, e.handler, ARG)
|
||||
|
||||
# Test valid document
|
||||
doc = libxml2.parseDoc(valid)
|
||||
ret = doc.validateDtd(ctxt, dtd)
|
||||
if ret != 1 or e.errors:
|
||||
print("error doing DTD validation")
|
||||
sys.exit(1)
|
||||
doc.freeDoc()
|
||||
|
||||
# Test invalid document
|
||||
doc = libxml2.parseDoc(invalid)
|
||||
ret = doc.validateDtd(ctxt, dtd)
|
||||
if ret != 0 or not e.errors:
|
||||
print("Error: document supposed to be invalid")
|
||||
doc.freeDoc()
|
||||
|
||||
dtd.freeDtd()
|
||||
del dtd
|
||||
del ctxt
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env python3
|
||||
import setup_test
|
||||
import libxml2
|
||||
import sys
|
||||
|
||||
ARG = 'test string'
|
||||
|
||||
class ErrorHandler:
|
||||
|
||||
def __init__(self):
|
||||
self.errors = []
|
||||
|
||||
def handler(self, msg, data):
|
||||
if data != ARG:
|
||||
raise Exception("Error handler did not receive correct argument")
|
||||
self.errors.append(msg)
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
schema="""<?xml version="1.0"?>
|
||||
<element name="foo"
|
||||
xmlns="http://relaxng.org/ns/structure/1.0"
|
||||
xmlns:a="http://relaxng.org/ns/annotation/1.0"
|
||||
xmlns:ex1="http://www.example.com/n1"
|
||||
xmlns:ex2="http://www.example.com/n2">
|
||||
<a:documentation>A foo element.</a:documentation>
|
||||
<element name="ex1:bar1">
|
||||
<empty/>
|
||||
</element>
|
||||
<element name="ex2:bar2">
|
||||
<empty/>
|
||||
</element>
|
||||
</element>
|
||||
"""
|
||||
|
||||
valid="""<?xml version="1.0"?>
|
||||
<foo><pre1:bar1 xmlns:pre1="http://www.example.com/n1"/><pre2:bar2 xmlns:pre2="http://www.example.com/n2"/></foo>"""
|
||||
|
||||
invalid="""<?xml version="1.0"?>
|
||||
<foo><pre1:bar1 xmlns:pre1="http://www.example.com/n1">bad</pre1:bar1><pre2:bar2 xmlns:pre2="http://www.example.com/n2"/></foo>"""
|
||||
|
||||
rngp = libxml2.relaxNGNewMemParserCtxt(schema, len(schema))
|
||||
rngs = rngp.relaxNGParse()
|
||||
ctxt = rngs.relaxNGNewValidCtxt()
|
||||
e = ErrorHandler()
|
||||
ctxt.setValidityErrorHandler(e.handler, e.handler, ARG)
|
||||
|
||||
# Test valid document
|
||||
doc = libxml2.parseDoc(valid)
|
||||
ret = doc.relaxNGValidateDoc(ctxt)
|
||||
if ret != 0 or e.errors:
|
||||
print("error doing RelaxNG validation")
|
||||
sys.exit(1)
|
||||
doc.freeDoc()
|
||||
|
||||
# Test invalid document
|
||||
doc = libxml2.parseDoc(invalid)
|
||||
ret = doc.relaxNGValidateDoc(ctxt)
|
||||
if ret == 0 or not e.errors:
|
||||
print("Error: document supposed to be RelaxNG invalid")
|
||||
sys.exit(1)
|
||||
doc.freeDoc()
|
||||
|
||||
del rngp
|
||||
del rngs
|
||||
del ctxt
|
||||
libxml2.relaxNGCleanupTypes()
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env python3
|
||||
import setup_test
|
||||
import libxml2
|
||||
import sys
|
||||
|
||||
ARG = 'test string'
|
||||
|
||||
class ErrorHandler:
|
||||
|
||||
def __init__(self):
|
||||
self.errors = []
|
||||
|
||||
def handler(self, msg, data):
|
||||
if data != ARG:
|
||||
raise Exception("Error handler did not receive correct argument")
|
||||
self.errors.append(msg)
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
schema="""<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<schema xmlns = "http://www.w3.org/2001/XMLSchema">
|
||||
<element name = "Customer">
|
||||
<complexType>
|
||||
<sequence>
|
||||
<element name = "FirstName" type = "string" />
|
||||
<element name = "MiddleInitial" type = "string" />
|
||||
<element name = "LastName" type = "string" />
|
||||
</sequence>
|
||||
<attribute name = "customerID" type = "integer" />
|
||||
</complexType>
|
||||
</element>
|
||||
</schema>"""
|
||||
|
||||
valid="""<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<Customer customerID = "24332">
|
||||
<FirstName>Raymond</FirstName>
|
||||
<MiddleInitial>G</MiddleInitial>
|
||||
<LastName>Bayliss</LastName>
|
||||
</Customer>
|
||||
"""
|
||||
|
||||
invalid="""<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<Customer customerID = "24332">
|
||||
<MiddleInitial>G</MiddleInitial>
|
||||
<LastName>Bayliss</LastName>
|
||||
</Customer>
|
||||
"""
|
||||
|
||||
e = ErrorHandler()
|
||||
ctxt_parser = libxml2.schemaNewMemParserCtxt(schema, len(schema))
|
||||
ctxt_schema = ctxt_parser.schemaParse()
|
||||
ctxt_valid = ctxt_schema.schemaNewValidCtxt()
|
||||
ctxt_valid.setValidityErrorHandler(e.handler, e.handler, ARG)
|
||||
|
||||
# Test valid document
|
||||
doc = libxml2.parseDoc(valid)
|
||||
ret = doc.schemaValidateDoc(ctxt_valid)
|
||||
if ret != 0 or e.errors:
|
||||
print("error doing schema validation")
|
||||
sys.exit(1)
|
||||
doc.freeDoc()
|
||||
|
||||
# Test invalid document
|
||||
doc = libxml2.parseDoc(invalid)
|
||||
ret = doc.schemaValidateDoc(ctxt_valid)
|
||||
if ret == 0 or not e.errors:
|
||||
print("Error: document supposer to be schema invalid")
|
||||
sys.exit(1)
|
||||
doc.freeDoc()
|
||||
|
||||
del ctxt_parser
|
||||
del ctxt_schema
|
||||
del ctxt_valid
|
||||
libxml2.schemaCleanupTypes()
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
ctxt = libxml2.createFileParserCtxt("valid.xml")
|
||||
ctxt.validate(1)
|
||||
ctxt.parseDocument()
|
||||
doc = ctxt.doc()
|
||||
valid = ctxt.isValid()
|
||||
|
||||
if doc.name != "valid.xml":
|
||||
print("doc.name failed")
|
||||
sys.exit(1)
|
||||
root = doc.children
|
||||
if root.name != "doc":
|
||||
print("root.name failed")
|
||||
sys.exit(1)
|
||||
if valid != 1:
|
||||
print("validity check failed")
|
||||
sys.exit(1)
|
||||
doc.freeDoc()
|
||||
|
||||
i = 1000
|
||||
while i > 0:
|
||||
ctxt = libxml2.createFileParserCtxt("valid.xml")
|
||||
ctxt.validate(1)
|
||||
ctxt.parseDocument()
|
||||
doc = ctxt.doc()
|
||||
valid = ctxt.isValid()
|
||||
doc.freeDoc()
|
||||
if valid != 1:
|
||||
print("validity check failed")
|
||||
sys.exit(1)
|
||||
i = i - 1
|
||||
|
||||
#deactivate error messages from the validation
|
||||
def noerr(ctx, str):
|
||||
pass
|
||||
|
||||
libxml2.registerErrorHandler(noerr, None)
|
||||
|
||||
ctxt = libxml2.createFileParserCtxt("invalid.xml")
|
||||
ctxt.validate(1)
|
||||
ctxt.parseDocument()
|
||||
doc = ctxt.doc()
|
||||
valid = ctxt.isValid()
|
||||
if doc.name != "invalid.xml":
|
||||
print("doc.name failed")
|
||||
sys.exit(1)
|
||||
root = doc.children
|
||||
if root.name != "doc":
|
||||
print("root.name failed")
|
||||
sys.exit(1)
|
||||
if valid != 0:
|
||||
print("validity check failed")
|
||||
sys.exit(1)
|
||||
doc.freeDoc()
|
||||
|
||||
i = 1000
|
||||
while i > 0:
|
||||
ctxt = libxml2.createFileParserCtxt("invalid.xml")
|
||||
ctxt.validate(1)
|
||||
ctxt.parseDocument()
|
||||
doc = ctxt.doc()
|
||||
valid = ctxt.isValid()
|
||||
doc.freeDoc()
|
||||
if valid != 0:
|
||||
print("validity check failed")
|
||||
sys.exit(1)
|
||||
i = i - 1
|
||||
del ctxt
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,144 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# this tests the entities substitutions with the XmlTextReader interface
|
||||
#
|
||||
import sys
|
||||
import setup_test
|
||||
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="""<foo>
|
||||
<label>some text</label>
|
||||
<item>100</item>
|
||||
</foo>"""
|
||||
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="""<foo>
|
||||
<label>some text</label>
|
||||
<item>1000</item>
|
||||
</foo>"""
|
||||
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="""<foo>
|
||||
<label>some text</label>
|
||||
<item>1000</item>
|
||||
</foo>"""
|
||||
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)))
|
||||
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# this test exercise the XPath basic engine, parser, etc, and
|
||||
# allows to detect memory leaks
|
||||
#
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
doc = libxml2.parseFile("tst.xml")
|
||||
if doc.name != "tst.xml":
|
||||
print("doc.name error")
|
||||
sys.exit(1);
|
||||
|
||||
ctxt = doc.xpathNewContext()
|
||||
res = ctxt.xpathEval("//*")
|
||||
if len(res) != 2:
|
||||
print("xpath query: wrong node set size")
|
||||
sys.exit(1)
|
||||
if res[0].name != "doc" or res[1].name != "foo":
|
||||
print("xpath query: wrong node set value")
|
||||
sys.exit(1)
|
||||
ctxt.setContextNode(res[0])
|
||||
res = ctxt.xpathEval("foo")
|
||||
if len(res) != 1:
|
||||
print("xpath query: wrong node set size")
|
||||
sys.exit(1)
|
||||
if res[0].name != "foo":
|
||||
print("xpath query: wrong node set value")
|
||||
sys.exit(1)
|
||||
doc.freeDoc()
|
||||
ctxt.xpathFreeContext()
|
||||
i = 1000
|
||||
while i > 0:
|
||||
doc = libxml2.parseFile("tst.xml")
|
||||
ctxt = doc.xpathNewContext()
|
||||
res = ctxt.xpathEval("//*")
|
||||
doc.freeDoc()
|
||||
ctxt.xpathFreeContext()
|
||||
i = i -1
|
||||
del ctxt
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
def foo(ctx, x):
|
||||
return x + 1
|
||||
|
||||
def bar(ctx, x):
|
||||
return "%d" % (x + 2)
|
||||
|
||||
doc = libxml2.parseFile("tst.xml")
|
||||
ctxt = doc.xpathNewContext()
|
||||
res = ctxt.xpathEval("//*")
|
||||
if len(res) != 2:
|
||||
print("xpath query: wrong node set size")
|
||||
sys.exit(1)
|
||||
if res[0].name != "doc" or res[1].name != "foo":
|
||||
print("xpath query: wrong node set value")
|
||||
sys.exit(1)
|
||||
|
||||
libxml2.registerXPathFunction(ctxt._o, "foo", None, foo)
|
||||
libxml2.registerXPathFunction(ctxt._o, "bar", None, bar)
|
||||
i = 10000
|
||||
while i > 0:
|
||||
res = ctxt.xpathEval("foo(1)")
|
||||
if res != 2:
|
||||
print("xpath extension failure")
|
||||
sys.exit(1)
|
||||
i = i - 1
|
||||
i = 10000
|
||||
while i > 0:
|
||||
res = ctxt.xpathEval("bar(1)")
|
||||
if res != "3":
|
||||
print("xpath extension failure got %s expecting '3'")
|
||||
sys.exit(1)
|
||||
i = i - 1
|
||||
doc.freeDoc()
|
||||
ctxt.xpathFreeContext()
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python3
|
||||
import setup_test
|
||||
import libxml2
|
||||
import sys
|
||||
|
||||
libxml2.debugMemory(True)
|
||||
|
||||
expect="""--> Invalid expression
|
||||
--> Invalid expression
|
||||
--> Invalid expression
|
||||
--> Invalid expression
|
||||
--> Invalid expression
|
||||
--> Invalid expression
|
||||
--> Invalid expression
|
||||
--> Invalid expression
|
||||
--> Invalid expression
|
||||
--> Invalid expression
|
||||
"""
|
||||
err=""
|
||||
def callback(ctx, str):
|
||||
global err
|
||||
|
||||
err = err + "%s %s" % (ctx, str)
|
||||
|
||||
libxml2.registerErrorHandler(callback, "-->")
|
||||
|
||||
doc = libxml2.parseDoc("<fish/>")
|
||||
ctxt = doc.xpathNewContext()
|
||||
ctxt.setContextNode(doc)
|
||||
badexprs = (
|
||||
":false()", "bad:()", "bad(:)", ":bad(:)", "bad:(:)", "bad:bad(:)",
|
||||
"a:/b", "/c:/d", "//e:/f", "g://h"
|
||||
)
|
||||
for expr in badexprs:
|
||||
try:
|
||||
ctxt.xpathEval(expr)
|
||||
except libxml2.xpathError:
|
||||
pass
|
||||
else:
|
||||
print("Unexpectedly legal expression:", expr)
|
||||
ctxt.xpathFreeContext()
|
||||
doc.freeDoc()
|
||||
|
||||
if err != expect:
|
||||
print("error")
|
||||
print("received %s" %(err))
|
||||
print("expected %s" %(expect))
|
||||
sys.exit(1)
|
||||
|
||||
libxml2.cleanupParser()
|
||||
leakedbytes = libxml2.debugMemory(True)
|
||||
if leakedbytes == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak", leakedbytes, "bytes")
|
||||
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
expect=' xmlns:a="urn:whatevar"'
|
||||
|
||||
# Memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
d = libxml2.parseDoc("<a:a xmlns:a='urn:whatevar'/>")
|
||||
res=""
|
||||
for n in d.xpathEval("//namespace::*"):
|
||||
res = res + n.serialize()
|
||||
del n
|
||||
d.freeDoc()
|
||||
|
||||
if res != expect:
|
||||
print("test5 failed: unexpected output")
|
||||
print(res)
|
||||
del res
|
||||
del d
|
||||
# Memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import setup_test
|
||||
import libxml2
|
||||
|
||||
#memory debug specific
|
||||
libxml2.debugMemory(1)
|
||||
|
||||
#
|
||||
# A document hosting the nodes returned from the extension function
|
||||
#
|
||||
mydoc = libxml2.newDoc("1.0")
|
||||
|
||||
def foo(ctx, str):
|
||||
global mydoc
|
||||
|
||||
#
|
||||
# test returning a node set works as expected
|
||||
#
|
||||
parent = mydoc.newDocNode(None, 'p', None)
|
||||
mydoc.addChild(parent)
|
||||
node = mydoc.newDocText(str)
|
||||
parent.addChild(node)
|
||||
return [parent]
|
||||
|
||||
doc = libxml2.parseFile("tst.xml")
|
||||
ctxt = doc.xpathNewContext()
|
||||
libxml2.registerXPathFunction(ctxt._o, "foo", None, foo)
|
||||
res = ctxt.xpathEval("foo('hello')")
|
||||
if type(res) != type([]):
|
||||
print("Failed to return a nodeset")
|
||||
sys.exit(1)
|
||||
if len(res) != 1:
|
||||
print("Unexpected nodeset size")
|
||||
sys.exit(1)
|
||||
node = res[0]
|
||||
if node.name != 'p':
|
||||
print("Unexpected nodeset element result")
|
||||
sys.exit(1)
|
||||
node = node.children
|
||||
if node.type != 'text':
|
||||
print("Unexpected nodeset element children type")
|
||||
sys.exit(1)
|
||||
if node.content != 'hello':
|
||||
print("Unexpected nodeset element children content")
|
||||
sys.exit(1)
|
||||
|
||||
doc.freeDoc()
|
||||
mydoc.freeDoc()
|
||||
ctxt.xpathFreeContext()
|
||||
|
||||
#memory debug specific
|
||||
libxml2.cleanupParser()
|
||||
if libxml2.debugMemory(1) == 0:
|
||||
print("OK")
|
||||
else:
|
||||
print("Memory leak %d bytes" % (libxml2.debugMemory(1)))
|
||||
@@ -0,0 +1,895 @@
|
||||
/*
|
||||
* types.c: converter functions between the internal representation
|
||||
* and the Python objects
|
||||
*
|
||||
* See Copyright for the status of this software.
|
||||
*
|
||||
* daniel@veillard.com
|
||||
*/
|
||||
#include "libxml_wrap.h"
|
||||
#include <libxml/xpathInternals.h>
|
||||
#include <string.h>
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
#define PY_IMPORT_STRING_SIZE PyUnicode_FromStringAndSize
|
||||
#define PY_IMPORT_STRING PyUnicode_FromString
|
||||
#define PY_IMPORT_INT PyLong_FromLong
|
||||
#else
|
||||
#define PY_IMPORT_STRING_SIZE PyString_FromStringAndSize
|
||||
#define PY_IMPORT_STRING PyString_FromString
|
||||
#define PY_IMPORT_INT PyInt_FromLong
|
||||
#endif
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#include <crtdbg.h>
|
||||
|
||||
/* Taken from info on MSDN site, as we may not have the Windows WDK/DDK headers */
|
||||
typedef struct _IO_STATUS_BLOCK {
|
||||
union {
|
||||
NTSTATUS Status;
|
||||
PVOID Pointer;
|
||||
} DUMMYUNIONNAME;
|
||||
ULONG_PTR Information;
|
||||
} IO_STATUS_BLOCK;
|
||||
|
||||
typedef struct _FILE_ACCESS_INFORMATION {
|
||||
ACCESS_MASK AccessFlags;
|
||||
} FILE_ACCESS_INFORMATION;
|
||||
|
||||
typedef NTSTATUS (*t_NtQueryInformationFile) (HANDLE FileHandle,
|
||||
IO_STATUS_BLOCK *IoStatusBlock,
|
||||
PVOID FileInformation,
|
||||
ULONG Length,
|
||||
int FileInformationClass); /* this is an Enum */
|
||||
|
||||
#if (defined (_MSC_VER) && _MSC_VER >= 1400)
|
||||
/*
|
||||
* This is the (empty) invalid parameter handler
|
||||
* that is used for Visual C++ 2005 (and later) builds
|
||||
* so that we can use this instead of the system automatically
|
||||
* aborting the process.
|
||||
*
|
||||
* This is necessary as we use _get_oshandle() to check the validity
|
||||
* of the file descriptors as we close them, so when an invalid file
|
||||
* descriptor is passed into that function as we check on it, we get
|
||||
* -1 as the result, instead of the gspawn helper program aborting.
|
||||
*
|
||||
* Please see http://msdn.microsoft.com/zh-tw/library/ks2530z6%28v=vs.80%29.aspx
|
||||
* for an explanation on this.
|
||||
*/
|
||||
void
|
||||
myInvalidParameterHandler(const wchar_t *expression,
|
||||
const wchar_t *function,
|
||||
const wchar_t *file,
|
||||
unsigned int line,
|
||||
uintptr_t pReserved)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
FILE *
|
||||
libxml_PyFileGet(PyObject *f) {
|
||||
FILE *res;
|
||||
const char *mode;
|
||||
int fd = PyObject_AsFileDescriptor(f);
|
||||
|
||||
#ifdef _WIN32
|
||||
intptr_t w_fh = -1;
|
||||
HMODULE hntdll = NULL;
|
||||
IO_STATUS_BLOCK status_block;
|
||||
FILE_ACCESS_INFORMATION ai;
|
||||
t_NtQueryInformationFile NtQueryInformationFile;
|
||||
BOOL is_read = FALSE;
|
||||
BOOL is_write = FALSE;
|
||||
BOOL is_append = FALSE;
|
||||
|
||||
#if (defined (_MSC_VER) && _MSC_VER >= 1400)
|
||||
/* set up our empty invalid parameter handler */
|
||||
_invalid_parameter_handler oldHandler, newHandler;
|
||||
newHandler = myInvalidParameterHandler;
|
||||
oldHandler = _set_invalid_parameter_handler(newHandler);
|
||||
|
||||
/* Disable the message box for assertions. */
|
||||
_CrtSetReportMode(_CRT_ASSERT, 0);
|
||||
#endif
|
||||
|
||||
w_fh = _get_osfhandle(fd);
|
||||
|
||||
if (w_fh == -1)
|
||||
return(NULL);
|
||||
|
||||
hntdll = GetModuleHandleW(L"ntdll.dll");
|
||||
|
||||
if (hntdll == NULL)
|
||||
return(NULL);
|
||||
NtQueryInformationFile = (t_NtQueryInformationFile) (void (*)(void))
|
||||
GetProcAddress(hntdll, "NtQueryInformationFile");
|
||||
|
||||
if (NtQueryInformationFile != NULL &&
|
||||
(NtQueryInformationFile((HANDLE)w_fh,
|
||||
&status_block,
|
||||
&ai,
|
||||
sizeof(FILE_ACCESS_INFORMATION),
|
||||
8) == 0)) /* 8 means "FileAccessInformation" */
|
||||
{
|
||||
if (ai.AccessFlags & FILE_READ_DATA)
|
||||
is_read = TRUE;
|
||||
if (ai.AccessFlags & FILE_WRITE_DATA)
|
||||
is_write = TRUE;
|
||||
if (ai.AccessFlags & FILE_APPEND_DATA)
|
||||
is_append = TRUE;
|
||||
|
||||
if (is_write) {
|
||||
if (is_read) {
|
||||
if (is_append)
|
||||
mode = "a+";
|
||||
else
|
||||
mode = "rw";
|
||||
} else {
|
||||
if (is_append)
|
||||
mode = "a";
|
||||
else
|
||||
mode = "w";
|
||||
}
|
||||
} else {
|
||||
if (is_append)
|
||||
mode = "r+";
|
||||
else
|
||||
mode = "r";
|
||||
}
|
||||
}
|
||||
|
||||
FreeLibrary(hntdll);
|
||||
|
||||
if (!is_write && !is_read) /* also happens if we did not load or run NtQueryInformationFile() successfully */
|
||||
return(NULL);
|
||||
#else
|
||||
int flags;
|
||||
|
||||
/*
|
||||
* macOS returns O_RDWR for standard streams, but fails to write to
|
||||
* stdout or stderr when opened with fdopen(dup_fd, "rw").
|
||||
*/
|
||||
switch (fd) {
|
||||
case STDIN_FILENO:
|
||||
mode = "r";
|
||||
break;
|
||||
case STDOUT_FILENO:
|
||||
case STDERR_FILENO:
|
||||
mode = "w";
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* Get the flags on the fd to understand how it was opened
|
||||
*/
|
||||
flags = fcntl(fd, F_GETFL, 0);
|
||||
switch (flags & O_ACCMODE) {
|
||||
case O_RDWR:
|
||||
if (flags & O_APPEND)
|
||||
mode = "a+";
|
||||
else
|
||||
mode = "rw";
|
||||
break;
|
||||
case O_RDONLY:
|
||||
if (flags & O_APPEND)
|
||||
mode = "r+";
|
||||
else
|
||||
mode = "r";
|
||||
break;
|
||||
case O_WRONLY:
|
||||
if (flags & O_APPEND)
|
||||
mode = "a";
|
||||
else
|
||||
mode = "w";
|
||||
break;
|
||||
default:
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* the FILE struct gets a new fd, so that it can be closed
|
||||
* independently of the file descriptor given. The risk though is
|
||||
* lack of sync. So at the python level sync must be implemented
|
||||
* before and after a conversion took place. No way around it
|
||||
* in the Python3 infrastructure !
|
||||
* The duplicated fd and FILE * will be released in the subsequent
|
||||
* call to libxml_PyFileRelease() which must be generated accordingly
|
||||
*/
|
||||
fd = dup(fd);
|
||||
if (fd == -1)
|
||||
return(NULL);
|
||||
res = fdopen(fd, mode);
|
||||
if (res == NULL) {
|
||||
close(fd);
|
||||
return(NULL);
|
||||
}
|
||||
return(res);
|
||||
}
|
||||
|
||||
void libxml_PyFileRelease(FILE *f) {
|
||||
if (f != NULL)
|
||||
fclose(f);
|
||||
}
|
||||
#endif
|
||||
|
||||
PyObject *
|
||||
libxml_intWrap(int val)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
ret = PY_IMPORT_INT((long) val);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_longWrap(long val)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
ret = PyLong_FromLong(val);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_doubleWrap(double val)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
ret = PyFloat_FromDouble((double) val);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_charPtrWrap(char *str)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (str == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret = PY_IMPORT_STRING(str);
|
||||
xmlFree(str);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_charPtrConstWrap(const char *str)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (str == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret = PY_IMPORT_STRING(str);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlCharPtrWrap(xmlChar * str)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (str == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret = PY_IMPORT_STRING((char *) str);
|
||||
xmlFree(str);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlCharPtrConstWrap(const xmlChar * str)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (str == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret = PY_IMPORT_STRING((char *) str);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_constcharPtrWrap(const char *str)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (str == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret = PY_IMPORT_STRING(str);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_constxmlCharPtrWrap(const xmlChar * str)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (str == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret = PY_IMPORT_STRING((char *) str);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlDocPtrWrap(xmlDocPtr doc)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (doc == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
/* TODO: look at deallocation */
|
||||
ret = PyCapsule_New((void *) doc, (char *) "xmlDocPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlNodePtrWrap(xmlNodePtr node)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (node == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret = PyCapsule_New((void *) node, (char *) "xmlNodePtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlURIPtrWrap(xmlURIPtr uri)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (uri == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret = PyCapsule_New((void *) uri, (char *) "xmlURIPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlNsPtrWrap(xmlNsPtr ns)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (ns == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret = PyCapsule_New((void *) ns, (char *) "xmlNsPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlAttrPtrWrap(xmlAttrPtr attr)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (attr == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret = PyCapsule_New((void *) attr, (char *) "xmlAttrPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlAttributePtrWrap(xmlAttributePtr attr)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (attr == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret = PyCapsule_New((void *) attr, (char *) "xmlAttributePtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlElementPtrWrap(xmlElementPtr elem)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (elem == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret = PyCapsule_New((void *) elem, (char *) "xmlElementPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlParserCtxtPtrWrap(xmlParserCtxtPtr ctxt)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (ctxt == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
|
||||
ret = PyCapsule_New((void *) ctxt, (char *) "xmlParserCtxtPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#ifdef LIBXML_XPATH_ENABLED
|
||||
PyObject *
|
||||
libxml_xmlXPathContextPtrWrap(xmlXPathContextPtr ctxt)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (ctxt == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret = PyCapsule_New((void *) ctxt, (char *) "xmlXPathContextPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlXPathParserContextPtrWrap(xmlXPathParserContextPtr ctxt)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (ctxt == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret = PyCapsule_New((void *)ctxt, (char *)"xmlXPathParserContextPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* libxml_xmlXPathDestructNsNode:
|
||||
* cap: xmlNsPtr namespace node capsule object
|
||||
*
|
||||
* This function is called if and when a namespace node returned in
|
||||
* an XPath node set is to be destroyed. That's the only kind of
|
||||
* object returned in node set not directly linked to the original
|
||||
* xmlDoc document, see xmlXPathNodeSetDupNs.
|
||||
*/
|
||||
#if PY_VERSION_HEX < 0x02070000
|
||||
static void
|
||||
libxml_xmlXPathDestructNsNode(void *cap, void *desc ATTRIBUTE_UNUSED)
|
||||
#else
|
||||
static void
|
||||
libxml_xmlXPathDestructNsNode(PyObject *cap)
|
||||
#endif
|
||||
{
|
||||
#if PY_VERSION_HEX < 0x02070000
|
||||
xmlXPathNodeSetFreeNs((xmlNsPtr) cap);
|
||||
#else
|
||||
xmlXPathNodeSetFreeNs((xmlNsPtr) PyCapsule_GetPointer(cap, "xmlNsPtr"));
|
||||
#endif
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlXPathObjectPtrWrap(xmlXPathObjectPtr obj)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (obj == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
switch (obj->type) {
|
||||
case XPATH_XSLT_TREE: {
|
||||
if ((obj->nodesetval == NULL) ||
|
||||
(obj->nodesetval->nodeNr == 0) ||
|
||||
(obj->nodesetval->nodeTab == NULL)) {
|
||||
ret = PyList_New(0);
|
||||
} else {
|
||||
int i, len = 0;
|
||||
xmlNodePtr node;
|
||||
|
||||
node = obj->nodesetval->nodeTab[0]->children;
|
||||
while (node != NULL) {
|
||||
len++;
|
||||
node = node->next;
|
||||
}
|
||||
ret = PyList_New(len);
|
||||
node = obj->nodesetval->nodeTab[0]->children;
|
||||
for (i = 0;i < len;i++) {
|
||||
PyList_SetItem(ret, i, libxml_xmlNodePtrWrap(node));
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Return now, do not free the object passed down
|
||||
*/
|
||||
return (ret);
|
||||
}
|
||||
case XPATH_NODESET:
|
||||
if ((obj->nodesetval == NULL)
|
||||
|| (obj->nodesetval->nodeNr == 0)) {
|
||||
ret = PyList_New(0);
|
||||
} else {
|
||||
int i;
|
||||
xmlNodePtr node;
|
||||
|
||||
ret = PyList_New(obj->nodesetval->nodeNr);
|
||||
for (i = 0; i < obj->nodesetval->nodeNr; i++) {
|
||||
node = obj->nodesetval->nodeTab[i];
|
||||
if (node->type == XML_NAMESPACE_DECL) {
|
||||
PyObject *ns = PyCapsule_New((void *) node,
|
||||
(char *) "xmlNsPtr",
|
||||
libxml_xmlXPathDestructNsNode);
|
||||
PyList_SetItem(ret, i, ns);
|
||||
/* make sure the xmlNsPtr is not destroyed now */
|
||||
obj->nodesetval->nodeTab[i] = NULL;
|
||||
} else {
|
||||
PyList_SetItem(ret, i, libxml_xmlNodePtrWrap(node));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case XPATH_BOOLEAN:
|
||||
ret = PY_IMPORT_INT((long) obj->boolval);
|
||||
break;
|
||||
case XPATH_NUMBER:
|
||||
ret = PyFloat_FromDouble(obj->floatval);
|
||||
break;
|
||||
case XPATH_STRING:
|
||||
ret = PY_IMPORT_STRING((char *) obj->stringval);
|
||||
break;
|
||||
default:
|
||||
Py_INCREF(Py_None);
|
||||
ret = Py_None;
|
||||
}
|
||||
xmlXPathFreeObject(obj);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
xmlXPathObjectPtr
|
||||
libxml_xmlXPathObjectPtrConvert(PyObject *obj)
|
||||
{
|
||||
xmlXPathObjectPtr ret = NULL;
|
||||
|
||||
if (obj == NULL) {
|
||||
return (NULL);
|
||||
}
|
||||
if (PyFloat_Check (obj)) {
|
||||
ret = xmlXPathNewFloat((double) PyFloat_AS_DOUBLE(obj));
|
||||
} else if (PyLong_Check(obj)) {
|
||||
#ifdef PyLong_AS_LONG
|
||||
ret = xmlXPathNewFloat((double) PyLong_AS_LONG(obj));
|
||||
#else
|
||||
ret = xmlXPathNewFloat((double) PyInt_AS_LONG(obj));
|
||||
#endif
|
||||
#ifdef PyBool_Check
|
||||
} else if (PyBool_Check (obj)) {
|
||||
|
||||
if (obj == Py_True) {
|
||||
ret = xmlXPathNewBoolean(1);
|
||||
}
|
||||
else {
|
||||
ret = xmlXPathNewBoolean(0);
|
||||
}
|
||||
#endif
|
||||
} else if (PyBytes_Check (obj)) {
|
||||
xmlChar *str;
|
||||
|
||||
str = xmlStrndup((const xmlChar *) PyBytes_AS_STRING(obj),
|
||||
PyBytes_GET_SIZE(obj));
|
||||
ret = xmlXPathWrapString(str);
|
||||
#ifdef PyUnicode_Check
|
||||
} else if (PyUnicode_Check (obj)) {
|
||||
#if PY_VERSION_HEX >= 0x03030000
|
||||
xmlChar *str;
|
||||
const char *tmp;
|
||||
Py_ssize_t size;
|
||||
|
||||
/* tmp doesn't need to be deallocated */
|
||||
tmp = PyUnicode_AsUTF8AndSize(obj, &size);
|
||||
str = xmlStrndup((const xmlChar *) tmp, (int) size);
|
||||
ret = xmlXPathWrapString(str);
|
||||
#else
|
||||
xmlChar *str = NULL;
|
||||
PyObject *b;
|
||||
|
||||
b = PyUnicode_AsUTF8String(obj);
|
||||
if (b != NULL) {
|
||||
str = xmlStrndup((const xmlChar *) PyBytes_AS_STRING(b),
|
||||
PyBytes_GET_SIZE(b));
|
||||
Py_DECREF(b);
|
||||
}
|
||||
ret = xmlXPathWrapString(str);
|
||||
#endif
|
||||
#endif
|
||||
} else if (PyList_Check (obj)) {
|
||||
int i;
|
||||
PyObject *node;
|
||||
xmlNodePtr cur;
|
||||
xmlNodeSetPtr set;
|
||||
|
||||
set = xmlXPathNodeSetCreate(NULL);
|
||||
|
||||
for (i = 0; i < PyList_Size(obj); i++) {
|
||||
node = PyList_GetItem(obj, i);
|
||||
if ((node == NULL) || (node->ob_type == NULL))
|
||||
continue;
|
||||
|
||||
cur = NULL;
|
||||
if (PyCapsule_CheckExact(node)) {
|
||||
cur = PyxmlNode_Get(node);
|
||||
} else if ((PyObject_HasAttrString(node, (char *) "_o")) &&
|
||||
(PyObject_HasAttrString(node, (char *) "get_doc"))) {
|
||||
PyObject *wrapper;
|
||||
|
||||
wrapper = PyObject_GetAttrString(node, (char *) "_o");
|
||||
if (wrapper != NULL)
|
||||
cur = PyxmlNode_Get(wrapper);
|
||||
} else {
|
||||
}
|
||||
if (cur != NULL) {
|
||||
xmlXPathNodeSetAdd(set, cur);
|
||||
}
|
||||
}
|
||||
ret = xmlXPathWrapNodeSet(set);
|
||||
} else {
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
#endif /* LIBXML_XPATH_ENABLED */
|
||||
|
||||
PyObject *
|
||||
libxml_xmlValidCtxtPtrWrap(xmlValidCtxtPtr valid)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (valid == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
|
||||
ret =
|
||||
PyCapsule_New((void *) valid,
|
||||
(char *) "xmlValidCtxtPtr", NULL);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#ifdef LIBXML_CATALOG_ENABLED
|
||||
PyObject *
|
||||
libxml_xmlCatalogPtrWrap(xmlCatalogPtr catal)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (catal == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret =
|
||||
PyCapsule_New((void *) catal,
|
||||
(char *) "xmlCatalogPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
#endif /* LIBXML_CATALOG_ENABLED */
|
||||
|
||||
PyObject *
|
||||
libxml_xmlOutputBufferPtrWrap(xmlOutputBufferPtr buffer)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (buffer == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret =
|
||||
PyCapsule_New((void *) buffer,
|
||||
(char *) "xmlOutputBufferPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlParserInputBufferPtrWrap(xmlParserInputBufferPtr buffer)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (buffer == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret =
|
||||
PyCapsule_New((void *) buffer,
|
||||
(char *) "xmlParserInputBufferPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#ifdef LIBXML_REGEXP_ENABLED
|
||||
PyObject *
|
||||
libxml_xmlRegexpPtrWrap(xmlRegexpPtr regexp)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (regexp == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret =
|
||||
PyCapsule_New((void *) regexp,
|
||||
(char *) "xmlRegexpPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
#endif /* LIBXML_REGEXP_ENABLED */
|
||||
|
||||
#ifdef LIBXML_READER_ENABLED
|
||||
PyObject *
|
||||
libxml_xmlTextReaderPtrWrap(xmlTextReaderPtr reader)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (reader == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret =
|
||||
PyCapsule_New((void *) reader,
|
||||
(char *) "xmlTextReaderPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlTextReaderLocatorPtrWrap(xmlTextReaderLocatorPtr locator)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (locator == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret =
|
||||
PyCapsule_New((void *) locator,
|
||||
(char *) "xmlTextReaderLocatorPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
#endif /* LIBXML_READER_ENABLED */
|
||||
|
||||
#ifdef LIBXML_RELAXNG_ENABLED
|
||||
PyObject *
|
||||
libxml_xmlRelaxNGPtrWrap(xmlRelaxNGPtr ctxt)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (ctxt == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret =
|
||||
PyCapsule_New((void *) ctxt,
|
||||
(char *) "xmlRelaxNGPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlRelaxNGParserCtxtPtrWrap(xmlRelaxNGParserCtxtPtr ctxt)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (ctxt == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret =
|
||||
PyCapsule_New((void *) ctxt,
|
||||
(char *) "xmlRelaxNGParserCtxtPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
PyObject *
|
||||
libxml_xmlRelaxNGValidCtxtPtrWrap(xmlRelaxNGValidCtxtPtr valid)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (valid == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret =
|
||||
PyCapsule_New((void *) valid,
|
||||
(char *) "xmlRelaxNGValidCtxtPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
#endif /* LIBXML_RELAXNG_ENABLED */
|
||||
|
||||
#ifdef LIBXML_SCHEMAS_ENABLED
|
||||
PyObject *
|
||||
libxml_xmlSchemaPtrWrap(xmlSchemaPtr ctxt)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (ctxt == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret =
|
||||
PyCapsule_New((void *) ctxt,
|
||||
(char *) "xmlSchemaPtr", NULL);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlSchemaParserCtxtPtrWrap(xmlSchemaParserCtxtPtr ctxt)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (ctxt == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
ret =
|
||||
PyCapsule_New((void *) ctxt,
|
||||
(char *) "xmlSchemaParserCtxtPtr", NULL);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlSchemaValidCtxtPtrWrap(xmlSchemaValidCtxtPtr valid)
|
||||
{
|
||||
PyObject *ret;
|
||||
|
||||
if (valid == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
|
||||
ret =
|
||||
PyCapsule_New((void *) valid,
|
||||
(char *) "xmlSchemaValidCtxtPtr", NULL);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
#endif /* LIBXML_SCHEMAS_ENABLED */
|
||||
|
||||
static void
|
||||
libxml_xmlDestructError(PyObject *cap) {
|
||||
xmlErrorPtr err = (xmlErrorPtr) PyCapsule_GetPointer(cap, "xmlErrorPtr");
|
||||
xmlResetError(err);
|
||||
xmlFree(err);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
libxml_xmlErrorPtrWrap(const xmlError *error)
|
||||
{
|
||||
PyObject *ret;
|
||||
xmlErrorPtr copy;
|
||||
|
||||
if (error == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
copy = xmlMalloc(sizeof(*copy));
|
||||
if (copy == NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return (Py_None);
|
||||
}
|
||||
memset(copy, 0, sizeof(*copy));
|
||||
xmlCopyError(error, copy);
|
||||
ret = PyCapsule_New(copy, "xmlErrorPtr", libxml_xmlDestructError);
|
||||
return (ret);
|
||||
}
|
||||
Reference in New Issue
Block a user