• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "xmpmeta/xml/search.h"
2 
3 #include <stack>
4 #include <string>
5 
6 #include "android-base/logging.h"
7 #include "xmpmeta/xml/utils.h"
8 
9 using ::dynamic_depth::xmpmeta::xml::FromXmlChar;
10 
11 namespace dynamic_depth {
12 namespace xmpmeta {
13 namespace xml {
14 
DepthFirstSearch(const xmlDocPtr parent,const char * name)15 xmlNodePtr DepthFirstSearch(const xmlDocPtr parent, const char* name) {
16   return DepthFirstSearch(parent, "", name);
17 }
18 
DepthFirstSearch(const xmlDocPtr parent,const char * prefix,const char * name)19 xmlNodePtr DepthFirstSearch(const xmlDocPtr parent, const char* prefix,
20                             const char* name) {
21   if (parent == nullptr || parent->children == nullptr) {
22     LOG(ERROR) << "XML doc was null or has no XML nodes";
23     return nullptr;
24   }
25   xmlNodePtr result;
26   for (xmlNodePtr node = parent->children; node != nullptr; node = node->next) {
27     result = DepthFirstSearch(node, prefix, name);
28     if (result != nullptr) {
29       return result;
30     }
31   }
32   LOG(WARNING) << "No node matching " << prefix << ":" << name << " was found";
33   return nullptr;
34 }
35 
DepthFirstSearch(const xmlNodePtr parent,const char * name)36 xmlNodePtr DepthFirstSearch(const xmlNodePtr parent, const char* name) {
37   return DepthFirstSearch(parent, "", name);
38 }
39 
DepthFirstSearch(const xmlNodePtr parent,const char * prefix,const char * name)40 xmlNodePtr DepthFirstSearch(const xmlNodePtr parent, const char* prefix,
41                             const char* name) {
42   if (parent == nullptr) {
43     LOG(ERROR) << "XML node was null";
44     return nullptr;
45   }
46   std::stack<xmlNodePtr> node_stack;
47   node_stack.push(parent);
48   while (!node_stack.empty()) {
49     const xmlNodePtr current_node = node_stack.top();
50     node_stack.pop();
51     if (strcmp(FromXmlChar(current_node->name), name) == 0) {
52       if (!prefix || strlen(prefix) == 0) {
53         return current_node;
54       }
55       if (current_node->ns && current_node->ns->prefix &&
56           strcmp(FromXmlChar(current_node->ns->prefix), prefix) == 0) {
57         return current_node;
58       }
59     }
60     std::stack<xmlNodePtr> stack_to_reverse;
61     for (xmlNodePtr child = current_node->children; child != nullptr;
62          child = child->next) {
63       stack_to_reverse.push(child);
64     }
65     while (!stack_to_reverse.empty()) {
66       node_stack.push(stack_to_reverse.top());
67       stack_to_reverse.pop();
68     }
69   }
70   return nullptr;
71 }
72 
73 }  // namespace xml
74 }  // namespace xmpmeta
75 }  // namespace dynamic_depth
76