Mangiare Senza Glutine disponibile su App Store

Per altre informazioni scrivi a fabriziocaldarelli@negusweb.it

XPath con libxml++ su Linux

Da Programmazione Software.

Descrizione

In ambiente Linux, si può parserizzare un file xml tramite le libxml di Gnome (http://www.xmlsoft.org) oppure tramite libxml++ (http://libxmlplusplus.sourceforge.net/). Queste ultime richiedono un pò meno sforzo implementativo ma qualche chiamata a librerie esterne in più. Qui di seguito il codice di una classe che incapsula le libxml++ ed un codice di prova:

include/Xml/CXml.h

/*
 * CXml.h
 *
 *  Created on: 12-mar-2009
 *      Author: negus
 */
 
/**
 * Include DIRS
 * ---------------------------------
	-I/usr/include/libxml++-2.6
	-I/usr/lib/libxml++-2.6/include
	-I/usr/include/libxml2
	-I/usr/include/glibmm-2.4
	-I/usr/lib/glibmm-2.4/include
	-I/usr/include/sigc++-2.0
	-I/usr/lib/sigc++-2.0/include
	-I/usr/include/glib-2.0
	-I/usr/lib/glib-2.0/include
 * ---------------------------------
 */
 
/**
 * Against LIBS
 * ---------------------------------
	-lxml++-2.6
	-lxml2
	-lglibmm-2.4
	-lgobject-2.0
	-lsigc-2.0
	-lglib-2.0
 * ---------------------------------
 */
 
 
#ifndef CXML_H_
#define CXML_H_
 
#include <libxml++ libxml++.h="">
#include <iostream>
#include <string>
 
using namespace std;
 
class CXml {
public:			// Constructors / Destructors
	CXml(const string& iPathFileXml);
	virtual ~CXml();
 
public:
	xmlpp::Node* getRootNode();
 
private:
	int _ParseXml(const string& iPathFileXml,xmlpp::Node **oRootNode);
 
private:
	string pathFileXml;
	xmlpp::Node *rootNode;			// deleted from parser destructor
	xmlpp::DomParser *parser;
};
 
#endif /* CXML_H_ */



include/Xml/CXml.cpp

/*
 * CXml.cpp
 *
 *  Created on: 12-mar-2009
 *      Author: negus
 */
 
#include "Xml/CXml.h"
 
CXml::CXml(const string& iPathFileXml) {
 
	this->pathFileXml = iPathFileXml;
 
	this->_ParseXml(iPathFileXml,&this->rootNode);
 
}
 
CXml::~CXml() {
	delete parser;
}
 
int CXml::_ParseXml(const string& iPathFileXml,xmlpp::Node** oRootNode)
{
	*oRootNode = NULL;
 
	#ifdef LIBXMLCPP_EXCEPTIONS_ENABLED
	try
	{
		#endif //LIBXMLCPP_EXCEPTIONS_ENABLED
		parser = new xmlpp::DomParser(iPathFileXml);
		if(parser)
		{
			const xmlpp::Node* root = parser->get_document()->get_root_node(); //deleted by DomParser.
			*oRootNode = (xmlpp::Node*)root;
		}
		#ifdef LIBXMLCPP_EXCEPTIONS_ENABLED
	}
	catch(const std::exception& ex)
	{
		std::cout << "Exception caught: " << ex.what() << std::endl;
	}
	#endif //LIBXMLCPP_EXCEPTIONS_ENABLED
 
	return 0;
}
 
xmlpp::Node* CXml::getRootNode() { return this->rootNode; }



E ora un pezzo di codice per fare delle prove: main.cpp

/*
 * main.cpp
 *
 *  Created on: 12-mar-2009
 *      Author: negus
 */
 
#include "Xml/CXml.h"
 
void xpath_test(const xmlpp::Node* node, const Glib::ustring& xpath);
void print_indentation(unsigned int indentation);
void print_node(const xmlpp::Node* node, unsigned int indentation);
 
 
int main()
{
	CXml *xml = new CXml("/home/negus/prova.xml");
 
	#ifdef LIBXMLCPP_EXCEPTIONS_ENABLED
	try
	{
		#endif //LIBXMLCPP_EXCEPTIONS_ENABLED
		xmlpp::Node* root = xml->getRootNode();
		if(root)
		{
			// Find all sections, no matter where:
			xpath_test(root, "//livello1");
 
			// Find the title node (if there is one):
			//xpath_test(root, "title");
 
			std::cout << std::endl;
 
			// And finally test whether intra-document links are well-formed.
			// To be well-formed, the 'linkend' attribute must refer to
			// an element in terms of its 'id'.
			//
			// Find out whether there are linkend attributes that don't have
			// corresponding 'id's
			std::cout << "searching for unresolved internal references "
			<< "(see docbook manual):" << std::endl;
 
			//xpath_test(root, "//xref/@linkend");
		}
		#ifdef LIBXMLCPP_EXCEPTIONS_ENABLED
	}
	catch(const std::exception& ex)
	{
		std::cout << "Exception caught: " << ex.what() << std::endl;
	}
	#endif //LIBXMLCPP_EXCEPTIONS_ENABLED
 
	delete xml;
 
	return 0;
}
 
 
 
 
void xpath_test(const xmlpp::Node* node, const Glib::ustring& xpath)
{
  std::cout << std::endl; //Separate tests by an empty line.
  std::cout << "searching with xpath '" << xpath << "' in root node: " << std::endl;
 
  xmlpp::NodeSet set = node->find(xpath);
 
  //std::cout << set.size() << " nodes have been found:" << std::endl;
 
  //Print the structural paths:
  for(xmlpp::NodeSet::iterator i = set.begin(); i != set.end(); ++i)
  {
    //std::cout << " " << (*i)->get_path() << std::endl;
    //print_node(*i,0);
  }
}
 
 
void print_indentation(unsigned int indentation)
{
  for(unsigned int i = 0; i < indentation; ++i)
    std::cout << " ";
}
 
void print_node(const xmlpp::Node* node, unsigned int indentation)
{
  std::cout << std::endl; //Separate nodes by an empty line.
 
  const xmlpp::ContentNode* nodeContent = dynamic_cast<const xmlpp::contentnode*="">(node);
  const xmlpp::TextNode* nodeText = dynamic_cast<const xmlpp::textnode*="">(node);
  const xmlpp::CommentNode* nodeComment = dynamic_cast<const xmlpp::commentnode*="">(node);
 
  if(nodeText && nodeText->is_white_space()) //Let's ignore the indenting - you don't always want to do this.
    return;
 
  Glib::ustring nodename = node->get_name();
 
  if(!nodeText && !nodeComment && !nodename.empty()) //Let's not say "name: text".
  {
    print_indentation(indentation);
    std::cout << "Node name = " << node->get_name() << std::endl;
    std::cout << "Node name = " << nodename << std::endl;
  }
  else if(nodeText) //Let's say when it's text. - e.g. let's say what that white space is.
  {
    print_indentation(indentation);
    std::cout << "Text Node" << std::endl;
  }
 
  //Treat the various node types differently:
  if(nodeText)
  {
    print_indentation(indentation);
    std::cout << "text = \"" << nodeText->get_content() << "\"" << std::endl;
  }
  else if(nodeComment)
  {
    print_indentation(indentation);
    std::cout << "comment = " << nodeComment->get_content() << std::endl;
  }
  else if(nodeContent)
  {
    print_indentation(indentation);
    std::cout << "content = " << nodeContent->get_content() << std::endl;
  }
  else if(const xmlpp::Element* nodeElement = dynamic_cast<const xmlpp::element*="">(node))
  {
    //A normal Element node:
 
    //line() works only for ElementNodes.
    print_indentation(indentation);
    std::cout << "     line = " << node->get_line() << std::endl;
 
    //Print attributes:
    const xmlpp::Element::AttributeList& attributes = nodeElement->get_attributes();
    for(xmlpp::Element::AttributeList::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter)
    {
      const xmlpp::Attribute* attribute = *iter;
      print_indentation(indentation);
      std::cout << "  Attribute " << attribute->get_name() << " = " << attribute->get_value() << std::endl;
    }
 
    const xmlpp::Attribute* attribute = nodeElement->get_attribute("title");
    if(attribute)
    {
      std::cout << "title found: =" << attribute->get_value() << std::endl;
 
    }
  }
 
  if(!nodeContent)
  {
    //Recurse through child nodes:
    xmlpp::Node::NodeList list = node->get_children();
    for(xmlpp::Node::NodeList::iterator iter = list.begin(); iter != list.end(); ++iter)
    {
      print_node(*iter, indentation + 2); //recursive
    }
  }
}



Allegati

Il pacchetto completo per usare XPath (c++) su Linux