/* $Id: XMLtools.cxx 15892 2013-04-03 08:49:18Z sloot $ $URL: https://ilk.uvt.nl/svn/sources/libticcutils/trunk/src/XMLtools.cxx $ Copyright (c) 1998 - 2013 ILK - Tilburg University CLiPS - University of Antwerp This file is part of ticcutils timbl is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. timbl is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . For questions and suggestions, see: http://ilk.uvt.nl/software.html or send mail to: timbl@uvt.nl */ #include #include #include #include "libxml/xpath.h" #include "ticcutils/XMLtools.h" using namespace std; namespace TiCC { XmlDoc::XmlDoc( const std::string& elem ){ the_doc = xmlNewDoc( (const xmlChar*)"""1.0""" ); MakeRoot( elem ); } const string XmlDoc::toString() const { xmlChar *buf; int size; xmlDocDumpMemory( the_doc, &buf, &size ); const string result = string( (const char *)buf, size ); xmlFree( buf ); return result; } xmlNode *XmlDoc::getRoot() const { if ( the_doc ) return xmlDocGetRootElement(the_doc); else return 0; } void XmlDoc::setRoot( xmlNode *node ){ if ( the_doc ) xmlDocSetRootElement(the_doc, node ); } xmlNode *XmlDoc::MakeRoot( const string& elem ){ xmlNode *root; root = xmlNewDocNode( the_doc, 0, (const xmlChar*)elem.c_str(), 0 ); xmlDocSetRootElement( the_doc, root ); return root; } string getNS( const xmlNode *node, string& prefix ){ string result; prefix = ""; xmlNs *p = node->ns; if ( p ){ if ( p->prefix ){ prefix = (char *)p->prefix; } result = (char *)p->href; } return result; } map getNSvalues( const xmlNode *node ){ map result; xmlNs *p = node->ns; while ( p ){ string pre; string val; if ( p->prefix ){ pre = (char *)p->prefix; } val = (char *)p->href; result[pre] = val; p = p->next; } return result; } list FindLocal( xmlXPathContext* ctxt, const string& xpath ){ list nodes; xmlXPathObject* result = xmlXPathEval((xmlChar*)xpath.c_str(), ctxt); if ( result ){ if (result->type != XPATH_NODESET) { xmlXPathFreeObject(result); throw runtime_error( "sorry, only nodeset types supported for now." ); return nodes; } xmlNodeSet* nodeset = result->nodesetval; if ( nodeset ){ for (int i = 0; i != nodeset->nodeNr; ++i) nodes.push_back(nodeset->nodeTab[i]); } else { throw runtime_error( "FindLocal: Missing nodeset" ); } xmlXPathFreeObject(result); } else { throw runtime_error( "Invalid Xpath: '" + xpath + "'" ); } return nodes; } list FindNodes( xmlNode* node, const string& xpath ){ xmlXPathContext* ctxt = xmlXPathNewContext( node->doc ); ctxt->node = node; ctxt->namespaces = xmlGetNsList( node->doc, ctxt->node ); ctxt->nsNr = 0; if (ctxt->namespaces != 0 ) { while (ctxt->namespaces[ctxt->nsNr] != 0 ){ ctxt->nsNr++; } } list nodes = FindLocal( ctxt, xpath ); if (ctxt->namespaces != NULL) xmlFree(ctxt->namespaces); xmlXPathFreeContext(ctxt); return nodes; } xmlNode *xPath( xmlNode *node, const string& xpath ){ // try to find a path, but it may not be there... // if there are more, just return the first list srch = FindNodes( node, xpath ); xmlNode *result = 0; if ( srch.size() != 0 ){ result = srch.front(); } return result; } string serialize( const xmlNode& node ){ // serialize to a string (XML fragment) xmlBuffer *buf = xmlBufferCreate(); xmlNodeDump( buf, 0, const_cast(&node), 0, 0 ); string result = (const char*)xmlBufferContent( buf ); xmlBufferFree( buf ); return result; } }