1/* 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 17#ifndef AAPT_XML_DOM_H 18#define AAPT_XML_DOM_H 19 20#include "Diagnostics.h" 21#include "Resource.h" 22#include "ResourceValues.h" 23#include "util/StringPiece.h" 24#include "util/Util.h" 25#include "xml/XmlUtil.h" 26 27#include <istream> 28#include <memory> 29#include <string> 30#include <vector> 31 32namespace aapt { 33namespace xml { 34 35struct RawVisitor; 36 37/** 38 * Base class for all XML nodes. 39 */ 40struct Node { 41 Node* parent = nullptr; 42 size_t lineNumber = 0; 43 size_t columnNumber = 0; 44 std::u16string comment; 45 std::vector<std::unique_ptr<Node>> children; 46 47 virtual ~Node() = default; 48 49 void addChild(std::unique_ptr<Node> child); 50 virtual void accept(RawVisitor* visitor) = 0; 51}; 52 53/** 54 * Base class that implements the visitor methods for a 55 * subclass of Node. 56 */ 57template <typename Derived> 58struct BaseNode : public Node { 59 virtual void accept(RawVisitor* visitor) override; 60}; 61 62/** 63 * A Namespace XML node. Can only have one child. 64 */ 65struct Namespace : public BaseNode<Namespace> { 66 std::u16string namespacePrefix; 67 std::u16string namespaceUri; 68}; 69 70struct AaptAttribute { 71 Maybe<ResourceId> id; 72 aapt::Attribute attribute; 73}; 74 75/** 76 * An XML attribute. 77 */ 78struct Attribute { 79 std::u16string namespaceUri; 80 std::u16string name; 81 std::u16string value; 82 83 Maybe<AaptAttribute> compiledAttribute; 84 std::unique_ptr<Item> compiledValue; 85}; 86 87/** 88 * An Element XML node. 89 */ 90struct Element : public BaseNode<Element> { 91 std::u16string namespaceUri; 92 std::u16string name; 93 std::vector<Attribute> attributes; 94 95 Attribute* findAttribute(const StringPiece16& ns, const StringPiece16& name); 96 xml::Element* findChild(const StringPiece16& ns, const StringPiece16& name); 97 xml::Element* findChildWithAttribute(const StringPiece16& ns, const StringPiece16& name, 98 const StringPiece16& attrNs, 99 const StringPiece16& attrName, 100 const StringPiece16& attrValue); 101 std::vector<xml::Element*> getChildElements(); 102}; 103 104/** 105 * A Text (CDATA) XML node. Can not have any children. 106 */ 107struct Text : public BaseNode<Text> { 108 std::u16string text; 109}; 110 111/** 112 * An XML resource with a source, name, and XML tree. 113 */ 114struct XmlResource { 115 ResourceFile file; 116 std::unique_ptr<xml::Node> root; 117}; 118 119/** 120 * Inflates an XML DOM from a text stream, logging errors to the logger. 121 * Returns the root node on success, or nullptr on failure. 122 */ 123std::unique_ptr<XmlResource> inflate(std::istream* in, IDiagnostics* diag, const Source& source); 124 125/** 126 * Inflates an XML DOM from a binary ResXMLTree, logging errors to the logger. 127 * Returns the root node on success, or nullptr on failure. 128 */ 129std::unique_ptr<XmlResource> inflate(const void* data, size_t dataLen, IDiagnostics* diag, 130 const Source& source); 131 132Element* findRootElement(XmlResource* doc); 133Element* findRootElement(Node* node); 134 135/** 136 * A visitor interface for the different XML Node subtypes. This will not traverse into 137 * children. Use Visitor for that. 138 */ 139struct RawVisitor { 140 virtual ~RawVisitor() = default; 141 142 virtual void visit(Namespace* node) {} 143 virtual void visit(Element* node) {} 144 virtual void visit(Text* text) {} 145}; 146 147/** 148 * Visitor whose default implementation visits the children nodes of any node. 149 */ 150struct Visitor : public RawVisitor { 151 using RawVisitor::visit; 152 153 void visit(Namespace* node) override { 154 visitChildren(node); 155 } 156 157 void visit(Element* node) override { 158 visitChildren(node); 159 } 160 161 void visit(Text* text) override { 162 visitChildren(text); 163 } 164 165 void visitChildren(Node* node) { 166 for (auto& child : node->children) { 167 child->accept(this); 168 } 169 } 170}; 171 172/** 173 * An XML DOM visitor that will record the package name for a namespace prefix. 174 */ 175class PackageAwareVisitor : public Visitor, public IPackageDeclStack { 176private: 177 struct PackageDecl { 178 std::u16string prefix; 179 ExtractedPackage package; 180 }; 181 182 std::vector<PackageDecl> mPackageDecls; 183 184public: 185 using Visitor::visit; 186 187 void visit(Namespace* ns) override; 188 Maybe<ExtractedPackage> transformPackageAlias( 189 const StringPiece16& alias, const StringPiece16& localPackage) const override; 190}; 191 192// Implementations 193 194template <typename Derived> 195void BaseNode<Derived>::accept(RawVisitor* visitor) { 196 visitor->visit(static_cast<Derived*>(this)); 197} 198 199template <typename T> 200struct NodeCastImpl : public RawVisitor { 201 using RawVisitor::visit; 202 203 T* value = nullptr; 204 205 void visit(T* v) override { 206 value = v; 207 } 208}; 209 210template <typename T> 211T* nodeCast(Node* node) { 212 NodeCastImpl<T> visitor; 213 node->accept(&visitor); 214 return visitor.value; 215} 216 217} // namespace xml 218} // namespace aapt 219 220#endif // AAPT_XML_DOM_H 221