2010-05-14 01:05:28 +04:00
/* -------------------------------------------------------------------------- */
2015-09-23 16:03:22 +03:00
/* Copyright 2002-2015, OpenNebula Project, OpenNebula Systems */
2010-05-14 01:05:28 +04:00
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
# ifndef OBJECT_XML_H_
# define OBJECT_XML_H_
# include <string>
# include <vector>
2016-01-08 03:06:26 +03:00
# include <sstream>
2010-05-14 01:05:28 +04:00
# include <libxml/tree.h>
# include <libxml/parser.h>
# include <libxml/xpath.h>
# include <libxml/xpathInternals.h>
/**
* This class represents a generic Object supported by a xml document .
* The class provides basic methods to query attributes , and get xml nodes
*/
class ObjectXML
{
public :
// ---------------------- Constructors ------------------------------------
ObjectXML ( ) : xml ( 0 ) , ctx ( 0 ) { } ;
/**
* Constructs an object using a XML document
*/
2016-01-08 03:06:26 +03:00
ObjectXML ( const std : : string & xml_doc ) ;
2010-05-14 01:05:28 +04:00
/**
* Constructs an object using a XML Node . The node is copied to the new
* object
*/
ObjectXML ( const xmlNodePtr node ) ;
virtual ~ ObjectXML ( ) ;
/**
2016-01-08 03:06:26 +03:00
* Gets elements using Xpath expression .
2010-05-14 01:05:28 +04:00
* @ param xpath_expr the Xpath of the element
* @ return a vector with the elements
*/
2016-01-08 03:06:26 +03:00
void xpaths ( std : : vector < std : : string > & values , const char * xpath_expr ) ;
2010-05-14 01:05:28 +04:00
2016-01-08 03:06:26 +03:00
/* ---------------------------------------------------------------------- */
/* Gets elements, type wrappers. See __xpaths definition for full */
/* description of these methods. */
/* ---------------------------------------------------------------------- */
inline void xpaths ( std : : vector < int > & values , const char * xpath_expr )
{
__xpaths < int > ( values , xpath_expr ) ;
} ;
2011-02-25 15:54:39 +03:00
2016-01-08 03:06:26 +03:00
inline void xpaths ( std : : vector < float > & values , const char * xpath_expr )
{
__xpaths < float > ( values , xpath_expr ) ;
} ;
2011-02-25 15:54:39 +03:00
2014-10-30 19:21:27 +03:00
/**
* Gets and sets a xpath attribute , if the attribute is not found a default
* is used
* @ param value to set
* @ param xpath_expr of the xml element
* @ param def default value if the element is not found
*
* @ return - 1 if default was set
*/
2016-01-08 03:06:26 +03:00
int xpath ( std : : string & value , const char * xpath_expr , const char * def ) ;
2014-10-30 19:21:27 +03:00
2016-01-08 03:06:26 +03:00
/* ---------------------------------------------------------------------- */
/* Gets xpath attribute, type wrappers. See __xpath definition for full */
/* description of these methods. */
/* ---------------------------------------------------------------------- */
inline int xpath ( int & v , const char * x , const int & d )
{
return __xpath < int > ( v , x , d ) ;
}
2011-03-03 20:53:41 +03:00
2016-01-08 03:06:26 +03:00
inline int xpath ( float & v , const char * x , const float & d )
{
return __xpath < float > ( v , x , d ) ;
}
2012-12-04 16:35:45 +04:00
2016-01-08 03:06:26 +03:00
inline int xpath ( unsigned int & v , const char * x , const unsigned int & d )
{
return __xpath < unsigned int > ( v , x , d ) ;
}
2012-12-04 16:35:45 +04:00
2016-01-08 03:06:26 +03:00
inline int xpath ( long long & v , const char * x , const long long & d )
{
return __xpath < long long > ( v , x , d ) ;
}
inline int xpath ( unsigned long long & v , const char * x , const unsigned long long & d )
{
return __xpath < unsigned long long > ( v , x , d ) ;
}
inline int xpath ( time_t & v , const char * x , const time_t & d )
{
return __xpath < time_t > ( v , x , d ) ;
}
2011-02-25 17:23:46 +03:00
2011-02-25 16:17:41 +03:00
/**
* Gets the value of an element from an xml string
* @ param value the value of the element
* @ param xml the xml string
* @ param xpath the xpath of the target element
2013-08-06 19:25:21 +04:00
*
2011-02-25 16:17:41 +03:00
* @ return - 1 if the element was not found
*/
2016-01-08 03:06:26 +03:00
static int xpath_value ( std : : string & value , const char * xml , const char * xpath ) ;
2011-02-25 16:17:41 +03:00
2013-08-06 19:25:21 +04:00
/**
* Search the Object for a given attribute in a set of object specific
* routes .
* @ param name of the attribute
* @ param value of the attribute
*
* @ return - 1 if the element was not found
*/
2016-01-08 03:06:26 +03:00
virtual int search ( const char * name , std : : string & value ) ;
2013-08-06 19:25:21 +04:00
/**
* Search the Object for a given attribute in a set of object specific
* routes . integer version
*/
virtual int search ( const char * name , int & value ) ;
/**
* Search the Object for a given attribute in a set of object specific
* routes . float version
*/
virtual int search ( const char * name , float & value ) ;
2010-05-14 01:05:28 +04:00
/**
* Get xml nodes by Xpath
* @ param xpath_expr the Xpath for the elements
* @ param content nodes for the given Xpath expression . The nodes are
* returned as pointers to the object nodes .
* @ return the number of nodes found
*/
2016-01-08 03:06:26 +03:00
int get_nodes ( const char * xpath_expr , std : : vector < xmlNodePtr > & content ) ;
2010-05-14 01:05:28 +04:00
2013-01-22 17:14:56 +04:00
/**
* Adds a copy of the node as a child of the node in the xpath expression .
* The source node must be cleaned by the caller .
*
* @ param xpath_expr Path of the parent node
* @ param node Node copy and add
* @ param new_name New name for the node copy
*
* @ return 0 on success , - 1 otherwise
*/
int add_node ( const char * xpath_expr , xmlNodePtr node , const char * new_name ) ;
2010-05-14 01:05:28 +04:00
/**
2011-07-03 03:57:39 +04:00
* Frees a vector of XMLNodes , as returned by the get_nodes function
* @ param content the vector of xmlNodePtr
*/
2016-01-08 03:06:26 +03:00
void free_nodes ( std : : vector < xmlNodePtr > & content )
2011-07-03 03:57:39 +04:00
{
2016-01-08 03:06:26 +03:00
std : : vector < xmlNodePtr > : : iterator it ;
2011-07-03 03:57:39 +04:00
for ( it = content . begin ( ) ; it < content . end ( ) ; it + + )
{
xmlFreeNode ( * it ) ;
}
} ;
/**
2010-05-14 01:05:28 +04:00
* Updates the object representation with a new XML document . Previous
* XML resources are freed
* @ param xml_doc the new xml document
*/
2016-01-08 03:06:26 +03:00
int update_from_str ( const std : : string & xml_doc ) ;
2010-05-14 01:05:28 +04:00
/**
* Updates the object representation with a new XML document . Previous
* XML resources are freed
* @ param xml_doc the new xml document
*/
2011-02-24 20:12:26 +03:00
int update_from_node ( const xmlNodePtr node ) ;
2010-05-14 01:05:28 +04:00
2011-12-19 20:07:32 +04:00
/**
* Validates the xml string
*
* @ param xml_doc string to parse
* @ return 0 if the xml validates
*/
2016-01-08 03:06:26 +03:00
static int validate_xml ( const std : : string & xml_doc ) ;
2011-12-19 20:07:32 +04:00
2013-01-30 20:49:24 +04:00
/**
* Renames the nodes given in the xpath expression
* @ param xpath_expr xpath expression to find the nodes to rename
* @ param new_name new name for the xml elements
*
* @ return the number of nodes renamed
*/
int rename_nodes ( const char * xpath_expr , const char * new_name ) ;
2010-05-14 05:32:42 +04:00
// ---------------------------------------------------------
// Lex & bison parser for requirements and rank expressions
// ---------------------------------------------------------
/**
* Evaluates a requirement expression on the given host .
* @ param requirements string
* @ param result true if the host matches the requirements
* @ param errmsg string describing the error , must be freed by the
* calling function
* @ return 0 on success
*/
2016-01-08 03:06:26 +03:00
int eval_bool ( const std : : string & expr , bool & result , char * * errmsg ) ;
2010-05-14 05:32:42 +04:00
/**
* Evaluates a rank expression on the given host .
* @ param rank string
* @ param result of the rank evaluation
* @ param errmsg string describing the error , must be freed by the
* calling function
* @ return 0 on success
*/
2016-01-08 03:06:26 +03:00
int eval_arith ( const std : : string & expr , int & result , char * * errmsg ) ;
2010-05-14 05:32:42 +04:00
2010-05-14 21:15:20 +04:00
/**
* Function to write the Object in an output stream
*/
2016-01-08 03:06:26 +03:00
friend std : : ostream & operator < < ( std : : ostream & os , ObjectXML & oxml )
2010-05-14 21:15:20 +04:00
{
xmlChar * mem ;
int size ;
xmlDocDumpMemory ( oxml . xml , & mem , & size ) ;
2016-01-08 03:06:26 +03:00
std : : string str ( reinterpret_cast < char * > ( mem ) ) ;
2010-05-14 21:15:20 +04:00
os < < str ;
xmlFree ( mem ) ;
return os ;
} ;
2013-08-06 19:25:21 +04:00
protected :
/**
* Array of paths to look for attributes in search methods
*/
const char * * paths ;
/**
* Number of elements in paths array
*/
int num_paths ;
2010-05-14 01:05:28 +04:00
private :
/**
* XML representation of the Object
*/
xmlDocPtr xml ;
/**
* XPath Context to access Object elements
*/
xmlXPathContextPtr ctx ;
/**
* Parse a XML documents and initializes XPath contexts
*/
2016-01-08 03:06:26 +03:00
void xml_parse ( const std : : string & xml_doc ) ;
2013-08-06 19:25:21 +04:00
/**
* Search the Object for a given attribute in a set of object specific
* routes .
* @ param name of the attribute
* @ results vector of attributes that matches the query
*/
2016-01-08 03:06:26 +03:00
void search ( const char * name , std : : vector < std : : string > & results ) ;
/**
* Gets a xpath attribute , if the attribute is not found a default is used .
* This function only returns the first element
* @ param value of the element
* @ param xpath_expr of the xml element
* @ param def default value if the element is not found
*
* @ return - 1 if default was set
*/
template < typename T >
int __xpath ( T & value , const char * xpath_expr , const T & def )
{
std : : vector < std : : string > values ;
xpaths ( values , xpath_expr ) ;
if ( values . empty ( ) = = true )
{
value = def ;
return - 1 ;
}
std : : istringstream iss ( values [ 0 ] ) ;
iss > > std : : dec > > value ;
if ( iss . fail ( ) = = true )
{
value = def ;
return - 1 ;
}
return 0 ;
}
/**
* Gets elements by xpath .
* @ param values vector with the element values .
* @ param expr of the xml element
*/
template < typename T >
void __xpaths ( std : : vector < T > & values , const char * expr )
{
xmlXPathObjectPtr obj ;
xmlNodePtr cur ;
xmlChar * str_ptr ;
obj = xmlXPathEvalExpression ( reinterpret_cast < const xmlChar * > ( expr ) , ctx ) ;
if ( obj = = 0 )
{
return ;
}
switch ( obj - > type )
{
case XPATH_NUMBER :
values . push_back ( static_cast < T > ( obj - > floatval ) ) ;
break ;
case XPATH_NODESET :
for ( int i = 0 ; i < obj - > nodesetval - > nodeNr ; + + i )
{
cur = obj - > nodesetval - > nodeTab [ i ] ;
if ( cur = = 0 | | cur - > type ! = XML_ELEMENT_NODE )
{
continue ;
}
str_ptr = xmlNodeGetContent ( cur ) ;
if ( str_ptr ! = 0 )
{
std : : istringstream iss ( reinterpret_cast < char * > ( str_ptr ) ) ;
T val ;
iss > > std : : dec > > val ;
if ( ! iss . fail ( ) )
{
values . push_back ( val ) ;
}
xmlFree ( str_ptr ) ;
}
}
break ;
default :
break ;
}
xmlXPathFreeObject ( obj ) ;
} ;
2010-05-14 01:05:28 +04:00
} ;
# endif /*OBJECT_XML_H_*/