ATLAS Offline Software
Loading...
Searching...
No Matches
XMLCoreNode.cxx
Go to the documentation of this file.
1/*
2 * Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration.
3 */
10
11
13#include <charconv>
14#include <iostream>
15#include <format>
16
17
18static const char* const SPACE = " \t\r\n";
19
20
25ExcXMLCore::ExcXMLCore (const std::string& what)
26 : std::runtime_error ("ExcXMLCore: " + what)
27{
28}
29
30
38 const std::string& name,
39 const std::string& value)
40 : m_type (type),
41 m_name (name),
42 m_value (value)
43{
44}
45
46
52void XMLCoreNode::set_attrib (const std::string& name, const std::string& value)
53{
54 m_attribs[name] = value;
55}
56
57
64XMLCoreNode* XMLCoreNode::add_child (std::unique_ptr<XMLCoreNode> child)
65{
66 child->set_parent (this);
67 m_children.push_back (std::move (child));
68 return m_children.back().get();
69}
70
71
79
80
85{
86 return m_parent;
87}
88
89
97
98
102const std::string& XMLCoreNode::get_name() const
103{
104 return m_name;
105}
106
107
111const std::string& XMLCoreNode::get_value() const
112{
113 return m_value;
114}
115
116
121{
122 return m_attribs.size();
123}
124
125
133std::string XMLCoreNode::get_attrib_name (size_t i) const
134{
135 if (i >= m_attribs.size()) {
136 throw ExcXMLCore ("Out-of-range attribute index " + std::to_string(i) + " in " + m_name);
137 }
138
139 auto it = m_attribs.begin();
140 std::advance (it, i);
141 return it->first;
142}
143
144
149bool XMLCoreNode::has_attrib (const std::string& name) const
150{
151 return m_attribs.contains (name);
152}
153
154
162template <class T>
163std::optional<T> XMLCoreNode::try_attrib (std::string_view name) const
164{
165 std::optional<T> ret;
166 auto it = m_attribs.find (name);
167 if (it == m_attribs.end()) return ret;
168
169 T val = 0;
170 std::string::size_type beg = it->second.find_first_not_of (SPACE);
171 std::string::size_type end = it->second.find_last_not_of (SPACE);
172 if (beg == std::string::npos || end == std::string::npos) return ret;
173 const char* begp = it->second.c_str()+beg;
174 const char* endp = it->second.c_str()+end+1;
175 auto [ptr, ec] = std::from_chars (begp, endp, val);
176 if (ec == std::errc() && ptr == endp)
177 ret.emplace (val);
178 return ret;
179}
180
181
189std::optional<int> XMLCoreNode::try_int_attrib (std::string_view name) const
190{
191 return try_attrib<int> (name);
192}
193
194
202std::optional<double> XMLCoreNode::try_double_attrib (std::string_view name) const
203{
204 return try_attrib<double> (name);
205}
206
207
214const std::string& XMLCoreNode::get_attrib (std::string_view name) const
215{
216 auto it = m_attribs.find (name);
217 if (it == m_attribs.end()) {
218 throw ExcXMLCore (std::format("Cannot find attribute {} in {}", name, m_name));
219 }
220 return it->second;
221}
222
223
231int XMLCoreNode::get_int_attrib (std::string_view name) const
232{
233 std::optional<int> val = try_int_attrib (name);
234 if (!val) {
235 throw ExcXMLCore (std::format("Bad integer attribute {} in {}", name, m_name));
236 }
237 return val.value();
238}
239
240
248double XMLCoreNode::get_double_attrib (std::string_view name) const
249{
250 std::optional<double> val = try_double_attrib (name);
251 if (!val) {
252 throw ExcXMLCore (std::format("Bad double attribute {} in {}", name, m_name));
253 }
254 return val.value();
255}
256
257
267const XMLCoreNode* XMLCoreNode::get_child (const std::string& path) const
268{
269 std::vector<const XMLCoreNode*> children;
270 collect_children (path, children, true);
271 if (!children.empty()) {
272 return children[0];
273 }
274 return nullptr;
275}
276
277
287std::vector<const XMLCoreNode*>
288XMLCoreNode::get_children (const std::string& path /*= "*"*/) const
289{
290 std::vector<const XMLCoreNode*> children;
291 collect_children (path, children, false);
292 return children;
293}
294
295
296/*
297 * @brief Print the node structure in XML format (to cout).
298 * @param header String to print on hte first line.
299 * @param depth Initial nesting depth.
300 */
301void XMLCoreNode::print (const std::string& header,
302 int depth /*= 0*/) const
303{
304 print (std::cout, header, depth);
305}
306
307
308/*
309 * @brief Print the node structure in XML format.
310 * @param os Stream to which to print.
311 * @param header String to print on hte first line.
312 * @param depth Initial nesting depth.
313 */
314void XMLCoreNode::print (std::ostream& os,
315 const std::string& header,
316 int depth /*= 0*/) const
317{
318 if (!header.empty()) {
319 os << header << std::endl;
320 }
321
322 if (m_type == TEXT_NODE) {
323 bool allspace = m_value.find_last_of(SPACE) == std::string::npos;
324 if (!allspace)
325 os << m_value << std::endl;
326 return;
327 }
328
329 for (int i = 0; i < depth; i++) os << " ";
330
331 if (m_type == COMMENT_NODE) {
332 os << "<!--" << m_value << "-->" << std::endl;
333 return;
334 }
335
336 os << "<" << m_name;
337
338 for (const auto& p : m_attribs) {
339 os << " " << p.first << "='" << p.second << "'";
340 }
341
342 os << ">" << std::endl;
343
344 for (const auto& child : m_children) {
345 child->print (os, "", depth+1);
346 }
347
348 for (int i = 0; i < depth; i++) os << " ";
349 os << "</" << m_name << ">" << std::endl;
350 return;
351}
352
353
359{
360 m_parent = parent;
361}
362
363
372void XMLCoreNode::collect_children (const std::string& path,
373 std::vector<const XMLCoreNode*>& children,
374 bool only_one) const
375{
376 std::string::size_type pos = path.find ('/');
377 std::string name = path.substr (0, pos);
378 std::string tail;
379 if (pos != std::string::npos) {
380 tail = path.substr (pos+1);
381 }
382
383 for (const auto& child : m_children) {
384 if (name == "*" || child->get_name() == name) {
385 if (tail.empty()) {
386 children.push_back (child.get());
387 }
388 else {
389 child->collect_children (tail, children, only_one);
390 }
391 }
392 if (only_one && !children.empty()) break;
393 }
394}
395
396
static const char *const SPACE
Simple DOM-like node structure to hold the result of XML parsing.
Class for exceptions thrown from XMLCoreParser.
Definition XMLCoreNode.h:32
ExcXMLCore(const std::string &what)
Constructor.
std::string m_value
The value fo this node.
int get_int_attrib(std::string_view name) const
Retrieve the value of an attribute as an integer.
NodeType
Classify node types.
Definition XMLCoreNode.h:52
std::map< std::string, std::string, std::less<> > m_attribs
Attributes of this node.
std::string m_name
The name of this node.
XMLCoreNode * m_parent
The parent of this node, or null for a top-level node.
NodeType m_type
The type of this node.
XMLCoreNode(NodeType type, const std::string &name="", const std::string &value="")
Constructor.
std::string get_attrib_name(size_t i) const
Return the name of the i'th attribute.
bool has_attrib(const std::string &name) const
Test for presence of an attribute with a given name.
std::vector< const XMLCoreNode * > get_children(const std::string &path="*") const
Return all children matching a pattern.
void print(const std::string &header, int depth=0) const
XMLCoreNode * add_child(std::unique_ptr< XMLCoreNode > child)
Add a new child to this node.
void set_parent(XMLCoreNode *parent)
Set the parent for this node.
std::optional< double > try_double_attrib(std::string_view name) const
Try to retrieve an double attribute.
NodeType get_type() const
Return the type of this node.
size_t n_attribs() const
Return the number of attributes for this node.
const std::string & get_value() const
Return the value of this node, or an empty string if no value.
double get_double_attrib(std::string_view name) const
Retrieve the value of an attribute as a double.
XMLCoreNode * get_parent()
Get the parent of this node, or nullptr for a top-level node.
void set_attrib(const std::string &name, const std::string &value)
Set the value of an attribute for this node.
void collect_children(const std::string &path, std::vector< const XMLCoreNode * > &children, bool only_one) const
Collect children of this node matching a path.
const std::string & get_name() const
Return the name of this node, or an empty string if no name.
std::optional< int > try_int_attrib(std::string_view name) const
Try to retrieve an integer attribute.
std::vector< std::unique_ptr< XMLCoreNode > > m_children
Children of this node.
std::optional< T > try_attrib(std::string_view name) const
Try to retrieve an attribute of type T.
const XMLCoreNode * get_child(const std::string &path) const
Return the first child matching a pattern, or nullptr.
const std::string & get_attrib(std::string_view name) const
Retrieve the value of an attribute.
STL class.
std::string tail(std::string s, const std::string &pattern)
tail of a string
std::string depth
tag string for intendation
Definition fastadd.cxx:46
STL namespace.