Alex Vakulenko | bf71f70 | 2015-05-18 14:30:56 -0700 | [diff] [blame] | 1 | // Copyright 2015 The Chromium OS 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 "buffet/notification/xml_node.h" |
| 6 | |
| 7 | #include <base/strings/stringprintf.h> |
| 8 | #include <chromeos/strings/string_utils.h> |
| 9 | |
| 10 | namespace buffet { |
| 11 | |
| 12 | XmlNode::XmlNode(const std::string& name, |
| 13 | std::map<std::string, std::string> attributes) |
| 14 | : name_{name}, attributes_{std::move(attributes)} {} |
| 15 | |
| 16 | const std::string& XmlNode::name() const { |
| 17 | return name_; |
| 18 | } |
| 19 | |
| 20 | const std::string& XmlNode::text() const { |
| 21 | return text_; |
| 22 | } |
| 23 | |
| 24 | const std::map<std::string, std::string>& XmlNode::attributes() const { |
| 25 | return attributes_; |
| 26 | } |
| 27 | |
| 28 | const std::vector<std::unique_ptr<XmlNode>>& XmlNode::children() const { |
| 29 | return children_; |
| 30 | } |
| 31 | |
| 32 | bool XmlNode::GetAttribute(const std::string& name, std::string* value) const { |
| 33 | auto p = attributes_.find(name); |
| 34 | if (p == attributes_.end()) |
| 35 | return false; |
| 36 | |
| 37 | *value = p->second; |
| 38 | return true; |
| 39 | } |
| 40 | |
| 41 | std::string XmlNode::GetAttributeOrEmpty(const std::string& name) const { |
| 42 | std::string value; |
| 43 | GetAttribute(name, &value); |
| 44 | return value; |
| 45 | } |
| 46 | |
| 47 | const XmlNode* XmlNode::FindFirstChild(const std::string& name_path, |
| 48 | bool recursive) const { |
| 49 | return FindChildHelper(name_path, recursive, nullptr); |
| 50 | } |
| 51 | |
| 52 | std::vector<const XmlNode*> XmlNode::FindChildren(const std::string& name_path, |
| 53 | bool recursive) const { |
| 54 | std::vector<const XmlNode*> children; |
| 55 | FindChildHelper(name_path, recursive, &children); |
| 56 | return children; |
| 57 | } |
| 58 | |
| 59 | const XmlNode* XmlNode::FindChildHelper( |
| 60 | const std::string& name_path, |
| 61 | bool recursive, |
| 62 | std::vector<const XmlNode*>* children) const { |
| 63 | std::string name; |
| 64 | std::string rest_of_path; |
| 65 | chromeos::string_utils::SplitAtFirst(name_path, "/", &name, &rest_of_path, |
| 66 | false); |
| 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 buffet |