diff options
author | Hans Baier <hansfbaier@googlemail.com> | 2008-05-22 12:06:20 +0000 |
---|---|---|
committer | Hans Baier <hansfbaier@googlemail.com> | 2008-05-22 12:06:20 +0000 |
commit | 376263d92514f0e55daee8ea0c33cd226da1e97c (patch) | |
tree | 35082336188150864f99c967f739196ceacd17ae /libs/pbd/xml++.cc | |
parent | 975d4109305c1e2b8dfece2d2a8798b90469f2fd (diff) |
* added XPath support to pbd/xml++
git-svn-id: svn://localhost/ardour2/branches/3.0@3384 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/pbd/xml++.cc')
-rw-r--r-- | libs/pbd/xml++.cc | 67 |
1 files changed, 64 insertions, 3 deletions
diff --git a/libs/pbd/xml++.cc b/libs/pbd/xml++.cc index e603b4c50f..9881dc5bee 100644 --- a/libs/pbd/xml++.cc +++ b/libs/pbd/xml++.cc @@ -6,9 +6,14 @@ #include <pbd/xml++.h> #include <libxml/debugXML.h> +#include <libxml/xpath.h> +#include <libxml/xpathInternals.h> + +#define XML_VERSION "1.0" static XMLNode *readnode(xmlNodePtr); static void writenode(xmlDocPtr, XMLNode *, xmlNodePtr, int); +static XMLNodeList *find_impl(xmlXPathContext* ctxt, const string xpath); XMLTree::XMLTree() : _filename(), @@ -99,6 +104,7 @@ XMLTree::read_buffer(const string & buffer) return true; } + bool XMLTree::write(void) const { @@ -107,7 +113,7 @@ XMLTree::write(void) const int result; xmlKeepBlanksDefault(0); - doc = xmlNewDoc((xmlChar *) "1.0"); + doc = xmlNewDoc((xmlChar *) XML_VERSION); xmlSetDocCompressMode(doc, _compression); writenode(doc, _root, doc->children, 1); result = xmlSaveFormatFileEnc(_filename.c_str(), doc, "UTF-8", 1); @@ -127,7 +133,7 @@ XMLTree::debug(FILE* out) const XMLNodeList children; xmlKeepBlanksDefault(0); - doc = xmlNewDoc((xmlChar *) "1.0"); + doc = xmlNewDoc((xmlChar *) XML_VERSION); xmlSetDocCompressMode(doc, _compression); writenode(doc, _root, doc->children, 1); xmlDebugDumpDocument (out, doc); @@ -144,7 +150,7 @@ XMLTree::write_buffer(void) const XMLNodeList children; xmlKeepBlanksDefault(0); - doc = xmlNewDoc((xmlChar *) "1.0"); + doc = xmlNewDoc((xmlChar *) XML_VERSION); xmlSetDocCompressMode(doc, _compression); writenode(doc, _root, doc->children, 1); xmlDocDumpMemory(doc, (xmlChar **) & ptr, &len); @@ -279,6 +285,21 @@ XMLNode::add_child_copy(const XMLNode& n) return copy; } +XMLNodeList* +XMLNode::find(const string xpath) const +{ + xmlDocPtr doc = xmlNewDoc((xmlChar *) XML_VERSION); + writenode(doc, (XMLNode *) this, doc->children, 1); + xmlXPathContext* ctxt = xmlXPathNewContext(doc); + + XMLNodeList* result = find_impl(ctxt, xpath); + + xmlXPathFreeContext(ctxt); + xmlFreeDoc(doc); + + return result; +} + XMLNode * XMLNode::add_content(const string & c) { @@ -475,3 +496,43 @@ writenode(xmlDocPtr doc, XMLNode * n, xmlNodePtr p, int root = 0) writenode(doc, *curchild, node); } } + +static XMLNodeList* find_impl(xmlXPathContext* ctxt, const string xpath) +{ + xmlXPathObject* result = xmlXPathEval((const xmlChar*)xpath.c_str(), ctxt); + + if(!result) + { + xmlXPathFreeContext(ctxt); + xmlFreeDoc(ctxt->doc); + + throw XMLException("Invalid XPath: " + xpath); + } + + if(result->type != XPATH_NODESET) + { + xmlXPathFreeObject(result); + xmlXPathFreeContext(ctxt); + xmlFreeDoc(ctxt->doc); + + throw XMLException("Only nodeset result types are supported."); + } + + xmlNodeSet* nodeset = result->nodesetval; + XMLNodeList* nodes = new XMLNodeList(); + if( nodeset ) + { + for (int i = 0; i < nodeset->nodeNr; ++i) { + XMLNode* node = readnode(nodeset->nodeTab[i]); + nodes->push_back(node); + } + } + else + { + // return empty set + } + + xmlXPathFreeObject(result); + + return nodes; +} |