[libxml++] Node::find(): Propagate const qualifier to found nodes
- From: Kjell Ahlstedt <kjellahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libxml++] Node::find(): Propagate const qualifier to found nodes
- Date: Thu, 17 Sep 2015 09:19:18 +0000 (UTC)
commit f940edf2829d8d53284c42a35b8a46bf3a5a1e7f
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date: Thu Sep 17 10:26:32 2015 +0200
Node::find(): Propagate const qualifier to found nodes
* libxml++/nodes/node.[h|cc]: Add const_NodeSet. Add non-const versions of
find() and let the const versions return const_NodeSet.
* examples/dom_xpath/main.cc: Add some const. Bug #338907.
examples/dom_xpath/main.cc | 10 +--
libxml++/nodes/node.cc | 162 +++++++++++++++++++++++---------------------
libxml++/nodes/node.h | 22 ++++++-
3 files changed, 109 insertions(+), 85 deletions(-)
---
diff --git a/examples/dom_xpath/main.cc b/examples/dom_xpath/main.cc
index 96bf663..8000df8 100644
--- a/examples/dom_xpath/main.cc
+++ b/examples/dom_xpath/main.cc
@@ -1,5 +1,3 @@
-// -*- C++ -*-
-
/* main.cc
*
* Copyright (C) 2002 The libxml++ development team
@@ -59,19 +57,19 @@ bool xpath_test(const xmlpp::Node* node, const Glib::ustring& xpath)
{
std::cout << " " << child->get_path();
- auto attribute = dynamic_cast<xmlpp::Attribute*>(child);
+ auto attribute = dynamic_cast<const xmlpp::Attribute*>(child);
if (attribute)
std::cout << ", value=\"" << attribute->get_value() << "\"";
- auto content_node = dynamic_cast<xmlpp::ContentNode*>(child);
+ auto content_node = dynamic_cast<const xmlpp::ContentNode*>(child);
if (content_node)
std::cout << ", content=\"" << content_node->get_content() << "\"";
- auto entity_reference = dynamic_cast<xmlpp::EntityReference*>(child);
+ auto entity_reference = dynamic_cast<const xmlpp::EntityReference*>(child);
if (entity_reference)
std::cout << ", text=\"" << entity_reference->get_original_text() << "\"";
- auto element = dynamic_cast<xmlpp::Element*>(child);
+ auto element = dynamic_cast<const xmlpp::Element*>(child);
if (element)
{
auto text_node = element->get_child_text();
diff --git a/libxml++/nodes/node.cc b/libxml++/nodes/node.cc
index 5042a39..2b494ec 100644
--- a/libxml++/nodes/node.cc
+++ b/libxml++/nodes/node.cc
@@ -53,6 +53,81 @@ Tlist get_children_common(const Glib::ustring& name, xmlNode* child)
return children;
}
+// Common part of all overloaded xmlpp::Node::find() methods.
+template <typename Tvector>
+Tvector find_common(const Glib::ustring& xpath,
+ const xmlpp::Node::PrefixNsMap* namespaces, xmlNode* node)
+{
+ auto ctxt = xmlXPathNewContext(node->doc);
+ if (!ctxt)
+ throw xmlpp::internal_error("Could not create XPath context for " + xpath);
+ ctxt->node = node;
+
+ if (namespaces)
+ {
+ for (xmlpp::Node::PrefixNsMap::const_iterator it = namespaces->begin();
+ it != namespaces->end(); ++it)
+ xmlXPathRegisterNs(ctxt,
+ reinterpret_cast<const xmlChar*>(it->first.c_str()),
+ reinterpret_cast<const xmlChar*>(it->second.c_str()));
+ }
+
+ auto result = xmlXPathEval((const xmlChar*)xpath.c_str(), ctxt);
+
+ if (!result)
+ {
+ xmlXPathFreeContext(ctxt);
+
+ throw xmlpp::exception("Invalid XPath: " + xpath);
+ }
+
+ if (result->type != XPATH_NODESET)
+ {
+ xmlXPathFreeObject(result);
+ xmlXPathFreeContext(ctxt);
+
+ throw xmlpp::internal_error("Only nodeset result types are supported.");
+ }
+
+ auto nodeset = result->nodesetval;
+ Tvector nodes;
+ if (nodeset && !xmlXPathNodeSetIsEmpty(nodeset))
+ {
+ const int count = xmlXPathNodeSetGetLength(nodeset);
+ nodes.reserve(count);
+ for (int i = 0; i != count; ++i)
+ {
+ auto cnode = xmlXPathNodeSetItem(nodeset, i);
+ if (!cnode)
+ {
+ std::cerr << "Node::find(): The xmlNode was null." << std::endl;
+ continue;
+ }
+
+ if (cnode->type == XML_NAMESPACE_DECL)
+ {
+ //In this case we would cast it to a xmlNs*,
+ //but this C++ method only returns Nodes.
+ std::cerr << "Node::find(): Ignoring an xmlNs object." << std::endl;
+ continue;
+ }
+
+ //TODO: Check for other cnode->type values?
+
+ nodes.push_back(_convert_node(cnode));
+ }
+ }
+ else
+ {
+ // return empty set
+ }
+
+ xmlXPathFreeObject(result);
+ xmlXPathFreeContext(ctxt);
+
+ return nodes;
+}
+
// Common part of xmlpp::Node::eval_to_[boolean|number|string]
xmlXPathObject* eval_common(const Glib::ustring& xpath,
const xmlpp::Node::PrefixNsMap* namespaces,
@@ -451,91 +526,24 @@ Glib::ustring Node::get_path() const
return retn;
}
-static NodeSet find_impl(xmlXPathContext* ctxt, const Glib::ustring& xpath)
+NodeSet Node::find(const Glib::ustring& xpath)
{
- auto result = xmlXPathEval((const xmlChar*)xpath.c_str(), ctxt);
-
- if(!result)
- {
- xmlXPathFreeContext(ctxt);
-
- throw exception("Invalid XPath: " + xpath);
- }
-
- if(result->type != XPATH_NODESET)
- {
- xmlXPathFreeObject(result);
- xmlXPathFreeContext(ctxt);
-
- throw internal_error("Only nodeset result types are supported.");
- }
-
- auto nodeset = result->nodesetval;
- NodeSet nodes;
- if( nodeset && !xmlXPathNodeSetIsEmpty(nodeset))
- {
- const int count = xmlXPathNodeSetGetLength(nodeset);
- nodes.reserve(count);
- for (int i = 0; i != count; ++i)
- {
- auto cnode = xmlXPathNodeSetItem(nodeset, i);
- if(!cnode)
- {
- std::cerr << "Node::find_impl: The xmlNode was null." << std::endl;
- continue;
- }
-
- if(cnode->type == XML_NAMESPACE_DECL)
- {
- //In this case we would cast it to a xmlNs*,
- //but this C++ method only returns Nodes.
- std::cerr << "Node::find_impl: ignoring an xmlNs object." << std::endl;
- continue;
- }
-
- //TODO: Check for other cnode->type values?
-
- Node::create_wrapper(cnode);
- auto cppNode = static_cast<Node*>(cnode->_private);
- nodes.push_back(cppNode);
- }
- }
- else
- {
- // return empty set
- }
-
- xmlXPathFreeObject(result);
- xmlXPathFreeContext(ctxt);
-
- return nodes;
+ return find_common<NodeSet>(xpath, 0, impl_);
}
-NodeSet Node::find(const Glib::ustring& xpath) const
+const_NodeSet Node::find(const Glib::ustring& xpath) const
{
- auto ctxt = xmlXPathNewContext(impl_->doc);
- if (!ctxt)
- throw internal_error("Could not create XPath context for " + xpath);
- ctxt->node = impl_;
-
- return find_impl(ctxt, xpath);
+ return find_common<const_NodeSet>(xpath, 0, impl_);
}
-NodeSet Node::find(const Glib::ustring& xpath,
- const PrefixNsMap& namespaces) const
+NodeSet Node::find(const Glib::ustring& xpath, const PrefixNsMap& namespaces)
{
- auto ctxt = xmlXPathNewContext(impl_->doc);
- if (!ctxt)
- throw internal_error("Could not create XPath context for " + xpath);
- ctxt->node = impl_;
-
- for (PrefixNsMap::const_iterator it=namespaces.begin();
- it != namespaces.end(); it++)
- xmlXPathRegisterNs(ctxt,
- reinterpret_cast<const xmlChar*>(it->first.c_str()),
- reinterpret_cast<const xmlChar*>(it->second.c_str()));
+ return find_common<NodeSet>(xpath, &namespaces, impl_);
+}
- return find_impl(ctxt, xpath);
+const_NodeSet Node::find(const Glib::ustring& xpath, const PrefixNsMap& namespaces) const
+{
+ return find_common<const_NodeSet>(xpath, &namespaces, impl_);
}
bool Node::eval_to_boolean(const Glib::ustring& xpath, XPathResultType* result_type) const
diff --git a/libxml++/nodes/node.h b/libxml++/nodes/node.h
index 825a103..fe70152 100644
--- a/libxml++/nodes/node.h
+++ b/libxml++/nodes/node.h
@@ -29,6 +29,7 @@ class Attribute;
class Node;
typedef std::vector<Node*> NodeSet;
+typedef std::vector<const Node*> const_NodeSet;
// xmlpp::XPathResultType is similar to xmlXPathObjectType in libxml2.
/** An XPath expression is evaluated to yield a result, which
@@ -282,7 +283,15 @@ public:
* @throws xmlpp::exception If the XPath expression cannot be evaluated.
* @throws xmlpp::internal_error If the result type is not nodeset.
*/
- NodeSet find(const Glib::ustring& xpath) const;
+ NodeSet find(const Glib::ustring& xpath);
+
+ /** Find nodes from an XPath expression.
+ * @param xpath The XPath of the nodes.
+ * @returns The resulting const_NodeSet.
+ * @throws xmlpp::exception If the XPath expression cannot be evaluated.
+ * @throws xmlpp::internal_error If the result type is not nodeset.
+ */
+ const_NodeSet find(const Glib::ustring& xpath) const;
/** A map of namespace prefixes to namespace URIs.
*/
@@ -295,7 +304,16 @@ public:
* @throws xmlpp::exception If the XPath expression cannot be evaluated.
* @throws xmlpp::internal_error If the result type is not nodeset.
*/
- NodeSet find(const Glib::ustring& xpath, const PrefixNsMap& namespaces) const;
+ NodeSet find(const Glib::ustring& xpath, const PrefixNsMap& namespaces);
+
+ /** Find nodes from an XPath expression.
+ * @param xpath The XPath of the nodes.
+ * @param namespaces A map of namespace prefixes to namespace URIs to be used while finding.
+ * @returns The resulting const_NodeSet.
+ * @throws xmlpp::exception If the XPath expression cannot be evaluated.
+ * @throws xmlpp::internal_error If the result type is not nodeset.
+ */
+ const_NodeSet find(const Glib::ustring& xpath, const PrefixNsMap& namespaces) const;
/** Evaluate an XPath expression.
* @param xpath The XPath expression.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]