普通文本  |  123行  |  3.16 KB

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