@@ -53,9 +53,8 @@ Tlist get_children_common(const Glib::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 Glib::ustring& xpath,
56
+ // A common part of all overloaded xmlpp::Node::find() and eval_xpath() methods.
57
+ xmlXPathObject* find_common1 (const Glib::ustring& xpath,
59
58
const xmlpp::Node::PrefixNsMap* namespaces, xmlNode* node)
60
59
{
61
60
auto ctxt = xmlXPathNewContext (node->doc );
@@ -65,30 +64,27 @@ Tvector find_common(const Glib::ustring& xpath,
65
64
66
65
if (namespaces)
67
66
{
68
- for (xmlpp::Node::PrefixNsMap::const_iterator it = namespaces->begin ();
69
- it != namespaces->end (); ++it)
67
+ for (const auto & [prefix, ns_uri] : *namespaces)
70
68
xmlXPathRegisterNs (ctxt,
71
- reinterpret_cast <const xmlChar*>(it-> first .c_str ()),
72
- reinterpret_cast <const xmlChar*>(it-> second .c_str ()));
69
+ reinterpret_cast <const xmlChar*>(prefix .c_str ()),
70
+ reinterpret_cast <const xmlChar*>(ns_uri .c_str ()));
73
71
}
74
72
75
73
auto result = xmlXPathEval ((const xmlChar*)xpath.c_str (), ctxt);
74
+ xmlXPathFreeContext (ctxt);
76
75
77
76
if (!result)
78
- {
79
- xmlXPathFreeContext (ctxt);
80
-
81
77
throw xmlpp::exception (" Invalid XPath: " + xpath);
82
- }
83
78
84
- if (result->type != XPATH_NODESET)
85
- {
86
- xmlXPathFreeObject (result);
87
- xmlXPathFreeContext (ctxt);
88
-
89
- throw xmlpp::internal_error (" Only nodeset result types are supported." );
90
- }
79
+ return result;
80
+ }
91
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
+ {
92
88
auto nodeset = result->nodesetval ;
93
89
Tvector nodes;
94
90
if (nodeset && !xmlXPathNodeSetIsEmpty (nodeset))
@@ -100,15 +96,15 @@ Tvector find_common(const Glib::ustring& xpath,
100
96
auto cnode = xmlXPathNodeSetItem (nodeset, i);
101
97
if (!cnode)
102
98
{
103
- std::cerr << " Node::find (): The xmlNode was null." << std::endl;
99
+ std::cerr << " Node::" << method_name << " (): The xmlNode was null." << std::endl;
104
100
continue ;
105
101
}
106
102
107
103
if (cnode->type == XML_NAMESPACE_DECL)
108
104
{
109
- // In this case we would cast it to a xmlNs*,
110
- // but this C++ method only returns Nodes.
111
- 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;
112
108
continue ;
113
109
}
114
110
@@ -123,11 +119,62 @@ Tvector find_common(const Glib::ustring& xpath,
123
119
}
124
120
125
121
xmlXPathFreeObject (result);
126
- xmlXPathFreeContext (ctxt);
127
122
128
123
return nodes;
129
124
}
130
125
126
+ // Common part of all overloaded xmlpp::Node::find() methods.
127
+ template <typename Tvector>
128
+ Tvector find_common (const Glib::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 , Glib::ustring>
144
+ eval_xpath_common (const Glib::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
+ Glib::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
+
131
178
// Common part of xmlpp::Node::eval_to_[boolean|number|string]
132
179
xmlXPathObject* eval_common (const Glib::ustring& xpath,
133
180
const xmlpp::Node::PrefixNsMap* namespaces,
@@ -140,14 +187,13 @@ xmlXPathObject* eval_common(const Glib::ustring& xpath,
140
187
141
188
if (namespaces)
142
189
{
143
- for (xmlpp::Node::PrefixNsMap::const_iterator it = namespaces->begin ();
144
- it != namespaces->end (); ++it)
190
+ for (const auto & [prefix, ns_uri] : *namespaces)
145
191
xmlXPathRegisterNs (ctxt,
146
- reinterpret_cast <const xmlChar*>(it-> first .c_str ()),
147
- reinterpret_cast <const xmlChar*>(it-> second .c_str ()));
192
+ reinterpret_cast <const xmlChar*>(prefix .c_str ()),
193
+ reinterpret_cast <const xmlChar*>(ns_uri .c_str ()));
148
194
}
149
195
150
- auto xpath_value = xmlXPathEvalExpression (
196
+ auto xpath_value = xmlXPathEval (
151
197
reinterpret_cast <const xmlChar*>(xpath.c_str ()), ctxt);
152
198
153
199
xmlXPathFreeContext (ctxt);
@@ -414,6 +460,18 @@ Node::const_NodeSet Node::find(const Glib::ustring& xpath, const PrefixNsMap& na
414
460
return find_common<const_NodeSet>(xpath, &namespaces, impl_);
415
461
}
416
462
463
+ std::variant<Node::NodeSet, bool , double , Glib::ustring>
464
+ Node::eval_xpath (const Glib::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 , Glib::ustring>
470
+ Node::eval_xpath (const Glib::ustring& xpath, const PrefixNsMap& namespaces) const
471
+ {
472
+ return eval_xpath_common<const_NodeSet>(xpath, &namespaces, impl_);
473
+ }
474
+
417
475
bool Node::eval_to_boolean (const Glib::ustring& xpath, XPathResultType* result_type) const
418
476
{
419
477
return eval_common_to_boolean (xpath, nullptr , result_type, impl_);
0 commit comments