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