+
+static XMLSharedNodeList* 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;
+ XMLSharedNodeList* nodes = new XMLSharedNodeList();
+ if (nodeset) {
+ for (int i = 0; i < nodeset->nodeNr; ++i) {
+ XMLNode* node = readnode(nodeset->nodeTab[i]);
+ nodes->push_back(boost::shared_ptr<XMLNode>(node));
+ }
+ } else {
+ // return empty set
+ }
+
+ xmlXPathFreeObject(result);
+
+ return nodes;
+}
+
+/** Dump a node, its properties and children to a stream */
+void
+XMLNode::dump (ostream& s, string p) const
+{
+ if (_is_content) {
+ s << p << " " << content() << "\n";
+ } else {
+ s << p << "<" << _name;
+ for (XMLPropertyList::const_iterator i = _proplist.begin(); i != _proplist.end(); ++i) {
+ s << " " << (*i)->name() << "=\"" << (*i)->value() << "\"";
+ }
+ s << ">\n";
+
+ for (XMLNodeList::const_iterator i = _children.begin(); i != _children.end(); ++i) {
+ (*i)->dump (s, p + " ");
+ }
+
+ s << p << "</" << _name << ">\n";
+ }
+}