XmlDom.cpp revision efeb7af13be4446ce4a511a2ca707691e9a67c1e
175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/*
275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Copyright (C) 2015 The Android Open Source Project
375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski *
475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * you may not use this file except in compliance with the License.
675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * You may obtain a copy of the License at
775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski *
875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski *
1075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Unless required by applicable law or agreed to in writing, software
1175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
1275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * See the License for the specific language governing permissions and
1475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * limitations under the License.
1575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
1675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
1775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include "XmlDom.h"
1875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
19467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include <expat.h>
20ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
2175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <memory>
2275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <stack>
2375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <string>
2475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <tuple>
2575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
26ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "android-base/logging.h"
27ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
28d0f492db038c6210c1138865d816bfb134376538Adam Lesinski#include "ResourceUtils.h"
29ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "XmlPullParser.h"
30ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "util/Util.h"
31ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
32efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinskiusing ::aapt::io::InputStream;
33efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinskiusing ::android::StringPiece;
34efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinskiusing ::android::StringPiece16;
35d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski
3675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace aapt {
3775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace xml {
3875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
3975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskiconstexpr char kXmlNamespaceSep = 1;
4075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
4175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistruct Stack {
42ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<xml::Node> root;
43ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::stack<xml::Node*> node_stack;
44ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string pending_comment;
45ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  std::unique_ptr<xml::Text> last_text_node;
4675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski};
4775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
4875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/**
4975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Extracts the namespace and name of an expanded element or attribute name.
5075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
51ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void SplitName(const char* name, std::string* out_ns,
52ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                      std::string* out_name) {
53ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const char* p = name;
54ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  while (*p != 0 && *p != kXmlNamespaceSep) {
55ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    p++;
56ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
57ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
58ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (*p == 0) {
59ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    out_ns->clear();
60d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski    out_name->assign(name);
61ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  } else {
62d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski    out_ns->assign(name, (p - name));
63d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski    out_name->assign(p + 1);
64ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
6575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
6675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
67ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinskistatic void FinishPendingText(Stack* stack) {
68ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  if (stack->last_text_node != nullptr) {
6948448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski    if (!stack->last_text_node->text.empty()) {
70ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski      stack->node_stack.top()->AppendChild(std::move(stack->last_text_node));
71ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski    } else {
72ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski      // Drop an empty text node.
73ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski    }
7448448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski    stack->last_text_node = nullptr;
75ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  }
76ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski}
77ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski
78ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void AddToStack(Stack* stack, XML_Parser parser,
79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                       std::unique_ptr<Node> node) {
80ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  node->line_number = XML_GetCurrentLineNumber(parser);
81ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  node->column_number = XML_GetCurrentColumnNumber(parser);
82ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
83ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Node* this_node = node.get();
84ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!stack->node_stack.empty()) {
85e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski    stack->node_stack.top()->AppendChild(std::move(node));
86ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  } else {
87ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    stack->root = std::move(node);
88ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
89ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!NodeCast<Text>(this_node)) {
91ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    stack->node_stack.push(this_node);
92ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
9375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
9475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
95ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix,
96ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                          const char* uri) {
97ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
98ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
99ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  FinishPendingText(stack);
10075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
101ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<Namespace> ns = util::make_unique<Namespace>();
102ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (prefix) {
103d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski    ns->namespace_prefix = prefix;
104ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
10575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
106ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (uri) {
107d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski    ns->namespace_uri = uri;
108ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
10975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
110ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  AddToStack(stack, parser, std::move(ns));
11175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
11275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
113ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL EndNamespaceHandler(void* user_data, const char* prefix) {
114ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
115ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
116ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  FinishPendingText(stack);
11775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
118ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  CHECK(!stack->node_stack.empty());
119ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  stack->node_stack.pop();
12075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
12175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
122ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic bool less_attribute(const Attribute& lhs, const Attribute& rhs) {
123ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return std::tie(lhs.namespace_uri, lhs.name, lhs.value) <
124ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski         std::tie(rhs.namespace_uri, rhs.name, rhs.value);
12575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
12675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
127ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL StartElementHandler(void* user_data, const char* name,
128ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                        const char** attrs) {
129ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
130ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
131ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  FinishPendingText(stack);
13275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
133ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<Element> el = util::make_unique<Element>();
134ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  SplitName(name, &el->namespace_uri, &el->name);
13575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
136ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  while (*attrs) {
137ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    Attribute attribute;
138ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    SplitName(*attrs++, &attribute.namespace_uri, &attribute.name);
13948448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski    attribute.value = *attrs++;
14075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
141ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    // Insert in sorted order.
14248448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski    auto iter = std::lower_bound(el->attributes.begin(), el->attributes.end(), attribute,
14348448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski                                 less_attribute);
144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    el->attributes.insert(iter, std::move(attribute));
145ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
14675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
147ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->comment = std::move(stack->pending_comment);
148ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  AddToStack(stack, parser, std::move(el));
14975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
15075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
151ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL EndElementHandler(void* user_data, const char* name) {
152ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
153ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
154ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  FinishPendingText(stack);
15575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
156ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  CHECK(!stack->node_stack.empty());
157ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // stack->nodeStack.top()->comment = std::move(stack->pendingComment);
158ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  stack->node_stack.pop();
15975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
16075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
161ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinskistatic void XMLCALL CharacterDataHandler(void* user_data, const char* s, int len) {
162ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
163ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
164ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
165ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  const StringPiece str(s, len);
166ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  if (str.empty()) {
167ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return;
168ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
169ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
170ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // See if we can just append the text to a previous text node.
171ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  if (stack->last_text_node != nullptr) {
17248448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski    stack->last_text_node->text.append(str.data(), str.size());
173ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski    return;
174ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
17575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
176ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  stack->last_text_node = util::make_unique<Text>();
177ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  stack->last_text_node->line_number = XML_GetCurrentLineNumber(parser);
178ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  stack->last_text_node->column_number = XML_GetCurrentColumnNumber(parser);
17948448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski  stack->last_text_node->text = str.to_string();
18075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
18175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
182ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL CommentDataHandler(void* user_data, const char* comment) {
183ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
184ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
185ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  FinishPendingText(stack);
18675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!stack->pending_comment.empty()) {
188ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    stack->pending_comment += '\n';
189ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
190ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  stack->pending_comment += comment;
19175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
19275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
193efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinskistd::unique_ptr<XmlResource> Inflate(InputStream* in, IDiagnostics* diag, const Source& source) {
194ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack stack;
195ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
196efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  std::unique_ptr<std::remove_pointer<XML_Parser>::type, decltype(XML_ParserFree)*> parser = {
197efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski      XML_ParserCreateNS(nullptr, kXmlNamespaceSep), XML_ParserFree};
198efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  XML_SetUserData(parser.get(), &stack);
199efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  XML_UseParserAsHandlerArg(parser.get());
200efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  XML_SetElementHandler(parser.get(), StartElementHandler, EndElementHandler);
201efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  XML_SetNamespaceDeclHandler(parser.get(), StartNamespaceHandler, EndNamespaceHandler);
202efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  XML_SetCharacterDataHandler(parser.get(), CharacterDataHandler);
203efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  XML_SetCommentHandler(parser.get(), CommentDataHandler);
204efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski
205efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  const char* buffer = nullptr;
206efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  size_t buffer_size = 0;
207efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  while (in->Next(reinterpret_cast<const void**>(&buffer), &buffer_size)) {
208efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski    if (XML_Parse(parser.get(), buffer, buffer_size, false) == XML_STATUS_ERROR) {
209efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski      diag->Error(DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser.get())))
210efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski                  << XML_ErrorString(XML_GetErrorCode(parser.get())));
211efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski      return {};
2121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
213ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
214ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
215efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  if (in->HadError()) {
216efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski    diag->Error(DiagMessage(source) << in->GetError());
217efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski    return {};
218efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  } else {
219efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski    // Finish off the parsing.
220efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski    if (XML_Parse(parser.get(), nullptr, 0u, true) == XML_STATUS_ERROR) {
221efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski      diag->Error(DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser.get())))
222efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski                  << XML_ErrorString(XML_GetErrorCode(parser.get())));
223efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski      return {};
224efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski    }
225ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
226efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  return util::make_unique<XmlResource>(ResourceFile{{}, {}, source}, StringPool{},
227efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski                                        std::move(stack.root));
22875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
22975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
230d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic void CopyAttributes(Element* el, android::ResXMLParser* parser, StringPool* out_pool) {
231ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const size_t attr_count = parser->getAttributeCount();
232ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (attr_count > 0) {
233ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    el->attributes.reserve(attr_count);
234ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (size_t i = 0; i < attr_count; i++) {
235ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      Attribute attr;
236ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      size_t len;
237ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      const char16_t* str16 = parser->getAttributeNamespace(i, &len);
238ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (str16) {
239ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        attr.namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
240ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
241ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
242ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      str16 = parser->getAttributeName(i, &len);
243ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (str16) {
244ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        attr.name = util::Utf16ToUtf8(StringPiece16(str16, len));
245ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
246ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
247ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      str16 = parser->getAttributeStringValue(i, &len);
248ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (str16) {
249ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        attr.value = util::Utf16ToUtf8(StringPiece16(str16, len));
250ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
251d0f492db038c6210c1138865d816bfb134376538Adam Lesinski
252d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      android::Res_value res_value;
253d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      if (parser->getAttributeValue(i, &res_value) > 0) {
254d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        attr.compiled_value = ResourceUtils::ParseBinaryResValue(
255d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            ResourceType::kAnim, {}, parser->getStrings(), res_value, out_pool);
256d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      }
257d0f492db038c6210c1138865d816bfb134376538Adam Lesinski
258ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      el->attributes.push_back(std::move(attr));
25975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
260ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
26175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
26275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
263d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistd::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len, IDiagnostics* diag,
264d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                     const Source& source) {
265ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // We import the android namespace because on Windows NO_ERROR is a macro, not
266ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // an enum, which
267ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // causes errors when qualifying it with android::
268ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  using namespace android;
269803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski
270d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  StringPool string_pool;
271ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<Node> root;
272ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::stack<Node*> node_stack;
27375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
274ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ResXMLTree tree;
275ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (tree.setTo(data, data_len) != NO_ERROR) {
276ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return {};
277ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
278ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
279ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ResXMLParser::event_code_t code;
280ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT &&
281ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski         code != ResXMLParser::END_DOCUMENT) {
282ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<Node> new_node;
283ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    switch (code) {
284ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::START_NAMESPACE: {
285ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        std::unique_ptr<Namespace> node = util::make_unique<Namespace>();
286ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        size_t len;
287ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const char16_t* str16 = tree.getNamespacePrefix(&len);
288ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
289ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          node->namespace_prefix = util::Utf16ToUtf8(StringPiece16(str16, len));
290ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
291ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
292ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        str16 = tree.getNamespaceUri(&len);
293ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
294ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          node->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
295ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
296ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        new_node = std::move(node);
297ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
298ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
299ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
300ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::START_TAG: {
301ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        std::unique_ptr<Element> node = util::make_unique<Element>();
302ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        size_t len;
303ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const char16_t* str16 = tree.getElementNamespace(&len);
304ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
305ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          node->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
306ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
30775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
308ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        str16 = tree.getElementName(&len);
309ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
310ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          node->name = util::Utf16ToUtf8(StringPiece16(str16, len));
31175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
31275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
313d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        CopyAttributes(node.get(), &tree, &string_pool);
314ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
315ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        new_node = std::move(node);
316ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
317ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
318ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
319ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::TEXT: {
320ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        std::unique_ptr<Text> node = util::make_unique<Text>();
321ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        size_t len;
322ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const char16_t* str16 = tree.getText(&len);
323ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
324ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          node->text = util::Utf16ToUtf8(StringPiece16(str16, len));
32575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
326ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        new_node = std::move(node);
327ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
328ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
329ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
330ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::END_NAMESPACE:
331ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::END_TAG:
332ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        CHECK(!node_stack.empty());
333ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        node_stack.pop();
334ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
335ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
336ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      default:
337ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        LOG(FATAL) << "unhandled XML chunk type";
338ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
33975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
34075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
341ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (new_node) {
342ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      new_node->line_number = tree.getLineNumber();
343ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
344ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      Node* this_node = new_node.get();
345ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!root) {
346ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        CHECK(node_stack.empty()) << "node stack should be empty";
347ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        root = std::move(new_node);
348ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      } else {
349ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        CHECK(!node_stack.empty()) << "node stack should not be empty";
350e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski        node_stack.top()->AppendChild(std::move(new_node));
351ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
352ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
353ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!NodeCast<Text>(this_node)) {
354ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        node_stack.push(this_node);
355ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
3565eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski    }
357ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
358ea134e08d70d156bdd17714d5f9ab9c44c91d4faAdam Lesinski  return util::make_unique<XmlResource>(ResourceFile{}, std::move(string_pool), std::move(root));
3595eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
3605eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
361c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskistd::unique_ptr<Node> Namespace::Clone(const ElementCloneFunc& el_cloner) {
362ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  auto ns = util::make_unique<Namespace>();
363ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ns->comment = comment;
364ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ns->line_number = line_number;
365ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ns->column_number = column_number;
366ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ns->namespace_prefix = namespace_prefix;
367ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ns->namespace_uri = namespace_uri;
368ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ns->children.reserve(children.size());
369ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const std::unique_ptr<xml::Node>& child : children) {
370c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    ns->AppendChild(child->Clone(el_cloner));
371ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
372ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return std::move(ns);
373467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski}
374467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
375ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* FindRootElement(XmlResource* doc) {
376ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return FindRootElement(doc->root.get());
377ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}
378ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski
379ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* FindRootElement(Node* node) {
380ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!node) {
381ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return nullptr;
382ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
383ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
384ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Element* el = nullptr;
385ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  while ((el = NodeCast<Element>(node)) == nullptr) {
386ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (node->children.empty()) {
387ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return nullptr;
388ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski    }
389ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    // We are looking for the first element, and namespaces can only have one
390ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    // child.
391ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    node = node->children.front().get();
392ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
393ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return el;
394ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski}
395ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski
396e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinskivoid Node::AppendChild(std::unique_ptr<Node> child) {
397ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  child->parent = this;
398ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  children.push_back(std::move(child));
39975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
40075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
401e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinskivoid Node::InsertChild(size_t index, std::unique_ptr<Node> child) {
402e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski  child->parent = this;
403e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski  children.insert(children.begin() + index, std::move(child));
404e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski}
405e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski
406ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiAttribute* Element::FindAttribute(const StringPiece& ns,
407ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                  const StringPiece& name) {
408ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (auto& attr : attributes) {
409ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (ns == attr.namespace_uri && name == attr.name) {
410ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return &attr;
41175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
412ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
413ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return nullptr;
41475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
41575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
416c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskiconst Attribute* Element::FindAttribute(const StringPiece& ns, const StringPiece& name) const {
417c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  for (const auto& attr : attributes) {
418c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    if (ns == attr.namespace_uri && name == attr.name) {
419c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      return &attr;
420c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    }
421c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  }
422c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  return nullptr;
423c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski}
424c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
425ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* Element::FindChild(const StringPiece& ns, const StringPiece& name) {
426ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return FindChildWithAttribute(ns, name, {}, {}, {});
42775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
42875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
429ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* Element::FindChildWithAttribute(const StringPiece& ns,
430ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                         const StringPiece& name,
431ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                         const StringPiece& attr_ns,
432ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                         const StringPiece& attr_name,
433ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                         const StringPiece& attr_value) {
434ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (auto& child_node : children) {
435ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    Node* child = child_node.get();
436ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    while (NodeCast<Namespace>(child)) {
437ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (child->children.empty()) {
438ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
439ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
440ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      child = child->children[0].get();
44175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
44275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
443ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (Element* el = NodeCast<Element>(child)) {
444ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (ns == el->namespace_uri && name == el->name) {
445ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (attr_ns.empty() && attr_name.empty()) {
446ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          return el;
44775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
44875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
449ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        Attribute* attr = el->FindAttribute(attr_ns, attr_name);
450ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (attr && attr_value == attr->value) {
451ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          return el;
45275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
453ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
45475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
455ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
456ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return nullptr;
45775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
45875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
459ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::vector<Element*> Element::GetChildElements() {
460ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<Element*> elements;
461ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (auto& child_node : children) {
462ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    Node* child = child_node.get();
463ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    while (NodeCast<Namespace>(child)) {
464ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (child->children.empty()) {
465ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
466ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
467ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      child = child->children[0].get();
4685eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski    }
4695eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
470ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (Element* el = NodeCast<Element>(child)) {
471ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      elements.push_back(el);
4725eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski    }
473ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
474ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return elements;
4755eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
4765eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
477c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskistd::unique_ptr<Node> Element::Clone(const ElementCloneFunc& el_cloner) {
478ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  auto el = util::make_unique<Element>();
479ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->comment = comment;
480ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->line_number = line_number;
481ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->column_number = column_number;
482ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->name = name;
483ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->namespace_uri = namespace_uri;
484ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->attributes.reserve(attributes.size());
485c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  el_cloner(*this, el.get());
486ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->children.reserve(children.size());
487ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const std::unique_ptr<xml::Node>& child : children) {
488c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    el->AppendChild(child->Clone(el_cloner));
489ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
490ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return std::move(el);
4915eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
4925eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
493c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskistd::unique_ptr<Node> Text::Clone(const ElementCloneFunc&) {
494ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  auto t = util::make_unique<Text>();
495ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->comment = comment;
496ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->line_number = line_number;
497ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->column_number = column_number;
498ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->text = text;
499ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return std::move(t);
500ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}
501467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
502ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskivoid PackageAwareVisitor::Visit(Namespace* ns) {
503ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool added = false;
504ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (Maybe<ExtractedPackage> maybe_package =
505ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          ExtractPackageFromNamespace(ns->namespace_uri)) {
506ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    ExtractedPackage& package = maybe_package.value();
507ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    package_decls_.push_back(
508ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        PackageDecl{ns->namespace_prefix, std::move(package)});
509ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    added = true;
510ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
511ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
512ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Visitor::Visit(ns);
513ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
514ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (added) {
515ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    package_decls_.pop_back();
516ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
517467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski}
518467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
519ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiMaybe<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias(
520ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const StringPiece& alias, const StringPiece& local_package) const {
521ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (alias.empty()) {
522d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski    return ExtractedPackage{local_package.to_string(), false /* private */};
523ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
524ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
525ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const auto rend = package_decls_.rend();
526ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (auto iter = package_decls_.rbegin(); iter != rend; ++iter) {
527ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (alias == iter->prefix) {
528ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (iter->package.package.empty()) {
529d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski        return ExtractedPackage{local_package.to_string(), iter->package.private_namespace};
530ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
531ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return iter->package;
532ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    }
533ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
534ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return {};
535467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski}
536467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
537ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}  // namespace xml
538ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}  // namespace aapt
539