Home | History | Annotate | Download | only in notification
      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