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