@@ -53,9 +53,8 @@ Tlist get_children_common(const xmlpp::ustring& name, xmlNode* child)
53
53
return children;
54
54
}
55
55
56
- // Common part of all overloaded xmlpp::Node::find() methods.
57
- template <typename Tvector>
58
- Tvector find_common (const xmlpp::ustring& xpath,
56
+ // A common part of all overloaded xmlpp::Node::find() and eval_xpath() methods.
57
+ xmlXPathObject* find_common1 (const xmlpp::ustring& xpath,
59
58
const xmlpp::Node::PrefixNsMap* namespaces, xmlNode* node)
60
59
{
61
60
auto ctxt = xmlXPathNewContext (node->doc );
@@ -72,22 +71,20 @@ Tvector find_common(const xmlpp::ustring& xpath,
72
71
}
73
72
74
73
auto result = xmlXPathEval ((const xmlChar*)xpath.c_str (), ctxt);
74
+ xmlXPathFreeContext (ctxt);
75
75
76
76
if (!result)
77
- {
78
- xmlXPathFreeContext (ctxt);
79
-
80
77
throw xmlpp::exception (" Invalid XPath: " + xpath);
81
- }
82
78
83
- if (result->type != XPATH_NODESET)
84
- {
85
- xmlXPathFreeObject (result);
86
- xmlXPathFreeContext (ctxt);
87
-
88
- throw xmlpp::internal_error (" Only nodeset result types are supported." );
89
- }
79
+ return result;
80
+ }
90
81
82
+ // A common part of all overloaded xmlpp::Node::find() and eval_xpath() methods.
83
+ // Tvector == NodeSet or const_NodeSet
84
+ // result->type == XPATH_NODESET
85
+ template <typename Tvector>
86
+ Tvector find_common2 (xmlXPathObject* result, const char * method_name)
87
+ {
91
88
auto nodeset = result->nodesetval ;
92
89
Tvector nodes;
93
90
if (nodeset && !xmlXPathNodeSetIsEmpty (nodeset))
@@ -99,15 +96,15 @@ Tvector find_common(const xmlpp::ustring& xpath,
99
96
auto cnode = xmlXPathNodeSetItem (nodeset, i);
100
97
if (!cnode)
101
98
{
102
- std::cerr << " Node::find (): The xmlNode was null." << std::endl;
99
+ std::cerr << " Node::" << method_name << " (): The xmlNode was null." << std::endl;
103
100
continue ;
104
101
}
105
102
106
103
if (cnode->type == XML_NAMESPACE_DECL)
107
104
{
108
- // In this case we would cast it to a xmlNs*,
109
- // but this C++ method only returns Nodes.
110
- std::cerr << " Node::find (): Ignoring an xmlNs object." << std::endl;
105
+ // In this case we would cast it to a xmlNs*,
106
+ // but this C++ method only returns Nodes.
107
+ std::cerr << " Node::" << method_name << " (): Ignoring an xmlNs object." << std::endl;
111
108
continue ;
112
109
}
113
110
@@ -122,11 +119,62 @@ Tvector find_common(const xmlpp::ustring& xpath,
122
119
}
123
120
124
121
xmlXPathFreeObject (result);
125
- xmlXPathFreeContext (ctxt);
126
122
127
123
return nodes;
128
124
}
129
125
126
+ // Common part of all overloaded xmlpp::Node::find() methods.
127
+ template <typename Tvector>
128
+ Tvector find_common (const xmlpp::ustring& xpath,
129
+ const xmlpp::Node::PrefixNsMap* namespaces, xmlNode* node)
130
+ {
131
+ auto result = find_common1 (xpath, namespaces, node);
132
+
133
+ if (result->type != XPATH_NODESET)
134
+ {
135
+ xmlXPathFreeObject (result);
136
+ throw xmlpp::internal_error (" Only nodeset result types are supported." );
137
+ }
138
+ return find_common2<Tvector>(result, " find" );
139
+ }
140
+
141
+ // Common part of all overloaded xmlpp::Node::eval_xpath() methods.
142
+ template <typename Tvector>
143
+ std::variant<Tvector, bool , double , xmlpp::ustring>
144
+ eval_xpath_common (const xmlpp::ustring& xpath,
145
+ const xmlpp::Node::PrefixNsMap* namespaces, xmlNode* node)
146
+ {
147
+ auto result = find_common1 (xpath, namespaces, node);
148
+
149
+ switch (result->type )
150
+ {
151
+ case XPATH_NODESET:
152
+ return find_common2<Tvector>(result, " eval_xpath" );
153
+
154
+ case XPATH_BOOLEAN:
155
+ {
156
+ auto val = static_cast <bool >(result->boolval );
157
+ xmlXPathFreeObject (result);
158
+ return val;
159
+ }
160
+ case XPATH_NUMBER:
161
+ {
162
+ double val = result->floatval ;
163
+ xmlXPathFreeObject (result);
164
+ return val;
165
+ }
166
+ case XPATH_STRING:
167
+ {
168
+ xmlpp::ustring val = reinterpret_cast <const char *>(result->stringval );
169
+ xmlXPathFreeObject (result);
170
+ return val;
171
+ }
172
+ default :
173
+ xmlXPathFreeObject (result);
174
+ throw xmlpp::internal_error (" Unsupported result type." );
175
+ }
176
+ }
177
+
130
178
// Common part of xmlpp::Node::eval_to_[boolean|number|string]
131
179
xmlXPathObject* eval_common (const xmlpp::ustring& xpath,
132
180
const xmlpp::Node::PrefixNsMap* namespaces,
@@ -145,7 +193,7 @@ xmlXPathObject* eval_common(const xmlpp::ustring& xpath,
145
193
reinterpret_cast <const xmlChar*>(ns_uri.c_str ()));
146
194
}
147
195
148
- auto xpath_value = xmlXPathEvalExpression (
196
+ auto xpath_value = xmlXPathEval (
149
197
reinterpret_cast <const xmlChar*>(xpath.c_str ()), ctxt);
150
198
151
199
xmlXPathFreeContext (ctxt);
@@ -412,6 +460,18 @@ Node::const_NodeSet Node::find(const ustring& xpath, const PrefixNsMap& namespac
412
460
return find_common<const_NodeSet>(xpath, &namespaces, impl_);
413
461
}
414
462
463
+ std::variant<Node::NodeSet, bool , double , ustring>
464
+ Node::eval_xpath (const ustring& xpath, const PrefixNsMap& namespaces)
465
+ {
466
+ return eval_xpath_common<NodeSet>(xpath, &namespaces, impl_);
467
+ }
468
+
469
+ std::variant<Node::const_NodeSet, bool , double , ustring>
470
+ Node::eval_xpath (const ustring& xpath, const PrefixNsMap& namespaces) const
471
+ {
472
+ return eval_xpath_common<const_NodeSet>(xpath, &namespaces, impl_);
473
+ }
474
+
415
475
bool Node::eval_to_boolean (const ustring& xpath, XPathResultType* result_type) const
416
476
{
417
477
return eval_common_to_boolean (xpath, nullptr , result_type, impl_);
0 commit comments