blob: 60f24b37ce4e8ce3e4a9503c3803f8a22d676a85 [file] [log] [blame]
Vitaly Buka4615e0d2015-10-14 15:35:12 -07001// Copyright 2015 The Weave Authors. All rights reserved.
Alex Vakulenkobf71f702015-05-18 14:30:56 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Stefan Sauer2d16dfa2015-09-25 17:08:35 +02005#include "src/notification/xml_node.h"
Alex Vakulenkobf71f702015-05-18 14:30:56 -07006
7#include <base/strings/stringprintf.h>
Vitaly Buka24d6fd52015-08-13 23:22:48 -07008
Stefan Sauer2d16dfa2015-09-25 17:08:35 +02009#include "src/string_utils.h"
Alex Vakulenkobf71f702015-05-18 14:30:56 -070010
Vitaly Bukab6f015a2015-07-09 14:59:23 -070011namespace weave {
Alex Vakulenkobf71f702015-05-18 14:30:56 -070012
13XmlNode::XmlNode(const std::string& name,
14 std::map<std::string, std::string> attributes)
Vitaly Buka4ebd3292015-09-23 18:04:17 -070015 : name_{name}, attributes_{std::move(attributes)} {}
Alex Vakulenkobf71f702015-05-18 14:30:56 -070016
17const std::string& XmlNode::name() const {
18 return name_;
19}
20
21const std::string& XmlNode::text() const {
22 return text_;
23}
24
25const std::map<std::string, std::string>& XmlNode::attributes() const {
26 return attributes_;
27}
28
29const std::vector<std::unique_ptr<XmlNode>>& XmlNode::children() const {
30 return children_;
31}
32
33bool XmlNode::GetAttribute(const std::string& name, std::string* value) const {
34 auto p = attributes_.find(name);
35 if (p == attributes_.end())
36 return false;
37
38 *value = p->second;
39 return true;
40}
41
42std::string XmlNode::GetAttributeOrEmpty(const std::string& name) const {
43 std::string value;
44 GetAttribute(name, &value);
45 return value;
46}
47
48const XmlNode* XmlNode::FindFirstChild(const std::string& name_path,
49 bool recursive) const {
50 return FindChildHelper(name_path, recursive, nullptr);
51}
52
53std::vector<const XmlNode*> XmlNode::FindChildren(const std::string& name_path,
54 bool recursive) const {
55 std::vector<const XmlNode*> children;
56 FindChildHelper(name_path, recursive, &children);
57 return children;
58}
59
60const XmlNode* XmlNode::FindChildHelper(
61 const std::string& name_path,
62 bool recursive,
63 std::vector<const XmlNode*>* children) const {
Vitaly Buka24d6fd52015-08-13 23:22:48 -070064 auto parts = SplitAtFirst(name_path, "/", false);
65 const std::string& name = parts.first;
66 const std::string& rest_of_path = parts.second;
Alex Vakulenkobf71f702015-05-18 14:30:56 -070067 for (const auto& child : children_) {
68 const XmlNode* found_node = nullptr;
69 if (child->name() == name) {
70 if (rest_of_path.empty()) {
71 found_node = child.get();
72 } else {
73 found_node = child->FindChildHelper(rest_of_path, false, children);
74 }
75 } else if (recursive) {
76 found_node = child->FindChildHelper(name_path, true, children);
77 }
78
79 if (found_node) {
80 if (!children)
81 return found_node;
82 children->push_back(found_node);
83 }
84 }
85 return nullptr;
86}
87
88void XmlNode::SetText(const std::string& text) {
89 text_ = text;
90}
91
92void XmlNode::AppendText(const std::string& text) {
93 text_ += text;
94}
95
96void XmlNode::AddChild(std::unique_ptr<XmlNode> child) {
97 child->parent_ = this;
98 children_.push_back(std::move(child));
99}
100
101std::string XmlNode::ToString() const {
102 std::string xml = base::StringPrintf("<%s", name_.c_str());
103 for (const auto& pair : attributes_) {
104 base::StringAppendF(&xml, " %s=\"%s\"", pair.first.c_str(),
105 pair.second.c_str());
106 }
107 if (text_.empty() && children_.empty()) {
108 xml += "/>";
109 } else {
110 xml += '>';
111 if (!text_.empty()) {
112 xml += text_;
113 }
114 for (const auto& child : children_) {
115 xml += child->ToString();
116 }
117 base::StringAppendF(&xml, "</%s>", name_.c_str());
118 }
119 return xml;
120}
121
Vitaly Bukab6f015a2015-07-09 14:59:23 -0700122} // namespace weave