blob: 567418edf56ba68f77822c9c5e844ec7d874f66d [file] [log] [blame]
Adam Lesinski75f3a552015-06-03 14:54:23 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Adam Lesinski75f3a552015-06-03 14:54:23 -070017#include "XmlDom.h"
Adam Lesinskice5e56e2016-10-21 17:56:45 -070018
19#include <expat.h>
Adam Lesinski75f3a552015-06-03 14:54:23 -070020
21#include <cassert>
22#include <memory>
23#include <stack>
24#include <string>
25#include <tuple>
26
Adam Lesinskice5e56e2016-10-21 17:56:45 -070027#include "android-base/logging.h"
28
29#include "XmlPullParser.h"
30#include "util/Util.h"
31
Adam Lesinski75f3a552015-06-03 14:54:23 -070032namespace aapt {
33namespace xml {
34
35constexpr char kXmlNamespaceSep = 1;
36
37struct Stack {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070038 std::unique_ptr<xml::Node> root;
39 std::stack<xml::Node*> node_stack;
40 std::string pending_comment;
Adam Lesinski75f3a552015-06-03 14:54:23 -070041};
42
43/**
44 * Extracts the namespace and name of an expanded element or attribute name.
45 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -070046static void SplitName(const char* name, std::string* out_ns,
47 std::string* out_name) {
48 const char* p = name;
49 while (*p != 0 && *p != kXmlNamespaceSep) {
50 p++;
51 }
Adam Lesinski75f3a552015-06-03 14:54:23 -070052
Adam Lesinskice5e56e2016-10-21 17:56:45 -070053 if (*p == 0) {
54 out_ns->clear();
55 *out_name = StringPiece(name).ToString();
56 } else {
57 *out_ns = StringPiece(name, (p - name)).ToString();
58 *out_name = StringPiece(p + 1).ToString();
59 }
Adam Lesinski75f3a552015-06-03 14:54:23 -070060}
61
Adam Lesinskice5e56e2016-10-21 17:56:45 -070062static void AddToStack(Stack* stack, XML_Parser parser,
63 std::unique_ptr<Node> node) {
64 node->line_number = XML_GetCurrentLineNumber(parser);
65 node->column_number = XML_GetCurrentColumnNumber(parser);
Adam Lesinski75f3a552015-06-03 14:54:23 -070066
Adam Lesinskice5e56e2016-10-21 17:56:45 -070067 Node* this_node = node.get();
68 if (!stack->node_stack.empty()) {
69 stack->node_stack.top()->AddChild(std::move(node));
70 } else {
71 stack->root = std::move(node);
72 }
Adam Lesinski75f3a552015-06-03 14:54:23 -070073
Adam Lesinskice5e56e2016-10-21 17:56:45 -070074 if (!NodeCast<Text>(this_node)) {
75 stack->node_stack.push(this_node);
76 }
Adam Lesinski75f3a552015-06-03 14:54:23 -070077}
78
Adam Lesinskice5e56e2016-10-21 17:56:45 -070079static void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix,
80 const char* uri) {
81 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
82 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinski75f3a552015-06-03 14:54:23 -070083
Adam Lesinskice5e56e2016-10-21 17:56:45 -070084 std::unique_ptr<Namespace> ns = util::make_unique<Namespace>();
85 if (prefix) {
86 ns->namespace_prefix = StringPiece(prefix).ToString();
87 }
Adam Lesinski75f3a552015-06-03 14:54:23 -070088
Adam Lesinskice5e56e2016-10-21 17:56:45 -070089 if (uri) {
90 ns->namespace_uri = StringPiece(uri).ToString();
91 }
Adam Lesinski75f3a552015-06-03 14:54:23 -070092
Adam Lesinskice5e56e2016-10-21 17:56:45 -070093 AddToStack(stack, parser, std::move(ns));
Adam Lesinski75f3a552015-06-03 14:54:23 -070094}
95
Adam Lesinskice5e56e2016-10-21 17:56:45 -070096static void XMLCALL EndNamespaceHandler(void* user_data, const char* prefix) {
97 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
98 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinski75f3a552015-06-03 14:54:23 -070099
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700100 CHECK(!stack->node_stack.empty());
101 stack->node_stack.pop();
Adam Lesinski75f3a552015-06-03 14:54:23 -0700102}
103
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700104static bool less_attribute(const Attribute& lhs, const Attribute& rhs) {
105 return std::tie(lhs.namespace_uri, lhs.name, lhs.value) <
106 std::tie(rhs.namespace_uri, rhs.name, rhs.value);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700107}
108
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700109static void XMLCALL StartElementHandler(void* user_data, const char* name,
110 const char** attrs) {
111 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
112 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700113
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700114 std::unique_ptr<Element> el = util::make_unique<Element>();
115 SplitName(name, &el->namespace_uri, &el->name);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700116
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700117 while (*attrs) {
118 Attribute attribute;
119 SplitName(*attrs++, &attribute.namespace_uri, &attribute.name);
120 attribute.value = StringPiece(*attrs++).ToString();
Adam Lesinski75f3a552015-06-03 14:54:23 -0700121
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700122 // Insert in sorted order.
123 auto iter = std::lower_bound(el->attributes.begin(), el->attributes.end(),
124 attribute, less_attribute);
125 el->attributes.insert(iter, std::move(attribute));
126 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700127
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700128 el->comment = std::move(stack->pending_comment);
129 AddToStack(stack, parser, std::move(el));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700130}
131
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700132static void XMLCALL EndElementHandler(void* user_data, const char* name) {
133 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
134 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700135
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700136 CHECK(!stack->node_stack.empty());
137 // stack->nodeStack.top()->comment = std::move(stack->pendingComment);
138 stack->node_stack.pop();
Adam Lesinski75f3a552015-06-03 14:54:23 -0700139}
140
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700141static void XMLCALL CharacterDataHandler(void* user_data, const char* s,
142 int len) {
143 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
144 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700145
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700146 if (!s || len <= 0) {
147 return;
148 }
149
150 // See if we can just append the text to a previous text node.
151 if (!stack->node_stack.empty()) {
152 Node* currentParent = stack->node_stack.top();
153 if (!currentParent->children.empty()) {
154 Node* last_child = currentParent->children.back().get();
155 if (Text* text = NodeCast<Text>(last_child)) {
156 text->text += StringPiece(s, len).ToString();
Adam Lesinski75f3a552015-06-03 14:54:23 -0700157 return;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700158 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700159 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700160 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700161
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700162 std::unique_ptr<Text> text = util::make_unique<Text>();
163 text->text = StringPiece(s, len).ToString();
164 AddToStack(stack, parser, std::move(text));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700165}
166
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700167static void XMLCALL CommentDataHandler(void* user_data, const char* comment) {
168 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
169 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700170
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700171 if (!stack->pending_comment.empty()) {
172 stack->pending_comment += '\n';
173 }
174 stack->pending_comment += comment;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700175}
176
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700177std::unique_ptr<XmlResource> Inflate(std::istream* in, IDiagnostics* diag,
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700178 const Source& source) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700179 Stack stack;
Adam Lesinski803c7c82016-04-06 16:09:43 -0700180
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700181 XML_Parser parser = XML_ParserCreateNS(nullptr, kXmlNamespaceSep);
182 XML_SetUserData(parser, &stack);
183 XML_UseParserAsHandlerArg(parser);
184 XML_SetElementHandler(parser, StartElementHandler, EndElementHandler);
185 XML_SetNamespaceDeclHandler(parser, StartNamespaceHandler,
186 EndNamespaceHandler);
187 XML_SetCharacterDataHandler(parser, CharacterDataHandler);
188 XML_SetCommentHandler(parser, CommentDataHandler);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700189
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700190 char buffer[1024];
191 while (!in->eof()) {
192 in->read(buffer, sizeof(buffer) / sizeof(buffer[0]));
193 if (in->bad() && !in->eof()) {
194 stack.root = {};
195 diag->Error(DiagMessage(source) << strerror(errno));
196 break;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700197 }
198
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700199 if (XML_Parse(parser, buffer, in->gcount(), in->eof()) ==
200 XML_STATUS_ERROR) {
201 stack.root = {};
202 diag->Error(DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser)))
203 << XML_ErrorString(XML_GetErrorCode(parser)));
204 break;
205 }
206 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700207
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700208 XML_ParserFree(parser);
209 if (stack.root) {
210 return util::make_unique<XmlResource>(ResourceFile{{}, {}, source},
211 std::move(stack.root));
212 }
213 return {};
214}
Adam Lesinski75f3a552015-06-03 14:54:23 -0700215
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700216static void CopyAttributes(Element* el, android::ResXMLParser* parser) {
217 const size_t attr_count = parser->getAttributeCount();
218 if (attr_count > 0) {
219 el->attributes.reserve(attr_count);
220 for (size_t i = 0; i < attr_count; i++) {
221 Attribute attr;
222 size_t len;
223 const char16_t* str16 = parser->getAttributeNamespace(i, &len);
224 if (str16) {
225 attr.namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
226 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700227
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700228 str16 = parser->getAttributeName(i, &len);
229 if (str16) {
230 attr.name = util::Utf16ToUtf8(StringPiece16(str16, len));
231 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700232
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700233 str16 = parser->getAttributeStringValue(i, &len);
234 if (str16) {
235 attr.value = util::Utf16ToUtf8(StringPiece16(str16, len));
236 }
237 el->attributes.push_back(std::move(attr));
238 }
239 }
240}
Adam Lesinski75f3a552015-06-03 14:54:23 -0700241
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700242std::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len,
243 IDiagnostics* diag, const Source& source) {
244 // We import the android namespace because on Windows NO_ERROR is a macro, not
245 // an enum, which
246 // causes errors when qualifying it with android::
247 using namespace android;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700248
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700249 std::unique_ptr<Node> root;
250 std::stack<Node*> node_stack;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700251
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700252 ResXMLTree tree;
253 if (tree.setTo(data, data_len) != NO_ERROR) {
254 return {};
255 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700256
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700257 ResXMLParser::event_code_t code;
258 while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT &&
259 code != ResXMLParser::END_DOCUMENT) {
260 std::unique_ptr<Node> new_node;
261 switch (code) {
262 case ResXMLParser::START_NAMESPACE: {
263 std::unique_ptr<Namespace> node = util::make_unique<Namespace>();
264 size_t len;
265 const char16_t* str16 = tree.getNamespacePrefix(&len);
266 if (str16) {
267 node->namespace_prefix = util::Utf16ToUtf8(StringPiece16(str16, len));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700268 }
269
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700270 str16 = tree.getNamespaceUri(&len);
271 if (str16) {
272 node->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700273 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700274 new_node = std::move(node);
275 break;
276 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700277
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700278 case ResXMLParser::START_TAG: {
279 std::unique_ptr<Element> node = util::make_unique<Element>();
280 size_t len;
281 const char16_t* str16 = tree.getElementNamespace(&len);
282 if (str16) {
283 node->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
Adam Lesinskica5638f2015-10-21 14:42:43 -0700284 }
Adam Lesinskica5638f2015-10-21 14:42:43 -0700285
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700286 str16 = tree.getElementName(&len);
287 if (str16) {
288 node->name = util::Utf16ToUtf8(StringPiece16(str16, len));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700289 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700290
291 CopyAttributes(node.get(), &tree);
292
293 new_node = std::move(node);
294 break;
295 }
296
297 case ResXMLParser::TEXT: {
298 std::unique_ptr<Text> node = util::make_unique<Text>();
299 size_t len;
300 const char16_t* str16 = tree.getText(&len);
301 if (str16) {
302 node->text = util::Utf16ToUtf8(StringPiece16(str16, len));
303 }
304 new_node = std::move(node);
305 break;
306 }
307
308 case ResXMLParser::END_NAMESPACE:
309 case ResXMLParser::END_TAG:
310 CHECK(!node_stack.empty());
311 node_stack.pop();
312 break;
313
314 default:
315 LOG(FATAL) << "unhandled XML chunk type";
316 break;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700317 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700318
319 if (new_node) {
320 new_node->line_number = tree.getLineNumber();
321
322 Node* this_node = new_node.get();
323 if (!root) {
324 CHECK(node_stack.empty()) << "node stack should be empty";
325 root = std::move(new_node);
326 } else {
327 CHECK(!node_stack.empty()) << "node stack should not be empty";
328 node_stack.top()->AddChild(std::move(new_node));
329 }
330
331 if (!NodeCast<Text>(this_node)) {
332 node_stack.push(this_node);
333 }
334 }
335 }
336 return util::make_unique<XmlResource>(ResourceFile{}, std::move(root));
337}
338
339std::unique_ptr<Node> Namespace::Clone() {
340 auto ns = util::make_unique<Namespace>();
341 ns->comment = comment;
342 ns->line_number = line_number;
343 ns->column_number = column_number;
344 ns->namespace_prefix = namespace_prefix;
345 ns->namespace_uri = namespace_uri;
346
347 ns->children.reserve(children.size());
348 for (const std::unique_ptr<xml::Node>& child : children) {
349 ns->AddChild(child->Clone());
350 }
351 return std::move(ns);
352}
353
354Element* FindRootElement(XmlResource* doc) {
355 return FindRootElement(doc->root.get());
356}
357
358Element* FindRootElement(Node* node) {
359 if (!node) {
Adam Lesinski75f3a552015-06-03 14:54:23 -0700360 return nullptr;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700361 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700362
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700363 Element* el = nullptr;
364 while ((el = NodeCast<Element>(node)) == nullptr) {
365 if (node->children.empty()) {
366 return nullptr;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700367 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700368 // We are looking for the first element, and namespaces can only have one
369 // child.
370 node = node->children.front().get();
371 }
372 return el;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700373}
374
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700375void Node::AddChild(std::unique_ptr<Node> child) {
376 child->parent = this;
377 children.push_back(std::move(child));
378}
Adam Lesinski75f3a552015-06-03 14:54:23 -0700379
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700380Attribute* Element::FindAttribute(const StringPiece& ns,
381 const StringPiece& name) {
382 for (auto& attr : attributes) {
383 if (ns == attr.namespace_uri && name == attr.name) {
384 return &attr;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700385 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700386 }
387 return nullptr;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700388}
389
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700390Element* Element::FindChild(const StringPiece& ns, const StringPiece& name) {
391 return FindChildWithAttribute(ns, name, {}, {}, {});
392}
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700393
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700394Element* Element::FindChildWithAttribute(const StringPiece& ns,
395 const StringPiece& name,
396 const StringPiece& attr_ns,
397 const StringPiece& attr_name,
398 const StringPiece& attr_value) {
399 for (auto& child_node : children) {
400 Node* child = child_node.get();
401 while (NodeCast<Namespace>(child)) {
402 if (child->children.empty()) {
403 break;
404 }
405 child = child->children[0].get();
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700406 }
407
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700408 if (Element* el = NodeCast<Element>(child)) {
409 if (ns == el->namespace_uri && name == el->name) {
410 if (attr_ns.empty() && attr_name.empty()) {
411 return el;
412 }
413
414 Attribute* attr = el->FindAttribute(attr_ns, attr_name);
415 if (attr && attr_value == attr->value) {
416 return el;
417 }
418 }
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700419 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700420 }
421 return nullptr;
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700422}
423
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700424std::vector<Element*> Element::GetChildElements() {
425 std::vector<Element*> elements;
426 for (auto& child_node : children) {
427 Node* child = child_node.get();
428 while (NodeCast<Namespace>(child)) {
429 if (child->children.empty()) {
430 break;
431 }
432 child = child->children[0].get();
433 }
434
435 if (Element* el = NodeCast<Element>(child)) {
436 elements.push_back(el);
437 }
438 }
439 return elements;
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700440}
441
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700442std::unique_ptr<Node> Element::Clone() {
443 auto el = util::make_unique<Element>();
444 el->comment = comment;
445 el->line_number = line_number;
446 el->column_number = column_number;
447 el->name = name;
448 el->namespace_uri = namespace_uri;
Adam Lesinski467f1712015-11-16 17:35:44 -0800449
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700450 el->attributes.reserve(attributes.size());
451 for (xml::Attribute& attr : attributes) {
452 // Don't copy compiled values or attributes.
453 el->attributes.push_back(
454 xml::Attribute{attr.namespace_uri, attr.name, attr.value});
455 }
Adam Lesinski467f1712015-11-16 17:35:44 -0800456
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700457 el->children.reserve(children.size());
458 for (const std::unique_ptr<xml::Node>& child : children) {
459 el->AddChild(child->Clone());
460 }
461 return std::move(el);
Adam Lesinski467f1712015-11-16 17:35:44 -0800462}
463
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700464std::unique_ptr<Node> Text::Clone() {
465 auto t = util::make_unique<Text>();
466 t->comment = comment;
467 t->line_number = line_number;
468 t->column_number = column_number;
469 t->text = text;
470 return std::move(t);
Adam Lesinski467f1712015-11-16 17:35:44 -0800471}
472
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700473void PackageAwareVisitor::Visit(Namespace* ns) {
474 bool added = false;
475 if (Maybe<ExtractedPackage> maybe_package =
476 ExtractPackageFromNamespace(ns->namespace_uri)) {
477 ExtractedPackage& package = maybe_package.value();
478 package_decls_.push_back(
479 PackageDecl{ns->namespace_prefix, std::move(package)});
480 added = true;
481 }
482
483 Visitor::Visit(ns);
484
485 if (added) {
486 package_decls_.pop_back();
487 }
488}
489
490Maybe<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias(
491 const StringPiece& alias, const StringPiece& local_package) const {
492 if (alias.empty()) {
493 return ExtractedPackage{local_package.ToString(), false /* private */};
494 }
495
496 const auto rend = package_decls_.rend();
497 for (auto iter = package_decls_.rbegin(); iter != rend; ++iter) {
498 if (alias == iter->prefix) {
499 if (iter->package.package.empty()) {
500 return ExtractedPackage{local_package.ToString(),
501 iter->package.private_namespace};
502 }
503 return iter->package;
504 }
505 }
506 return {};
507}
508
509} // namespace xml
510} // namespace aapt