How to retrieve node and attribute values from xml file in C++ using libxml2 by using xpath ?
Thanks in advance, Bhargava
Since this is tagged C++ I'll assume you can use the libxml++ library bindings.
I wrote a simple program that:
DomParserfind() on the document root node to get to the attribute.Attribute nodeget_value()Here's the code:
#include <iostream>
#include <libxml++/libxml++.h>
using namespace std;
using namespace Glib;
using namespace xmlpp;
int main(int argc, char* argv[])
{
// Parse the file
DomParser parser;
parser.parse_file("file.xml");
Node* rootNode = parser.get_document()->get_root_node();
// Xpath query
NodeSet result = rootNode->find("/root/a/b/@attr");
// Get first node from result
Node *firstNodeInResult = result.at(0);
// Cast to Attribute node (dynamic_cast on reference can throw [fail fast])
Attribute &attribute = dynamic_cast<Attribute&>(*firstNodeInResult);
// Get value of the attribute
ustring attributeValue = attribute.get_value();
// Print attribute value
cout << attributeValue << endl;
}
Given this input:
<!-- file.xml -->
<root>
<a>
<b attr="I want to get this"> </b>
</a>
</root>
The code will output:
I want to get this
To compile this on an Unix system:
c++ `pkg-config libxml++-2.6 --cflags` `pkg-config libxml++-2.6 --libs` file.cpp
undefined reference when I tried to compile. Compiling like this fixed the issue for me (sorry the stupid lowercase tilde in stack overflow is screwing up the formatting...) <command start>c++ file.cpp pkg-config libxml++-2.6 --cflags pkg-config libxml++-2.6 --libs<command end>terminate called after throwing an instance of 'std::bad_cast'sp1.xml:
<users noofids="1">
<user user="vin" password="abc"/>
</users>
Program:
#include <libxml/xpath.h>
#include <libxml/tree.h>
#include <iostream>
using namespace std;
int
main (int argc, char **argv)
{
char ID[25];
xmlInitParser ();
//LIBXML_TEST_VERSION
xmlDoc *doc = xmlParseFile ("sp1.xml");
xmlXPathContext *xpathCtx = xmlXPathNewContext (doc);
xmlXPathObject *xpathObj =
xmlXPathEvalExpression ((xmlChar *) "users/user", xpathCtx);
xmlNode *node = xpathObj->nodesetval->nodeTab[0];
xmlAttr *attr = node->properties;
while (attr)
{
//if(!xmlStrcmp(attr->name,(const xmlChar *)"noofids"))
//sprintf(ID,"%s",attr->children->content);
std::cout << "Attribute name: " << attr->name << " value: " << attr->
children->content << std::endl;
attr = attr->next;
}
//std::cout<<"ID: "<<ID<<endl;
return 0;
}
i got output by trying by my own
This is an example of how to get the value for the xpath you are trying to evaluate with libxml++.
Based on Alexandre Jasmin's answer but his only shows how to print an xpath attribute and it's not trivial to figure out how to print the Node's value because you have to cast it to a specific object (also his answer throws an exception).
#include <iostream>
#include <libxml++/libxml++.h>
using namespace std;
using namespace Glib;
using namespace xmlpp;
int main(int argc, char* argv[])
{
// Parse the file
DomParser parser;
parser.parse_file("sample.xml");
Node* root = parser.get_document()->get_root_node();
// Xpath query
NodeSet result = root->find("/root/ApplicationSettings/level_three");
// Get first element from result
Element *first_element = (Element *)result.at(0);
// Print the content of the Element
cout << first_element->get_child_text()->get_content() << endl;
}
sample.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<root>
<ApplicationSettings>
<level_three>hello world</level_three>
</ApplicationSettings>
</root>
compile
g++ test.cpp -o test `pkg-config libxml++-2.6 --cflags` `pkg-config libxml++-2.6 --libs`
run
./test