Home | History | Annotate | Download | only in xml
      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 
     32 namespace aapt {
     33 namespace xml {
     34 
     35 struct RawVisitor;
     36 
     37 /**
     38  * Base class for all XML nodes.
     39  */
     40 struct 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  */
     57 template <typename Derived>
     58 struct BaseNode : public Node {
     59     virtual void accept(RawVisitor* visitor) override;
     60 };
     61 
     62 /**
     63  * A Namespace XML node. Can only have one child.
     64  */
     65 struct Namespace : public BaseNode<Namespace> {
     66     std::u16string namespacePrefix;
     67     std::u16string namespaceUri;
     68 };
     69 
     70 struct AaptAttribute {
     71     Maybe<ResourceId> id;
     72     aapt::Attribute attribute;
     73 };
     74 
     75 /**
     76  * An XML attribute.
     77  */
     78 struct 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  */
     90 struct 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  */
    107 struct Text : public BaseNode<Text> {
    108     std::u16string text;
    109 };
    110 
    111 /**
    112  * An XML resource with a source, name, and XML tree.
    113  */
    114 struct 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  */
    123 std::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  */
    129 std::unique_ptr<XmlResource> inflate(const void* data, size_t dataLen, IDiagnostics* diag,
    130                                      const Source& source);
    131 
    132 Element* findRootElement(XmlResource* doc);
    133 Element* 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  */
    139 struct 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  */
    150 struct 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  */
    175 class PackageAwareVisitor : public Visitor, public IPackageDeclStack {
    176 private:
    177     struct PackageDecl {
    178         std::u16string prefix;
    179         ExtractedPackage package;
    180     };
    181 
    182     std::vector<PackageDecl> mPackageDecls;
    183 
    184 public:
    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 
    194 template <typename Derived>
    195 void BaseNode<Derived>::accept(RawVisitor* visitor) {
    196     visitor->visit(static_cast<Derived*>(this));
    197 }
    198 
    199 template <typename T>
    200 struct 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 
    210 template <typename T>
    211 T* 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