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