fix bug #72490 added methods serialize() and saveTo() to all node
* tree.c: fix bug #72490
* python/libxml.c python/libxml.py: added methods serialize()
and saveTo() to all node elements.
Daniel
diff --git a/python/libxml.c b/python/libxml.c
index 8c7d295..efa42fc 100644
--- a/python/libxml.c
+++ b/python/libxml.c
@@ -1458,6 +1458,225 @@
/************************************************************************
* *
+ * Serialization front-end *
+ * *
+ ************************************************************************/
+
+PyObject *
+libxml_serializeNode(PyObject *self, PyObject *args) {
+ PyObject *py_retval = NULL;
+ xmlChar *c_retval;
+ PyObject *pyobj_node;
+ xmlNodePtr node;
+ xmlDocPtr doc;
+ xmlChar *encoding;
+ int format;
+ int len;
+
+ if (!PyArg_ParseTuple(args, "Ozi:serializeNode", &pyobj_node,
+ &encoding, &format))
+ return(NULL);
+ node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
+
+ if (node == NULL) {
+ Py_INCREF(Py_None);
+ return(Py_None);
+ }
+ if (node->type == XML_DOCUMENT_NODE) {
+ doc = (xmlDocPtr) node;
+ xmlDocDumpFormatMemoryEnc(doc, &c_retval, &len, encoding, format);
+ py_retval = libxml_charPtrWrap(c_retval);
+ } else if (node->type == XML_HTML_DOCUMENT_NODE) {
+ xmlOutputBufferPtr buf;
+ xmlCharEncodingHandlerPtr handler = NULL;
+
+ doc = (xmlDocPtr) node;
+ if (encoding == NULL)
+ encoding = (xmlChar *) htmlGetMetaEncoding(doc);
+
+ if (encoding != NULL) {
+ handler = xmlFindCharEncodingHandler(encoding);
+ if (handler == NULL) {
+ Py_INCREF(Py_None);
+ return(Py_None);
+ }
+ }
+
+ /*
+ * Fallback to HTML or ASCII when the encoding is unspecified
+ */
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("HTML");
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("ascii");
+
+ buf = xmlAllocOutputBuffer(handler);
+ if (buf == NULL) {
+ Py_INCREF(Py_None);
+ return(Py_None);
+ }
+ htmlDocContentDumpFormatOutput(buf, doc, encoding, format);
+ xmlOutputBufferFlush(buf);
+ if (buf->conv != NULL) {
+ len = buf->conv->use;
+ c_retval = buf->conv->content;
+ buf->conv->content = NULL;
+ } else {
+ len = buf->buffer->use;
+ c_retval = buf->buffer->content;
+ buf->buffer->content = NULL;
+ }
+ (void)xmlOutputBufferClose(buf);
+ py_retval = libxml_charPtrWrap(c_retval);
+ } else {
+ doc = node->doc;
+ if (doc->type == XML_DOCUMENT_NODE) {
+ xmlOutputBufferPtr buf;
+ xmlCharEncodingHandlerPtr handler = NULL;
+
+ if (encoding != NULL) {
+ handler = xmlFindCharEncodingHandler(encoding);
+ if (handler == NULL) {
+ Py_INCREF(Py_None);
+ return(Py_None);
+ }
+ }
+
+ buf = xmlAllocOutputBuffer(handler);
+ if (buf == NULL) {
+ Py_INCREF(Py_None);
+ return(Py_None);
+ }
+ xmlNodeDumpOutput(buf, doc, node, 0, format, encoding);
+ xmlOutputBufferFlush(buf);
+ if (buf->conv != NULL) {
+ len = buf->conv->use;
+ c_retval = buf->conv->content;
+ buf->conv->content = NULL;
+ } else {
+ len = buf->buffer->use;
+ c_retval = buf->buffer->content;
+ buf->buffer->content = NULL;
+ }
+ (void)xmlOutputBufferClose(buf);
+ py_retval = libxml_charPtrWrap(c_retval);
+ } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
+ xmlOutputBufferPtr buf;
+ xmlCharEncodingHandlerPtr handler = NULL;
+
+ if (encoding != NULL) {
+ handler = xmlFindCharEncodingHandler(encoding);
+ if (handler == NULL) {
+ Py_INCREF(Py_None);
+ return(Py_None);
+ }
+ }
+
+ /*
+ * Fallback to HTML or ASCII when the encoding is unspecified
+ */
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("HTML");
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("ascii");
+
+ buf = xmlAllocOutputBuffer(handler);
+ if (buf == NULL) {
+ Py_INCREF(Py_None);
+ return(Py_None);
+ }
+ htmlNodeDumpFormatOutput(buf, doc, node, encoding, format);
+ xmlOutputBufferFlush(buf);
+ if (buf->conv != NULL) {
+ len = buf->conv->use;
+ c_retval = buf->conv->content;
+ buf->conv->content = NULL;
+ } else {
+ len = buf->buffer->use;
+ c_retval = buf->buffer->content;
+ buf->buffer->content = NULL;
+ }
+ (void)xmlOutputBufferClose(buf);
+ py_retval = libxml_charPtrWrap(c_retval);
+ } else {
+ Py_INCREF(Py_None);
+ return(Py_None);
+ }
+ }
+ return(py_retval);
+}
+
+PyObject *
+libxml_saveNodeTo(PyObject *self, PyObject *args) {
+ PyObject *py_file = NULL;
+ FILE *output;
+ PyObject *pyobj_node;
+ xmlNodePtr node;
+ xmlDocPtr doc;
+ xmlChar *encoding;
+ int format;
+ int len;
+ xmlOutputBufferPtr buf;
+ xmlCharEncodingHandlerPtr handler = NULL;
+
+ if (!PyArg_ParseTuple(args, "OOzi:serializeNode", &pyobj_node,
+ &py_file, &encoding, &format))
+ return(NULL);
+ node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
+
+ if (node == NULL) {
+ return(PyInt_FromLong((long) -1));
+ }
+ if ((py_file == NULL) || (!(PyFile_Check(py_file)))) {
+ return(PyInt_FromLong((long) -1));
+ }
+ output = PyFile_AsFile(py_file);
+ if (output == NULL) {
+ return(PyInt_FromLong((long) -1));
+ }
+
+ if (node->type == XML_DOCUMENT_NODE) {
+ doc = (xmlDocPtr) node;
+ } else if (node->type == XML_HTML_DOCUMENT_NODE) {
+ doc = (xmlDocPtr) node;
+ } else {
+ doc = node->doc;
+ }
+ if (doc->type == XML_HTML_DOCUMENT_NODE) {
+ if (encoding == NULL)
+ encoding = (xmlChar *) htmlGetMetaEncoding(doc);
+ }
+ if (encoding != NULL) {
+ handler = xmlFindCharEncodingHandler(encoding);
+ if (handler == NULL) {
+ return(PyInt_FromLong((long) -1));
+ }
+ }
+ if (doc->type == XML_HTML_DOCUMENT_NODE) {
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("HTML");
+ if (handler == NULL)
+ handler = xmlFindCharEncodingHandler("ascii");
+ }
+
+ buf = xmlOutputBufferCreateFile(output, handler);
+ if (node->type == XML_DOCUMENT_NODE) {
+ len = xmlSaveFormatFileTo(buf, doc, encoding, format);
+ } else if (node->type == XML_HTML_DOCUMENT_NODE) {
+ htmlDocContentDumpFormatOutput(buf, doc, encoding, format);
+ len = xmlOutputBufferClose(buf);
+ } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
+ htmlNodeDumpFormatOutput(buf, doc, node, encoding, format);
+ len = xmlOutputBufferClose(buf);
+ } else {
+ xmlNodeDumpOutput(buf, doc, node, 0, format, encoding);
+ len = xmlOutputBufferClose(buf);
+ }
+ return(PyInt_FromLong((long) len));
+}
+
+/************************************************************************
+ * *
* Extra stuff *
* *
************************************************************************/
@@ -1497,6 +1716,8 @@
{ "type", libxml_type, METH_VARARGS, NULL },
{ "doc", libxml_doc, METH_VARARGS, NULL },
{ "xmlNewNode", libxml_xmlNewNode, METH_VARARGS, NULL },
+ { "serializeNode", libxml_serializeNode, METH_VARARGS, NULL },
+ { "saveNodeTo", libxml_saveNodeTo, METH_VARARGS, NULL },
{ NULL }
};
diff --git a/python/libxml.py b/python/libxml.py
index 18f6840..8d99466 100644
--- a/python/libxml.py
+++ b/python/libxml.py
@@ -132,7 +132,7 @@
# 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 and content access
+# doc reference, content access and serializing to a string or URI
#
class xmlCore:
def __init__(self, _obj=None):
@@ -238,6 +238,17 @@
return xmlDoc(_doc=ret)
def free(self):
libxml2mod.freeDoc(self._o)
+
+ #
+ # 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)
#
# converters to present a nicer view of the XPath returns