Bump version to 6.4.7.2.M8
[LibreOffice.git] / external / liborcus / 0001-add-xml-path.patch
blob3f9a16bb880fb547908f29492b35c208f091a398
1 diff --git a/include/orcus/xml_structure_tree.hpp b/include/orcus/xml_structure_tree.hpp
2 index 58cabfd116fa24e35ff27cf8d7512b6e73df33f4..c88808d24bd74c175fa4017328d3e54b4c588c5e 100644
3 --- a/include/orcus/xml_structure_tree.hpp
4 +++ b/include/orcus/xml_structure_tree.hpp
5 @@ -127,6 +127,20 @@ public:
6 size_t get_xmlns_index(xmlns_id_t ns) const;
8 std::string get_xmlns_short_name(xmlns_id_t ns) const;
10 + /**
11 + * Get a XPath like ID for the element inside of the XML tree.
12 + *
13 + */
14 + std::string get_path() const;
16 + /**
17 + * Select an element by a path expression. The path expression may be
18 + * generated by <code>xml_structure_tree::walker::get_path</code>.
19 + *
20 + * @param path a simple XPath like expression
21 + */
22 + element select_by_path(const std::string& path);
25 xml_structure_tree(xmlns_context& xmlns_cxt);
26 diff --git a/src/liborcus/xml_structure_tree.cpp b/src/liborcus/xml_structure_tree.cpp
27 index 2778bc05f32841a9441bf471913872e119256895..6622bc57cd2595f12bba80d4bbdb5c24cd6e7bc6 100644
28 --- a/src/liborcus/xml_structure_tree.cpp
29 +++ b/src/liborcus/xml_structure_tree.cpp
30 @@ -12,6 +12,7 @@
31 #include "orcus/exception.hpp"
33 #include "orcus/string_pool.hpp"
34 +#include "string_helper.hpp"
36 #include <iostream>
37 #include <sstream>
38 @@ -275,6 +276,15 @@ struct xml_structure_tree_impl
40 delete mp_root;
43 + std::string get_element_str(const xml_structure_tree::entity_name& name) const
44 + {
45 + ostringstream ss;
46 + if (m_xmlns_cxt.get_index(name.ns) != index_not_found)
47 + ss << m_xmlns_cxt.get_short_name(name.ns) << ":";
48 + ss << name.name;
49 + return ss.str();
50 + }
53 struct xml_structure_tree::walker_impl
54 @@ -423,6 +433,66 @@ string xml_structure_tree::walker::get_xmlns_short_name(xmlns_id_t ns) const
55 return mp_impl->m_parent_impl.m_xmlns_cxt.get_short_name(ns);
58 +string xml_structure_tree::walker::get_path() const
60 + ostringstream ss;
61 + for (auto& element : mp_impl->m_scopes)
62 + {
63 + ss << "/" << mp_impl->m_parent_impl.get_element_str(element.name);
64 + }
66 + return ss.str();
69 +xml_structure_tree::element xml_structure_tree::walker::select_by_path(const std::string& path)
71 + pstring p(path);
72 + std::vector<pstring> parts = string_helper::split_string(p, '/');
73 + if (parts.empty())
74 + throw general_error("invalid format for path");
76 + // string_helper::split_string will create an empty first element due to leading '/'
77 + if (parts[0] != "")
78 + {
79 + throw general_error("invalid format for path");
80 + }
81 + else
82 + {
83 + parts.erase(parts.begin());
84 + }
86 + if (parts.empty())
87 + throw general_error("invalid format for path");
89 + element_ref root_ref(mp_impl->mp_root->name, &mp_impl->mp_root->prop);
90 + if (pstring(mp_impl->m_parent_impl.get_element_str(root_ref.name)) != parts[0])
91 + throw general_error("path does not match any element");
93 + std::vector<element_ref> scopes;
94 + scopes.push_back(root_ref);
96 + for (size_t i = 1; i < parts.size(); ++i)
97 + {
98 + const elem_prop& prop = *scopes.back().prop;
99 + bool found = false;
100 + for (auto& child : prop.child_elements)
102 + if (pstring(mp_impl->m_parent_impl.get_element_str(child.first)) == parts[i])
104 + scopes.emplace_back(child.first, child.second);
105 + found = true;
106 + break;
109 + if (!found)
110 + throw general_error("path does not match any element");
113 + std::swap(mp_impl->m_scopes, scopes);
114 + const element_ref& ref = mp_impl->m_scopes.back();
115 + return element(ref.name, ref.prop->repeat);
118 xml_structure_tree::xml_structure_tree(xmlns_context& xmlns_cxt) :
119 mp_impl(new xml_structure_tree_impl(xmlns_cxt)) {}