DocWire SDK
DocWire SDK: Award-winning modern data processing in C++20. SourceForge Community Choice & Microsoft support. AI-driven processing. Supports nearly 100 data formats, including email boxes and OCR. Boost efficiency in text extraction, web data extraction, data mining, document analysis. Offline processing possible for security and confidentiality
xml_attributes.h
1 /*********************************************************************************************************************************************/
2 /* DocWire SDK: Award-winning modern data processing in C++20. SourceForge Community Choice & Microsoft support. AI-driven processing. */
3 /* Supports nearly 100 data formats, including email boxes and OCR. Boost efficiency in text extraction, web data extraction, data mining, */
4 /* document analysis. Offline processing possible for security and confidentiality */
5 /* */
6 /* Copyright (c) SILVERCODERS Ltd, http://silvercoders.com */
7 /* Project homepage: https://github.com/docwire/docwire */
8 /* */
9 /* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-DocWire-Commercial */
10 /*********************************************************************************************************************************************/
11 
12 #ifndef DOCWIRE_XML_ATTRIBUTES_H
13 #define DOCWIRE_XML_ATTRIBUTES_H
14 
15 #include "safety_policy.h"
16 #include "xml_node_ref.h"
17 #include "xml_attribute_ref.h"
18 #include "sentinel.h"
19 #include "checked.h"
20 #include "convert_base.h"
21 #include <algorithm>
22 #include <optional>
23 #include <ranges>
24 
28 namespace docwire::xml
29 {
30 
39 template <safety_policy safety_level = default_safety_level>
40 class attributes_view : public std::ranges::view_base
41 {
42 public:
43  class iterator;
44  iterator begin() const { return iterator{m_reader}; }
49  ~attributes_view() noexcept(noexcept(m_reader.get().move_to_element()))
50  {
51  m_reader.get().move_to_element();
52  }
53  sentinel end() const { return {}; }
54 
60 private:
61  std::reference_wrapper<reader<safety_level>> m_reader;
62 };
63 
72 template<safety_policy safety_level>
74 {
75  return attributes_view<safety_level>{node.state()->xml_reader};
76 }
77 
87 template<safety_policy safety_level>
88 checked<std::optional<std::string_view>, safety_level> attribute_value(const node_ref<safety_level>& node, std::string_view name)
89 {
90  auto attrs = attributes<safety_level>(node);
91  if (auto it = std::ranges::find_if(attrs, [name](const auto& attr) { return attr.name() == name; }); it != attrs.end())
92  return (*it).value();
93  return std::nullopt;
94 }
95 
106 template<typename T, safety_policy safety_level>
107 requires convert::conversion_implementation_exists<T, std::string_view>
108 checked<std::optional<T>, safety_level> attribute_value(const node_ref<safety_level>& node, std::string_view name)
109 {
110  if (auto sv = attribute_value(node, name))
111  return convert::try_to<T>(*sv);
112  return std::nullopt;
113 }
114 
118 template<safety_policy safety_level>
119 class attributes_view<safety_level>::iterator
120 {
121 public:
122  using iterator_concept = std::input_iterator_tag;
123  using difference_type = std::ptrdiff_t;
125  using pointer = const value_type*;
126  using reference = const value_type&;
127 
128  bool operator==(const sentinel&) const {
129  return !m_attribute.has_value();
130  }
131 
132  reference operator*() const {
133  return *m_attribute;
134  }
135 
136  pointer operator->() const {
137  return &operator*();
138  }
139 
140  iterator& operator++() {
141  if (m_attribute.has_value() && !m_reader.get().move_to_next_attribute()) {
142  m_attribute.reset();
143  }
144  return *this;
145  }
146 
147  void operator++(int) {
148  ++(*this);
149  }
150 
151 private:
152  friend class attributes_view<safety_level>;
153  explicit iterator(std::reference_wrapper<reader<safety_level>> reader)
154  : m_reader(reader) {
155  if (m_reader.get().move_to_first_attribute()) {
156  m_attribute.emplace(m_reader.get());
157  }
158  }
159  std::reference_wrapper<reader<safety_level>> m_reader;
160  checked<std::optional<value_type>, safety_level> m_attribute; // The presence of a value indicates a valid iterator.
161 };
162 
163 } // namespace docwire::xml
164 
165 #endif // DOCWIRE_XML_ATTRIBUTES_H
A generic wrapper for dereferenceable types (like pointers and optionals) that provides checked acces...
Definition: checked.h:39
A reference to an XML attribute.
Iterator for traversing XML attributes.
A view over the attributes of an XML node.
~attributes_view() noexcept(noexcept(m_reader.get().move_to_element()))
Destructor. Moves the reader back to the element containing the attributes to ensure consistent state...
attributes_view(reader< safety_level > &reader)
Constructs a view from a reader.
A reference to the current XML node in the reader.
Definition: xml_node_ref.h:33
const not_null< std::shared_ptr< iterator_state< safety_level > >, safety_level > & state() const
Returns the shared iterator state associated with this node reference.
Definition: xml_node_ref.h:54
XML processing utilities.
attributes_view< safety_level > attributes(const node_ref< safety_level > &node)
A factory function to create an attributes_view with a specified safety policy.
checked< std::optional< std::string_view >, safety_level > attribute_value(const node_ref< safety_level > &node, std::string_view name)
A convenience helper to find an attribute by name.
requires(!string_method_equipped< T >) struct stringifier< T >
Specialization for types that are streamable to std::ostream.
A sentinel type used to define the end of a range or view.
Definition: sentinel.h:23