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

  1. /*
  2.  * CXml.h
  3.  *
  4.  *  Created on: 12-mar-2009
  5.  *      Author: negus
  6.  */
  7.  
  8. /**
  9.  * Include DIRS
  10.  * ---------------------------------
  11. 	-I/usr/include/libxml++-2.6
  12. 	-I/usr/lib/libxml++-2.6/include
  13. 	-I/usr/include/libxml2
  14. 	-I/usr/include/glibmm-2.4
  15. 	-I/usr/lib/glibmm-2.4/include
  16. 	-I/usr/include/sigc++-2.0
  17. 	-I/usr/lib/sigc++-2.0/include
  18. 	-I/usr/include/glib-2.0
  19. 	-I/usr/lib/glib-2.0/include
  20.  * ---------------------------------
  21.  */
  22.  
  23. /**
  24.  * Against LIBS
  25.  * ---------------------------------
  26. 	-lxml++-2.6
  27. 	-lxml2
  28. 	-lglibmm-2.4
  29. 	-lgobject-2.0
  30. 	-lsigc-2.0
  31. 	-lglib-2.0
  32.  * ---------------------------------
  33.  */
  34.  
  35.  
  36. #ifndef CXML_H_
  37. #define CXML_H_
  38.  
  39. #include <libxml++ libxml++.h="">
  40. #include <iostream>
  41. #include <string>
  42.  
  43. using namespace std;
  44.  
  45. class CXml {
  46. public:			// Constructors / Destructors
  47. 	CXml(const string& iPathFileXml);
  48. 	virtual ~CXml();
  49.  
  50. public:
  51. 	xmlpp::Node* getRootNode();
  52.  
  53. private:
  54. 	int _ParseXml(const string& iPathFileXml,xmlpp::Node **oRootNode);
  55.  
  56. private:
  57. 	string pathFileXml;
  58. 	xmlpp::Node *rootNode;			// deleted from parser destructor
  59. 	xmlpp::DomParser *parser;
  60. };
  61.  
  62. #endif /* CXML_H_ */



include/Xml/CXml.cpp

  1. /*
  2.  * CXml.cpp
  3.  *
  4.  *  Created on: 12-mar-2009
  5.  *      Author: negus
  6.  */
  7.  
  8. #include "Xml/CXml.h"
  9.  
  10. CXml::CXml(const string& iPathFileXml) {
  11.  
  12. 	this->pathFileXml = iPathFileXml;
  13.  
  14. 	this->_ParseXml(iPathFileXml,&this->rootNode);
  15.  
  16. }
  17.  
  18. CXml::~CXml() {
  19. 	delete parser;
  20. }
  21.  
  22. int CXml::_ParseXml(const string& iPathFileXml,xmlpp::Node** oRootNode)
  23. {
  24. 	*oRootNode = NULL;
  25.  
  26. 	#ifdef LIBXMLCPP_EXCEPTIONS_ENABLED
  27. 	try
  28. 	{
  29. 		#endif //LIBXMLCPP_EXCEPTIONS_ENABLED
  30. 		parser = new xmlpp::DomParser(iPathFileXml);
  31. 		if(parser)
  32. 		{
  33. 			const xmlpp::Node* root = parser->get_document()->get_root_node(); //deleted by DomParser.
  34. 			*oRootNode = (xmlpp::Node*)root;
  35. 		}
  36. 		#ifdef LIBXMLCPP_EXCEPTIONS_ENABLED
  37. 	}
  38. 	catch(const std::exception& ex)
  39. 	{
  40. 		std::cout << "Exception caught: " << ex.what() << std::endl;
  41. 	}
  42. 	#endif //LIBXMLCPP_EXCEPTIONS_ENABLED
  43.  
  44. 	return 0;
  45. }
  46.  
  47. xmlpp::Node* CXml::getRootNode() { return this->rootNode; }



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

  1. /*
  2.  * main.cpp
  3.  *
  4.  *  Created on: 12-mar-2009
  5.  *      Author: negus
  6.  */
  7.  
  8. #include "Xml/CXml.h"
  9.  
  10. void xpath_test(const xmlpp::Node* node, const Glib::ustring& xpath);
  11. void print_indentation(unsigned int indentation);
  12. void print_node(const xmlpp::Node* node, unsigned int indentation);
  13.  
  14.  
  15. int main()
  16. {
  17. 	CXml *xml = new CXml("/home/negus/prova.xml");
  18.  
  19. 	#ifdef LIBXMLCPP_EXCEPTIONS_ENABLED
  20. 	try
  21. 	{
  22. 		#endif //LIBXMLCPP_EXCEPTIONS_ENABLED
  23. 		xmlpp::Node* root = xml->getRootNode();
  24. 		if(root)
  25. 		{
  26. 			// Find all sections, no matter where:
  27. 			xpath_test(root, "//livello1");
  28.  
  29. 			// Find the title node (if there is one):
  30. 			//xpath_test(root, "title");
  31.  
  32. 			std::cout << std::endl;
  33.  
  34. 			// And finally test whether intra-document links are well-formed.
  35. 			// To be well-formed, the 'linkend' attribute must refer to
  36. 			// an element in terms of its 'id'.
  37. 			//
  38. 			// Find out whether there are linkend attributes that don't have
  39. 			// corresponding 'id's
  40. 			std::cout << "searching for unresolved internal references "
  41. 			<< "(see docbook manual):" << std::endl;
  42.  
  43. 			//xpath_test(root, "//xref/@linkend");
  44. 		}
  45. 		#ifdef LIBXMLCPP_EXCEPTIONS_ENABLED
  46. 	}
  47. 	catch(const std::exception& ex)
  48. 	{
  49. 		std::cout << "Exception caught: " << ex.what() << std::endl;
  50. 	}
  51. 	#endif //LIBXMLCPP_EXCEPTIONS_ENABLED
  52.  
  53. 	delete xml;
  54.  
  55. 	return 0;
  56. }
  57.  
  58.  
  59.  
  60.  
  61. void xpath_test(const xmlpp::Node* node, const Glib::ustring& xpath)
  62. {
  63.   std::cout << std::endl; //Separate tests by an empty line.
  64.   std::cout << "searching with xpath '" << xpath << "' in root node: " << std::endl;
  65.  
  66.   xmlpp::NodeSet set = node->find(xpath);
  67.  
  68.   //std::cout << set.size() << " nodes have been found:" << std::endl;
  69.  
  70.   //Print the structural paths:
  71.   for(xmlpp::NodeSet::iterator i = set.begin(); i != set.end(); ++i)
  72.   {
  73.     //std::cout << " " << (*i)->get_path() << std::endl;
  74.     //print_node(*i,0);
  75.   }
  76. }
  77.  
  78.  
  79. void print_indentation(unsigned int indentation)
  80. {
  81.   for(unsigned int i = 0; i < indentation; ++i)
  82.     std::cout << " ";
  83. }
  84.  
  85. void print_node(const xmlpp::Node* node, unsigned int indentation)
  86. {
  87.   std::cout << std::endl; //Separate nodes by an empty line.
  88.  
  89.   const xmlpp::ContentNode* nodeContent = dynamic_cast<const xmlpp::contentnode*="">(node);
  90.   const xmlpp::TextNode* nodeText = dynamic_cast<const xmlpp::textnode*="">(node);
  91.   const xmlpp::CommentNode* nodeComment = dynamic_cast<const xmlpp::commentnode*="">(node);
  92.  
  93.   if(nodeText && nodeText->is_white_space()) //Let's ignore the indenting - you don't always want to do this.
  94.     return;
  95.  
  96.   Glib::ustring nodename = node->get_name();
  97.  
  98.   if(!nodeText && !nodeComment && !nodename.empty()) //Let's not say "name: text".
  99.   {
  100.     print_indentation(indentation);
  101.     std::cout << "Node name = " << node->get_name() << std::endl;
  102.     std::cout << "Node name = " << nodename << std::endl;
  103.   }
  104.   else if(nodeText) //Let's say when it's text. - e.g. let's say what that white space is.
  105.   {
  106.     print_indentation(indentation);
  107.     std::cout << "Text Node" << std::endl;
  108.   }
  109.  
  110.   //Treat the various node types differently:
  111.   if(nodeText)
  112.   {
  113.     print_indentation(indentation);
  114.     std::cout << "text = \"" << nodeText->get_content() << "\"" << std::endl;
  115.   }
  116.   else if(nodeComment)
  117.   {
  118.     print_indentation(indentation);
  119.     std::cout << "comment = " << nodeComment->get_content() << std::endl;
  120.   }
  121.   else if(nodeContent)
  122.   {
  123.     print_indentation(indentation);
  124.     std::cout << "content = " << nodeContent->get_content() << std::endl;
  125.   }
  126.   else if(const xmlpp::Element* nodeElement = dynamic_cast<const xmlpp::element*="">(node))
  127.   {
  128.     //A normal Element node:
  129.  
  130.     //line() works only for ElementNodes.
  131.     print_indentation(indentation);
  132.     std::cout << "     line = " << node->get_line() << std::endl;
  133.  
  134.     //Print attributes:
  135.     const xmlpp::Element::AttributeList& attributes = nodeElement->get_attributes();
  136.     for(xmlpp::Element::AttributeList::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter)
  137.     {
  138.       const xmlpp::Attribute* attribute = *iter;
  139.       print_indentation(indentation);
  140.       std::cout << "  Attribute " << attribute->get_name() << " = " << attribute->get_value() << std::endl;
  141.     }
  142.  
  143.     const xmlpp::Attribute* attribute = nodeElement->get_attribute("title");
  144.     if(attribute)
  145.     {
  146.       std::cout << "title found: =" << attribute->get_value() << std::endl;
  147.  
  148.     }
  149.   }
  150.  
  151.   if(!nodeContent)
  152.   {
  153.     //Recurse through child nodes:
  154.     xmlpp::Node::NodeList list = node->get_children();
  155.     for(xmlpp::Node::NodeList::iterator iter = list.begin(); iter != list.end(); ++iter)
  156.     {
  157.       print_node(*iter, indentation + 2); //recursive
  158.     }
  159.   }
  160. }



Allegati

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

Strumenti personali
hobby
approfondimenti