#include "xmpmeta/xml/search.h" #include <stack> #include <string> #include "android-base/logging.h" #include "xmpmeta/xml/utils.h" using ::dynamic_depth::xmpmeta::xml::FromXmlChar; namespace dynamic_depth { namespace xmpmeta { namespace xml { xmlNodePtr DepthFirstSearch(const xmlDocPtr parent, const char* name) { return DepthFirstSearch(parent, "", name); } xmlNodePtr DepthFirstSearch(const xmlDocPtr parent, const char* prefix, const char* name) { if (parent == nullptr || parent->children == nullptr) { LOG(ERROR) << "XML doc was null or has no XML nodes"; return nullptr; } xmlNodePtr result; for (xmlNodePtr node = parent->children; node != nullptr; node = node->next) { result = DepthFirstSearch(node, prefix, name); if (result != nullptr) { return result; } } LOG(WARNING) << "No node matching " << prefix << ":" << name << " was found"; return nullptr; } xmlNodePtr DepthFirstSearch(const xmlNodePtr parent, const char* name) { return DepthFirstSearch(parent, "", name); } xmlNodePtr DepthFirstSearch(const xmlNodePtr parent, const char* prefix, const char* name) { if (parent == nullptr) { LOG(ERROR) << "XML node was null"; return nullptr; } std::stack<xmlNodePtr> node_stack; node_stack.push(parent); while (!node_stack.empty()) { const xmlNodePtr current_node = node_stack.top(); node_stack.pop(); if (strcmp(FromXmlChar(current_node->name), name) == 0) { if (!prefix || strlen(prefix) == 0) { return current_node; } if (current_node->ns && current_node->ns->prefix && strcmp(FromXmlChar(current_node->ns->prefix), prefix) == 0) { return current_node; } } std::stack<xmlNodePtr> stack_to_reverse; for (xmlNodePtr child = current_node->children; child != nullptr; child = child->next) { stack_to_reverse.push(child); } while (!stack_to_reverse.empty()) { node_stack.push(stack_to_reverse.top()); stack_to_reverse.pop(); } } return nullptr; } } // namespace xml } // namespace xmpmeta } // namespace dynamic_depth