blob: fab2f19fc0acdba07e08e21d4c4b6ab44fa874a2 [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 Lesinskid5083f62017-01-16 15:07:21 -080032using android::StringPiece;
33using android::StringPiece16;
34
Adam Lesinski75f3a552015-06-03 14:54:23 -070035namespace aapt {
36namespace xml {
37
38constexpr char kXmlNamespaceSep = 1;
39
40struct Stack {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070041 std::unique_ptr<xml::Node> root;
42 std::stack<xml::Node*> node_stack;
43 std::string pending_comment;
Adam Lesinski75f3a552015-06-03 14:54:23 -070044};
45
46/**
47 * Extracts the namespace and name of an expanded element or attribute name.
48 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -070049static void SplitName(const char* name, std::string* out_ns,
50 std::string* out_name) {
51 const char* p = name;
52 while (*p != 0 && *p != kXmlNamespaceSep) {
53 p++;
54 }
Adam Lesinski75f3a552015-06-03 14:54:23 -070055
Adam Lesinskice5e56e2016-10-21 17:56:45 -070056 if (*p == 0) {
57 out_ns->clear();
Adam Lesinskid5083f62017-01-16 15:07:21 -080058 out_name->assign(name);
Adam Lesinskice5e56e2016-10-21 17:56:45 -070059 } else {
Adam Lesinskid5083f62017-01-16 15:07:21 -080060 out_ns->assign(name, (p - name));
61 out_name->assign(p + 1);
Adam Lesinskice5e56e2016-10-21 17:56:45 -070062 }
Adam Lesinski75f3a552015-06-03 14:54:23 -070063}
64
Adam Lesinskice5e56e2016-10-21 17:56:45 -070065static void AddToStack(Stack* stack, XML_Parser parser,
66 std::unique_ptr<Node> node) {
67 node->line_number = XML_GetCurrentLineNumber(parser);
68 node->column_number = XML_GetCurrentColumnNumber(parser);
Adam Lesinski75f3a552015-06-03 14:54:23 -070069
Adam Lesinskice5e56e2016-10-21 17:56:45 -070070 Node* this_node = node.get();
71 if (!stack->node_stack.empty()) {
Adam Lesinskie343eb12016-10-27 16:31:58 -070072 stack->node_stack.top()->AppendChild(std::move(node));
Adam Lesinskice5e56e2016-10-21 17:56:45 -070073 } else {
74 stack->root = std::move(node);
75 }
Adam Lesinski75f3a552015-06-03 14:54:23 -070076
Adam Lesinskice5e56e2016-10-21 17:56:45 -070077 if (!NodeCast<Text>(this_node)) {
78 stack->node_stack.push(this_node);
79 }
Adam Lesinski75f3a552015-06-03 14:54:23 -070080}
81
Adam Lesinskice5e56e2016-10-21 17:56:45 -070082static void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix,
83 const char* uri) {
84 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
85 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinski75f3a552015-06-03 14:54:23 -070086
Adam Lesinskice5e56e2016-10-21 17:56:45 -070087 std::unique_ptr<Namespace> ns = util::make_unique<Namespace>();
88 if (prefix) {
Adam Lesinskid5083f62017-01-16 15:07:21 -080089 ns->namespace_prefix = prefix;
Adam Lesinskice5e56e2016-10-21 17:56:45 -070090 }
Adam Lesinski75f3a552015-06-03 14:54:23 -070091
Adam Lesinskice5e56e2016-10-21 17:56:45 -070092 if (uri) {
Adam Lesinskid5083f62017-01-16 15:07:21 -080093 ns->namespace_uri = uri;
Adam Lesinskice5e56e2016-10-21 17:56:45 -070094 }
Adam Lesinski75f3a552015-06-03 14:54:23 -070095
Adam Lesinskice5e56e2016-10-21 17:56:45 -070096 AddToStack(stack, parser, std::move(ns));
Adam Lesinski75f3a552015-06-03 14:54:23 -070097}
98
Adam Lesinskice5e56e2016-10-21 17:56:45 -070099static void XMLCALL EndNamespaceHandler(void* user_data, const char* prefix) {
100 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
101 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700102
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700103 CHECK(!stack->node_stack.empty());
104 stack->node_stack.pop();
Adam Lesinski75f3a552015-06-03 14:54:23 -0700105}
106
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700107static bool less_attribute(const Attribute& lhs, const Attribute& rhs) {
108 return std::tie(lhs.namespace_uri, lhs.name, lhs.value) <
109 std::tie(rhs.namespace_uri, rhs.name, rhs.value);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700110}
111
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700112static void XMLCALL StartElementHandler(void* user_data, const char* name,
113 const char** attrs) {
114 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
115 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700116
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700117 std::unique_ptr<Element> el = util::make_unique<Element>();
118 SplitName(name, &el->namespace_uri, &el->name);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700119
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700120 while (*attrs) {
121 Attribute attribute;
122 SplitName(*attrs++, &attribute.namespace_uri, &attribute.name);
Adam Lesinskid5083f62017-01-16 15:07:21 -0800123 attribute.value = *attrs++;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700124
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700125 // Insert in sorted order.
126 auto iter = std::lower_bound(el->attributes.begin(), el->attributes.end(),
127 attribute, less_attribute);
128 el->attributes.insert(iter, std::move(attribute));
129 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700130
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700131 el->comment = std::move(stack->pending_comment);
132 AddToStack(stack, parser, std::move(el));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700133}
134
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700135static void XMLCALL EndElementHandler(void* user_data, const char* name) {
136 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
137 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700138
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700139 CHECK(!stack->node_stack.empty());
140 // stack->nodeStack.top()->comment = std::move(stack->pendingComment);
141 stack->node_stack.pop();
Adam Lesinski75f3a552015-06-03 14:54:23 -0700142}
143
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700144static void XMLCALL CharacterDataHandler(void* user_data, const char* s,
145 int len) {
146 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
147 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700148
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700149 if (!s || len <= 0) {
150 return;
151 }
152
153 // See if we can just append the text to a previous text node.
154 if (!stack->node_stack.empty()) {
155 Node* currentParent = stack->node_stack.top();
156 if (!currentParent->children.empty()) {
157 Node* last_child = currentParent->children.back().get();
158 if (Text* text = NodeCast<Text>(last_child)) {
Adam Lesinskid5083f62017-01-16 15:07:21 -0800159 text->text.append(s, len);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700160 return;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700161 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700162 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700163 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700164
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700165 std::unique_ptr<Text> text = util::make_unique<Text>();
Adam Lesinskid5083f62017-01-16 15:07:21 -0800166 text->text.assign(s, len);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700167 AddToStack(stack, parser, std::move(text));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700168}
169
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700170static void XMLCALL CommentDataHandler(void* user_data, const char* comment) {
171 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
172 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700173
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700174 if (!stack->pending_comment.empty()) {
175 stack->pending_comment += '\n';
176 }
177 stack->pending_comment += comment;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700178}
179
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700180std::unique_ptr<XmlResource> Inflate(std::istream* in, IDiagnostics* diag,
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700181 const Source& source) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700182 Stack stack;
Adam Lesinski803c7c82016-04-06 16:09:43 -0700183
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700184 XML_Parser parser = XML_ParserCreateNS(nullptr, kXmlNamespaceSep);
185 XML_SetUserData(parser, &stack);
186 XML_UseParserAsHandlerArg(parser);
187 XML_SetElementHandler(parser, StartElementHandler, EndElementHandler);
188 XML_SetNamespaceDeclHandler(parser, StartNamespaceHandler,
189 EndNamespaceHandler);
190 XML_SetCharacterDataHandler(parser, CharacterDataHandler);
191 XML_SetCommentHandler(parser, CommentDataHandler);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700192
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700193 char buffer[1024];
194 while (!in->eof()) {
195 in->read(buffer, sizeof(buffer) / sizeof(buffer[0]));
196 if (in->bad() && !in->eof()) {
197 stack.root = {};
198 diag->Error(DiagMessage(source) << strerror(errno));
199 break;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700200 }
201
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700202 if (XML_Parse(parser, buffer, in->gcount(), in->eof()) ==
203 XML_STATUS_ERROR) {
204 stack.root = {};
205 diag->Error(DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser)))
206 << XML_ErrorString(XML_GetErrorCode(parser)));
207 break;
208 }
209 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700210
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700211 XML_ParserFree(parser);
212 if (stack.root) {
213 return util::make_unique<XmlResource>(ResourceFile{{}, {}, source},
214 std::move(stack.root));
215 }
216 return {};
217}
Adam Lesinski75f3a552015-06-03 14:54:23 -0700218
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700219static void CopyAttributes(Element* el, android::ResXMLParser* parser) {
220 const size_t attr_count = parser->getAttributeCount();
221 if (attr_count > 0) {
222 el->attributes.reserve(attr_count);
223 for (size_t i = 0; i < attr_count; i++) {
224 Attribute attr;
225 size_t len;
226 const char16_t* str16 = parser->getAttributeNamespace(i, &len);
227 if (str16) {
228 attr.namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
229 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700230
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700231 str16 = parser->getAttributeName(i, &len);
232 if (str16) {
233 attr.name = util::Utf16ToUtf8(StringPiece16(str16, len));
234 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700235
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700236 str16 = parser->getAttributeStringValue(i, &len);
237 if (str16) {
238 attr.value = util::Utf16ToUtf8(StringPiece16(str16, len));
239 }
240 el->attributes.push_back(std::move(attr));
241 }
242 }
243}
Adam Lesinski75f3a552015-06-03 14:54:23 -0700244
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700245std::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len,
246 IDiagnostics* diag, const Source& source) {
247 // We import the android namespace because on Windows NO_ERROR is a macro, not
248 // an enum, which
249 // causes errors when qualifying it with android::
250 using namespace android;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700251
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700252 std::unique_ptr<Node> root;
253 std::stack<Node*> node_stack;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700254
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700255 ResXMLTree tree;
256 if (tree.setTo(data, data_len) != NO_ERROR) {
257 return {};
258 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700259
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700260 ResXMLParser::event_code_t code;
261 while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT &&
262 code != ResXMLParser::END_DOCUMENT) {
263 std::unique_ptr<Node> new_node;
264 switch (code) {
265 case ResXMLParser::START_NAMESPACE: {
266 std::unique_ptr<Namespace> node = util::make_unique<Namespace>();
267 size_t len;
268 const char16_t* str16 = tree.getNamespacePrefix(&len);
269 if (str16) {
270 node->namespace_prefix = util::Utf16ToUtf8(StringPiece16(str16, len));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700271 }
272
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700273 str16 = tree.getNamespaceUri(&len);
274 if (str16) {
275 node->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700276 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700277 new_node = std::move(node);
278 break;
279 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700280
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700281 case ResXMLParser::START_TAG: {
282 std::unique_ptr<Element> node = util::make_unique<Element>();
283 size_t len;
284 const char16_t* str16 = tree.getElementNamespace(&len);
285 if (str16) {
286 node->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
Adam Lesinskica5638f2015-10-21 14:42:43 -0700287 }
Adam Lesinskica5638f2015-10-21 14:42:43 -0700288
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700289 str16 = tree.getElementName(&len);
290 if (str16) {
291 node->name = util::Utf16ToUtf8(StringPiece16(str16, len));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700292 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700293
294 CopyAttributes(node.get(), &tree);
295
296 new_node = std::move(node);
297 break;
298 }
299
300 case ResXMLParser::TEXT: {
301 std::unique_ptr<Text> node = util::make_unique<Text>();
302 size_t len;
303 const char16_t* str16 = tree.getText(&len);
304 if (str16) {
305 node->text = util::Utf16ToUtf8(StringPiece16(str16, len));
306 }
307 new_node = std::move(node);
308 break;
309 }
310
311 case ResXMLParser::END_NAMESPACE:
312 case ResXMLParser::END_TAG:
313 CHECK(!node_stack.empty());
314 node_stack.pop();
315 break;
316
317 default:
318 LOG(FATAL) << "unhandled XML chunk type";
319 break;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700320 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700321
322 if (new_node) {
323 new_node->line_number = tree.getLineNumber();
324
325 Node* this_node = new_node.get();
326 if (!root) {
327 CHECK(node_stack.empty()) << "node stack should be empty";
328 root = std::move(new_node);
329 } else {
330 CHECK(!node_stack.empty()) << "node stack should not be empty";
Adam Lesinskie343eb12016-10-27 16:31:58 -0700331 node_stack.top()->AppendChild(std::move(new_node));
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700332 }
333
334 if (!NodeCast<Text>(this_node)) {
335 node_stack.push(this_node);
336 }
337 }
338 }
339 return util::make_unique<XmlResource>(ResourceFile{}, std::move(root));
340}
341
342std::unique_ptr<Node> Namespace::Clone() {
343 auto ns = util::make_unique<Namespace>();
344 ns->comment = comment;
345 ns->line_number = line_number;
346 ns->column_number = column_number;
347 ns->namespace_prefix = namespace_prefix;
348 ns->namespace_uri = namespace_uri;
349
350 ns->children.reserve(children.size());
351 for (const std::unique_ptr<xml::Node>& child : children) {
Adam Lesinskie343eb12016-10-27 16:31:58 -0700352 ns->AppendChild(child->Clone());
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700353 }
354 return std::move(ns);
355}
356
357Element* FindRootElement(XmlResource* doc) {
358 return FindRootElement(doc->root.get());
359}
360
361Element* FindRootElement(Node* node) {
362 if (!node) {
Adam Lesinski75f3a552015-06-03 14:54:23 -0700363 return nullptr;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700364 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700365
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700366 Element* el = nullptr;
367 while ((el = NodeCast<Element>(node)) == nullptr) {
368 if (node->children.empty()) {
369 return nullptr;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700370 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700371 // We are looking for the first element, and namespaces can only have one
372 // child.
373 node = node->children.front().get();
374 }
375 return el;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700376}
377
Adam Lesinskie343eb12016-10-27 16:31:58 -0700378void Node::AppendChild(std::unique_ptr<Node> child) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700379 child->parent = this;
380 children.push_back(std::move(child));
381}
Adam Lesinski75f3a552015-06-03 14:54:23 -0700382
Adam Lesinskie343eb12016-10-27 16:31:58 -0700383void Node::InsertChild(size_t index, std::unique_ptr<Node> child) {
384 child->parent = this;
385 children.insert(children.begin() + index, std::move(child));
386}
387
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700388Attribute* Element::FindAttribute(const StringPiece& ns,
389 const StringPiece& name) {
390 for (auto& attr : attributes) {
391 if (ns == attr.namespace_uri && name == attr.name) {
392 return &attr;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700393 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700394 }
395 return nullptr;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700396}
397
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700398Element* Element::FindChild(const StringPiece& ns, const StringPiece& name) {
399 return FindChildWithAttribute(ns, name, {}, {}, {});
400}
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700401
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700402Element* Element::FindChildWithAttribute(const StringPiece& ns,
403 const StringPiece& name,
404 const StringPiece& attr_ns,
405 const StringPiece& attr_name,
406 const StringPiece& attr_value) {
407 for (auto& child_node : children) {
408 Node* child = child_node.get();
409 while (NodeCast<Namespace>(child)) {
410 if (child->children.empty()) {
411 break;
412 }
413 child = child->children[0].get();
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700414 }
415
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700416 if (Element* el = NodeCast<Element>(child)) {
417 if (ns == el->namespace_uri && name == el->name) {
418 if (attr_ns.empty() && attr_name.empty()) {
419 return el;
420 }
421
422 Attribute* attr = el->FindAttribute(attr_ns, attr_name);
423 if (attr && attr_value == attr->value) {
424 return el;
425 }
426 }
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700427 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700428 }
429 return nullptr;
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700430}
431
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700432std::vector<Element*> Element::GetChildElements() {
433 std::vector<Element*> elements;
434 for (auto& child_node : children) {
435 Node* child = child_node.get();
436 while (NodeCast<Namespace>(child)) {
437 if (child->children.empty()) {
438 break;
439 }
440 child = child->children[0].get();
441 }
442
443 if (Element* el = NodeCast<Element>(child)) {
444 elements.push_back(el);
445 }
446 }
447 return elements;
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700448}
449
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700450std::unique_ptr<Node> Element::Clone() {
451 auto el = util::make_unique<Element>();
452 el->comment = comment;
453 el->line_number = line_number;
454 el->column_number = column_number;
455 el->name = name;
456 el->namespace_uri = namespace_uri;
Adam Lesinski467f1712015-11-16 17:35:44 -0800457
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700458 el->attributes.reserve(attributes.size());
459 for (xml::Attribute& attr : attributes) {
460 // Don't copy compiled values or attributes.
461 el->attributes.push_back(
462 xml::Attribute{attr.namespace_uri, attr.name, attr.value});
463 }
Adam Lesinski467f1712015-11-16 17:35:44 -0800464
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700465 el->children.reserve(children.size());
466 for (const std::unique_ptr<xml::Node>& child : children) {
Adam Lesinskie343eb12016-10-27 16:31:58 -0700467 el->AppendChild(child->Clone());
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700468 }
469 return std::move(el);
Adam Lesinski467f1712015-11-16 17:35:44 -0800470}
471
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700472std::unique_ptr<Node> Text::Clone() {
473 auto t = util::make_unique<Text>();
474 t->comment = comment;
475 t->line_number = line_number;
476 t->column_number = column_number;
477 t->text = text;
478 return std::move(t);
Adam Lesinski467f1712015-11-16 17:35:44 -0800479}
480
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700481void PackageAwareVisitor::Visit(Namespace* ns) {
482 bool added = false;
483 if (Maybe<ExtractedPackage> maybe_package =
484 ExtractPackageFromNamespace(ns->namespace_uri)) {
485 ExtractedPackage& package = maybe_package.value();
486 package_decls_.push_back(
487 PackageDecl{ns->namespace_prefix, std::move(package)});
488 added = true;
489 }
490
491 Visitor::Visit(ns);
492
493 if (added) {
494 package_decls_.pop_back();
495 }
496}
497
498Maybe<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias(
499 const StringPiece& alias, const StringPiece& local_package) const {
500 if (alias.empty()) {
Adam Lesinskid5083f62017-01-16 15:07:21 -0800501 return ExtractedPackage{local_package.to_string(), false /* private */};
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700502 }
503
504 const auto rend = package_decls_.rend();
505 for (auto iter = package_decls_.rbegin(); iter != rend; ++iter) {
506 if (alias == iter->prefix) {
507 if (iter->package.package.empty()) {
Adam Lesinskid5083f62017-01-16 15:07:21 -0800508 return ExtractedPackage{local_package.to_string(), iter->package.private_namespace};
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700509 }
510 return iter->package;
511 }
512 }
513 return {};
514}
515
516} // namespace xml
517} // namespace aapt