32 #ifndef QUERY_XPATH_HPP_ 33 #define QUERY_XPATH_HPP_ 35 #include "../Helper/Strings.hpp" 36 #include "../Main/Exception.hpp" 37 #include "../Parsing/XML.hpp" 39 #include <pugixml.hpp> 44 #include <string_view> 57 inline constexpr std::string_view
cDataHead{
"<![CDATA["};
79 XPath(
const std::string& xpath,
bool textOnly);
107 pugi::xpath_query query;
112 [[nodiscard]]
static std::string nodeToString(
const pugi::xpath_node& node,
bool textOnly);
115 class TextOnlyWalker :
public pugi::xml_tree_walker {
117 bool for_each(pugi::xml_node& node)
override;
118 [[nodiscard]] std::string getResult()
const;
140 inline XPath::XPath(
const std::string& xpath,
bool textOnly) : compiled(false), isTextOnly(false) {
143 this->query = pugi::xpath_query(xpath.c_str());
144 this->compiled =
true;
146 catch(
const pugi::xpath_exception& e) {
151 this->isTextOnly = textOnly;
170 if(!(this->compiled)) {
180 return this->query.evaluate_boolean(*(doc.doc));
182 catch(
const std::exception& e) {
207 if(!(this->compiled)) {
217 if(this->query.return_type() == pugi::xpath_type_node_set) {
218 const auto nodeSet{this->query.evaluate_node_set(*(doc.doc))};
220 if(nodeSet.empty()) {
224 resultTo = XPath::nodeToString(nodeSet[0], this->isTextOnly);
228 resultTo = this->query.evaluate_string(*(doc.doc));
231 catch(
const std::exception& e) {
256 if(!(this->compiled)) {
266 if(this->query.return_type() == pugi::xpath_type_node_set) {
267 const auto nodeSet{this->query.evaluate_node_set(*(doc.doc))};
269 resultTo.reserve(nodeSet.size());
271 for(
const auto& node : nodeSet) {
272 const auto result{XPath::nodeToString(node, this->isTextOnly)};
274 if(!result.empty()) {
275 resultTo.emplace_back(result);
280 const auto result{this->query.evaluate_string(*(doc.doc))};
282 if(!result.empty()) {
283 resultTo.emplace_back(result);
287 catch(
const std::exception& e) {
315 if(!(this->compiled)) {
325 if(this->query.return_type() == pugi::xpath_type_node_set) {
326 const auto nodeSet{this->query.evaluate_node_set(*(doc.doc))};
328 resultTo.reserve(nodeSet.size());
330 for(
const auto& node : nodeSet) {
331 if(node !=
nullptr) {
332 resultTo.emplace_back(node.node());
338 "Could not create subset, because the result of the query is no node set" 342 catch(
const std::exception& e) {
348 inline std::string XPath::nodeToString(
const pugi::xpath_node& node,
bool textOnly) {
351 if(node.attribute() !=
nullptr) {
352 result = node.attribute().as_string();
354 else if(node.node() !=
nullptr) {
356 XPath::TextOnlyWalker walker;
358 node.node().traverse(walker);
360 result = walker.getResult();
362 if(!result.empty()) {
367 for(
const auto& child : node.node().children()) {
368 std::ostringstream outStrStr;
371 child.print(outStrStr,
"", 0);
373 out = outStrStr.str();
396 inline bool XPath::TextOnlyWalker::for_each(pugi::xml_node& node) {
397 if(node.type() == pugi::node_pcdata) {
398 std::string nodeText(node.text().as_string());
402 this->result += nodeText;
404 this->result.push_back(
' ');
411 inline std::string XPath::TextOnlyWalker::getResult()
const {
Class for XPath exceptions.
Definition: XPath.hpp:104
void getAll(const Parsing::XML &doc, std::vector< std::string > &resultTo) const
Gets all matches from performing the query on a parsed JSON document.
Definition: XPath.hpp:251
bool getBool(const Parsing::XML &doc) const
Gets a boolean result from performing the query on a parsed XML document.
Definition: XPath.hpp:168
XPath(const std::string &xpath, bool textOnly)
Constructor setting a XPath string and whether the result should be text-only.
Definition: XPath.hpp:140
#define MAIN_EXCEPTION_CLASS()
Macro used to easily define classes for general exceptions.
Definition: Exception.hpp:50
void trim(std::string &stringToTrim)
Removes whitespaces around a string.
Definition: Strings.hpp:360
void getFirst(const Parsing::XML &doc, std::string &resultTo) const
Gets the first match from performing the query on a parsed JSON document.
Definition: XPath.hpp:202
Implements a XPath query using the pugixml library.
Definition: XPath.hpp:74
constexpr std::string_view cDataTail
The end of a CDATA tag.
Definition: XPath.hpp:60
constexpr std::string_view cDataHead
The beginning of a CDATA tag.
Definition: XPath.hpp:57
Namespace for classes handling queries.
Definition: XML.hpp:51
Parses HTML markup into clean XML.
Definition: XML.hpp:149
void getSubSets(const Parsing::XML &doc, std::vector< Parsing::XML > &resultTo) const
Gets all matching subsets from performing the query on a parsed JSON document.
Definition: XPath.hpp:310