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
16
17static const char* const SPACE = " \t\r\n";
18
19
24ExcXMLCore::ExcXMLCore (const std::string& what)
25 : std::runtime_error ("ExcXMLCore: " + what)
26{
27}
28
29
37 const std::string& name,
38 const std::string& value)
39 : m_type (type),
40 m_name (name),
41 m_value (value)
42{
43}
44
45
51void XMLCoreNode::set_attrib (const std::string& name, const std::string& value)
52{
53 m_attribs[name] = value;
54}
55
56
63XMLCoreNode* XMLCoreNode::add_child (std::unique_ptr<XMLCoreNode> child)
64{
65 child->set_parent (this);
66 m_children.push_back (std::move (child));
67 return m_children.back().get();
68}
69
70
78
79
84{
85 return m_parent;
86}
87
88
96
97
101const std::string& XMLCoreNode::get_name() const
102{
103 return m_name;
104}
105
106
110const std::string& XMLCoreNode::get_value() const
111{
112 return m_value;
113}
114
115
120{
121 return m_attribs.size();
122}
123
124
132std::string XMLCoreNode::get_attrib_name (size_t i) const
133{
134 if (i >= m_attribs.size()) {
135 throw ExcXMLCore ("Out-of-range attribute index " + std::to_string(i) + " in " + m_name);
136 }
137
138 auto it = m_attribs.begin();
139 std::advance (it, i);
140 return it->first;
141}
142
143
148bool XMLCoreNode::has_attrib (const std::string& name) const
149{
150 return m_attribs.contains (name);
151}
152
153
161template <class T>
162std::optional<T> XMLCoreNode::try_attrib (const std::string& name) const
163{
164 std::optional<T> ret;
165 auto it = m_attribs.find (name);
166 if (it == m_attribs.end()) return ret;
167
168 T val = 0;
169 std::string::size_type beg = it->second.find_first_not_of (SPACE);
170 std::string::size_type end = it->second.find_last_not_of (SPACE);
171 if (beg == std::string::npos || end == std::string::npos) return ret;
172 const char* begp = it->second.c_str()+beg;
173 const char* endp = it->second.c_str()+end+1;
174 auto [ptr, ec] = std::from_chars (begp, endp, val);
175 if (ec == std::errc() && ptr == endp)
176 ret.emplace (val);
177 return ret;
178}
179
180
188std::optional<int> XMLCoreNode::try_int_attrib (const std::string& name) const
189{
190 return try_attrib<int> (name);
191}
192
193
201std::optional<double> XMLCoreNode::try_double_attrib (const std::string& name) const
202{
203 return try_attrib<double> (name);
204}
205
206
213const std::string& XMLCoreNode::get_attrib (const std::string& name) const
214{
215 auto it = m_attribs.find (name);
216 if (it == m_attribs.end()) {
217 throw ExcXMLCore ("Cannot find attribute " + name + " in " + m_name);
218 }
219 return it->second;
220}
221
222
230int XMLCoreNode::get_int_attrib (const std::string& name) const
231{
232 std::optional<int> val = try_int_attrib (name);
233 if (!val) {
234 throw ExcXMLCore ("Bad integer attribute " + name + " in " + m_name);
235 }
236 return val.value();
237}
238
239
247double XMLCoreNode::get_double_attrib (const std::string& name) const
248{
249 std::optional<double> val = try_double_attrib (name);
250 if (!val) {
251 throw ExcXMLCore ("Bad double attribute " + name + " in " + m_name);
252 }
253 return val.value();
254}
255
256
266const XMLCoreNode* XMLCoreNode::get_child (const std::string& path) const
267{
268 std::vector<const XMLCoreNode*> children;
269 collect_children (path, children, true);
270 if (!children.empty()) {
271 return children[0];
272 }
273 return nullptr;
274}
275
276
286std::vector<const XMLCoreNode*>
287XMLCoreNode::get_children (const std::string& path /*= "*"*/) const
288{
289 std::vector<const XMLCoreNode*> children;
290 collect_children (path, children, false);
291 return children;
292}
293
294
295/*
296 * @brief Print the node structure in XML format (to cout).
297 * @param header String to print on hte first line.
298 * @param depth Initial nesting depth.
299 */
300void XMLCoreNode::print (const std::string& header,
301 int depth /*= 0*/) const
302{
303 print (std::cout, header, depth);
304}
305
306
307/*
308 * @brief Print the node structure in XML format.
309 * @param os Stream to which to print.
310 * @param header String to print on hte first line.
311 * @param depth Initial nesting depth.
312 */
313void XMLCoreNode::print (std::ostream& os,
314 const std::string& header,
315 int depth /*= 0*/) const
316{
317 if (!header.empty()) {
318 os << header << std::endl;
319 }
320
321 if (m_type == TEXT_NODE) {
322 bool allspace = m_value.find_last_of(SPACE) == std::string::npos;
323 if (!allspace)
324 os << m_value << std::endl;
325 return;
326 }
327
328 for (int i = 0; i < depth; i++) os << " ";
329
330 if (m_type == COMMENT_NODE) {
331 os << "<!--" << m_value << "-->" << std::endl;
332 return;
333 }
334
335 os << "<" << m_name;
336
337 for (const auto& p : m_attribs) {
338 os << " " << p.first << "='" << p.second << "'";
339 }
340
341 os << ">" << std::endl;
342
343 for (const auto& child : m_children) {
344 child->print (os, "", depth+1);
345 }
346
347 for (int i = 0; i < depth; i++) os << " ";
348 os << "</" << m_name << ">" << std::endl;
349 return;
350}
351
352
358{
359 m_parent = parent;
360}
361
362
371void XMLCoreNode::collect_children (const std::string& path,
372 std::vector<const XMLCoreNode*>& children,
373 bool only_one) const
374{
375 std::string::size_type pos = path.find ('/');
376 std::string name = path.substr (0, pos);
377 std::string tail;
378 if (pos != std::string::npos) {
379 tail = path.substr (pos+1);
380 }
381
382 for (const auto& child : m_children) {
383 if (name == "*" || child->get_name() == name) {
384 if (tail.empty()) {
385 children.push_back (child.get());
386 }
387 else {
388 child->collect_children (tail, children, only_one);
389 }
390 }
391 if (only_one && !children.empty()) break;
392 }
393}
394
395
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:31
ExcXMLCore(const std::string &what)
Constructor.
std::string m_value
The value fo this node.
NodeType
Classify node types.
Definition XMLCoreNode.h:51
double get_double_attrib(const std::string &name) const
Retrieve the value of an attribute as a double.
std::string m_name
The name of this node.
const std::string & get_attrib(const std::string &name) const
Retrieve the value of an attribute.
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.
NodeType get_type() const
Return the type of this node.
std::optional< int > try_int_attrib(const std::string &name) const
Try to retrieve an integer attribute.
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.
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.
std::optional< double > try_double_attrib(const std::string &name) const
Try to retrieve an double attribute.
std::optional< T > try_attrib(const std::string &name) const
Try to retrieve an attribute of type T.
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.
int get_int_attrib(const std::string &name) const
Retrieve the value of an attribute as an integer.
std::map< std::string, std::string > m_attribs
Attributes of this node.
std::vector< std::unique_ptr< XMLCoreNode > > m_children
Children of this node.
const XMLCoreNode * get_child(const std::string &path) const
Return the first child matching a pattern, or nullptr.
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.