| // Copyright 2015 The Weave Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/notification/xml_node.h" |
| |
| #include <base/strings/stringprintf.h> |
| |
| #include "src/string_utils.h" |
| |
| namespace weave { |
| |
| XmlNode::XmlNode(const std::string& name, |
| std::map<std::string, std::string> attributes) |
| : name_{name}, attributes_{std::move(attributes)} {} |
| |
| const std::string& XmlNode::name() const { |
| return name_; |
| } |
| |
| const std::string& XmlNode::text() const { |
| return text_; |
| } |
| |
| const std::map<std::string, std::string>& XmlNode::attributes() const { |
| return attributes_; |
| } |
| |
| const std::vector<std::unique_ptr<XmlNode>>& XmlNode::children() const { |
| return children_; |
| } |
| |
| bool XmlNode::GetAttribute(const std::string& name, std::string* value) const { |
| auto p = attributes_.find(name); |
| if (p == attributes_.end()) |
| return false; |
| |
| *value = p->second; |
| return true; |
| } |
| |
| std::string XmlNode::GetAttributeOrEmpty(const std::string& name) const { |
| std::string value; |
| GetAttribute(name, &value); |
| return value; |
| } |
| |
| const XmlNode* XmlNode::FindFirstChild(const std::string& name_path, |
| bool recursive) const { |
| return FindChildHelper(name_path, recursive, nullptr); |
| } |
| |
| std::vector<const XmlNode*> XmlNode::FindChildren(const std::string& name_path, |
| bool recursive) const { |
| std::vector<const XmlNode*> children; |
| FindChildHelper(name_path, recursive, &children); |
| return children; |
| } |
| |
| const XmlNode* XmlNode::FindChildHelper( |
| const std::string& name_path, |
| bool recursive, |
| std::vector<const XmlNode*>* children) const { |
| auto parts = SplitAtFirst(name_path, "/", false); |
| const std::string& name = parts.first; |
| const std::string& rest_of_path = parts.second; |
| for (const auto& child : children_) { |
| const XmlNode* found_node = nullptr; |
| if (child->name() == name) { |
| if (rest_of_path.empty()) { |
| found_node = child.get(); |
| } else { |
| found_node = child->FindChildHelper(rest_of_path, false, children); |
| } |
| } else if (recursive) { |
| found_node = child->FindChildHelper(name_path, true, children); |
| } |
| |
| if (found_node) { |
| if (!children) |
| return found_node; |
| children->push_back(found_node); |
| } |
| } |
| return nullptr; |
| } |
| |
| void XmlNode::SetText(const std::string& text) { |
| text_ = text; |
| } |
| |
| void XmlNode::AppendText(const std::string& text) { |
| text_ += text; |
| } |
| |
| void XmlNode::AddChild(std::unique_ptr<XmlNode> child) { |
| child->parent_ = this; |
| children_.push_back(std::move(child)); |
| } |
| |
| std::string XmlNode::ToString() const { |
| std::string xml = base::StringPrintf("<%s", name_.c_str()); |
| for (const auto& pair : attributes_) { |
| base::StringAppendF(&xml, " %s=\"%s\"", pair.first.c_str(), |
| pair.second.c_str()); |
| } |
| if (text_.empty() && children_.empty()) { |
| xml += "/>"; |
| } else { |
| xml += '>'; |
| if (!text_.empty()) { |
| xml += text_; |
| } |
| for (const auto& child : children_) { |
| xml += child->ToString(); |
| } |
| base::StringAppendF(&xml, "</%s>", name_.c_str()); |
| } |
| return xml; |
| } |
| |
| } // namespace weave |