Пример #1
0
/**
 * Takes a pointer to an XML node that is assumed to point at a "material"
 * tag.
 * It reads the definition and produces a new Material object.
 * @param element A pointer to an Element node that is a "material" tag
 * @return A new Material object
 */
Material MaterialXMLParser::parse(Poco::XML::Element *element) const {
  using namespace Poco::XML;
  typedef AutoPtr<NamedNodeMap> NamedNodeMapPtr;
  NamedNodeMapPtr attrs = element->attributes();
  const auto id = attrs->getNamedItem(ID_ATT);
  if (!id || id->nodeValue().empty()) {
    throw std::invalid_argument("MaterialXMLReader::read() - No 'id' tag found "
                                "or emptry string provided.");
  }
  attrs->removeNamedItem(ID_ATT);

  MaterialBuilder builder;
  builder.setName(id->nodeValue());
  const auto nattrs = attrs->length();
  for (unsigned long i = 0; i < nattrs; ++i) {
    Node *node = attrs->item(i);
    addToBuilder(&builder, node->nodeName(), node->nodeValue());
  }
  return builder.build();
}
Пример #2
0
void ConfigProcessor::doIncludesRecursive(
        XMLDocumentPtr config,
        XMLDocumentPtr include_from,
        Node * node,
        zkutil::ZooKeeperNodeCache * zk_node_cache,
        std::unordered_set<std::string> & contributing_zk_paths)
{
    if (node->nodeType() == Node::TEXT_NODE)
    {
        for (auto & substitution : substitutions)
        {
            std::string value = node->nodeValue();

            bool replace_occured = false;
            size_t pos;
            while ((pos = value.find(substitution.first)) != std::string::npos)
            {
                value.replace(pos, substitution.first.length(), substitution.second);
                replace_occured = true;
            }

            if (replace_occured)
                node->setNodeValue(value);
        }
    }

    if (node->nodeType() != Node::ELEMENT_NODE)
        return;

    /// Substitute <layer> for the number extracted from the hostname only if there is an
    /// empty <layer> tag without attributes in the original file.
    if ( node->nodeName() == "layer" &&
        !node->hasAttributes() &&
        !node->hasChildNodes() &&
         node->nodeValue().empty())
    {
        NodePtr new_node = config->createTextNode(layerFromHost());
        node->appendChild(new_node);
        return;
    }

    NamedNodeMapPtr attributes = node->attributes();
    Node * incl_attribute = attributes->getNamedItem("incl");
    Node * from_zk_attribute = attributes->getNamedItem("from_zk");

    if (incl_attribute && from_zk_attribute)
        throw Poco::Exception("both incl and from_zk attributes set for element <" + node->nodeName() + ">");

    /// Replace the original contents, not add to it.
    bool replace = attributes->getNamedItem("replace");

    auto process_include = [&](const Node * include_attr, const std::function<Node * (const std::string &)> & get_node, const char * error_msg)
    {
        std::string name = include_attr->getNodeValue();
        Node * node_to_include = get_node(name);
        if (!node_to_include)
        {
            if (attributes->getNamedItem("optional"))
                node->parentNode()->removeChild(node);
            else if (throw_on_bad_incl)
                throw Poco::Exception(error_msg + name);
            else
                LOG_WARNING(log, error_msg << name);
        }
        else
        {
            Element * element = dynamic_cast<Element *>(node);

            element->removeAttribute("incl");
            element->removeAttribute("from_zk");

            if (replace)
            {
                while (Node * child = node->firstChild())
                    node->removeChild(child);

                element->removeAttribute("replace");
            }

            NodeListPtr children = node_to_include->childNodes();
            for (size_t i = 0; i < children->length(); ++i)
            {
                NodePtr new_node = config->importNode(children->item(i), true);
                node->appendChild(new_node);
            }

            NamedNodeMapPtr from_attrs = node_to_include->attributes();
            for (size_t i = 0; i < from_attrs->length(); ++i)
            {
                element->setAttributeNode(dynamic_cast<Attr *>(config->importNode(from_attrs->item(i), true)));
            }
        }
    };

    auto get_incl_node = [&](const std::string & name)
    {
        return include_from ? include_from->getNodeByPath("yandex/" + name) : nullptr;
    };
    if (incl_attribute)
        process_include(incl_attribute, get_incl_node, "Include not found: ");

    if (from_zk_attribute)
    {
        contributing_zk_paths.insert(from_zk_attribute->getNodeValue());

        if (zk_node_cache)
        {
            XMLDocumentPtr zk_document;
            auto get_zk_node = [&](const std::string & name) -> Node *
            {
                std::optional<std::string> contents = zk_node_cache->get(name);
                if (!contents)
                    return nullptr;

                /// Enclose contents into a fake <from_zk> tag to allow pure text substitutions.
                zk_document = dom_parser.parseString("<from_zk>" + *contents + "</from_zk>");
                return getRootNode(zk_document.get());
            };

            process_include(from_zk_attribute, get_zk_node, "Could not get ZooKeeper node: ");
        }
    }

    NodeListPtr children = node->childNodes();
    for (size_t i = 0; i < children->length(); ++i)
    {
        doIncludesRecursive(config, include_from, children->item(i), zk_node_cache, contributing_zk_paths);
    }
}