1 // Copyright 2015 The Weave Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/notification/xml_node.h" 6 7 #include <base/strings/stringprintf.h> 8 9 #include "src/string_utils.h" 10 11 namespace weave { 12 13 XmlNode::XmlNode(const std::string& name, 14 std::map<std::string, std::string> attributes) 15 : name_{name}, attributes_{std::move(attributes)} {} 16 17 const std::string& XmlNode::name() const { 18 return name_; 19 } 20 21 const std::string& XmlNode::text() const { 22 return text_; 23 } 24 25 const std::map<std::string, std::string>& XmlNode::attributes() const { 26 return attributes_; 27 } 28 29 const std::vector<std::unique_ptr<XmlNode>>& XmlNode::children() const { 30 return children_; 31 } 32 33 bool 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 42 std::string XmlNode::GetAttributeOrEmpty(const std::string& name) const { 43 std::string value; 44 GetAttribute(name, &value); 45 return value; 46 } 47 48 const XmlNode* XmlNode::FindFirstChild(const std::string& name_path, 49 bool recursive) const { 50 return FindChildHelper(name_path, recursive, nullptr); 51 } 52 53 std::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 60 const XmlNode* XmlNode::FindChildHelper( 61 const std::string& name_path, 62 bool recursive, 63 std::vector<const XmlNode*>* children) const { 64 auto parts = SplitAtFirst(name_path, "/", false); 65 const std::string& name = parts.first; 66 const std::string& rest_of_path = parts.second; 67 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 88 void XmlNode::SetText(const std::string& text) { 89 text_ = text; 90 } 91 92 void XmlNode::AppendText(const std::string& text) { 93 text_ += text; 94 } 95 96 void XmlNode::AddChild(std::unique_ptr<XmlNode> child) { 97 child->parent_ = this; 98 children_.push_back(std::move(child)); 99 } 100 101 std::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 122 } // namespace weave 123