| // 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 |