XmlDom.h revision 5eeaaddffd23d8d85aeb321e3ceea626e42cf9de
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#ifndef AAPT_XML_DOM_H
1875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#define AAPT_XML_DOM_H
1975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "Diagnostics.h"
211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "Resource.h"
221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "ResourceValues.h"
231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/StringPiece.h"
241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/Util.h"
25467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "xml/XmlUtil.h"
2675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
2775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <istream>
2875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <memory>
2975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <string>
3075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <vector>
3175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
3275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace aapt {
3375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace xml {
3475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
355eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskiclass RawVisitor;
3675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
3775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/**
3875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Base class for all XML nodes.
3975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
405eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskiclass Node {
415eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskipublic:
421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    Node* parent = nullptr;
431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    size_t lineNumber = 0;
441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    size_t columnNumber = 0;
45d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinski    std::string comment;
4675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    std::vector<std::unique_ptr<Node>> children;
4775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
48467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski    virtual ~Node() = default;
49467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
5075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    void addChild(std::unique_ptr<Node> child);
511ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    virtual void accept(RawVisitor* visitor) = 0;
525eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski    virtual std::unique_ptr<Node> clone() = 0;
5375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski};
5475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
5575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/**
5675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Base class that implements the visitor methods for a
5775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * subclass of Node.
5875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
5975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskitemplate <typename Derived>
605eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskiclass BaseNode : public Node {
615eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskipublic:
621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    virtual void accept(RawVisitor* visitor) override;
6375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski};
6475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
6575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/**
6675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * A Namespace XML node. Can only have one child.
6775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
685eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskiclass Namespace : public BaseNode<Namespace> {
695eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskipublic:
70d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinski    std::string namespacePrefix;
71d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinski    std::string namespaceUri;
725eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
735eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski    std::unique_ptr<Node> clone() override;
741ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
7575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
761ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistruct AaptAttribute {
7764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski    Maybe<ResourceId> id;
781ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    aapt::Attribute attribute;
7975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski};
8075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
8175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/**
8275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * An XML attribute.
8375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
8475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistruct Attribute {
85d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinski    std::string namespaceUri;
86d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinski    std::string name;
87d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinski    std::string value;
881ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
891ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    Maybe<AaptAttribute> compiledAttribute;
901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    std::unique_ptr<Item> compiledValue;
9175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski};
9275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
9375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/**
9475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * An Element XML node.
9575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
965eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskiclass Element : public BaseNode<Element> {
975eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskipublic:
98d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinski    std::string namespaceUri;
99d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinski    std::string name;
10075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    std::vector<Attribute> attributes;
10175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
102d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinski    Attribute* findAttribute(const StringPiece& ns, const StringPiece& name);
103d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinski    xml::Element* findChild(const StringPiece& ns, const StringPiece& name);
104d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinski    xml::Element* findChildWithAttribute(const StringPiece& ns, const StringPiece& name,
105d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinski                                         const StringPiece& attrNs,
106d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinski                                         const StringPiece& attrName,
107d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinski                                         const StringPiece& attrValue);
10875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    std::vector<xml::Element*> getChildElements();
1095eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski    std::unique_ptr<Node> clone() override;
11075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski};
11175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
11275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/**
11375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * A Text (CDATA) XML node. Can not have any children.
11475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
1155eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskiclass Text : public BaseNode<Text> {
1165eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskipublic:
117d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinski    std::string text;
1185eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
1195eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski    std::unique_ptr<Node> clone() override;
12075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski};
12175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
12275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/**
123467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski * An XML resource with a source, name, and XML tree.
124467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski */
1255eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskiclass XmlResource {
1265eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskipublic:
127467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski    ResourceFile file;
128467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski    std::unique_ptr<xml::Node> root;
129467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski};
130467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
131467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski/**
13275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Inflates an XML DOM from a text stream, logging errors to the logger.
13375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Returns the root node on success, or nullptr on failure.
13475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
1351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistd::unique_ptr<XmlResource> inflate(std::istream* in, IDiagnostics* diag, const Source& source);
13675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
13775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/**
13875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Inflates an XML DOM from a binary ResXMLTree, logging errors to the logger.
13975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Returns the root node on success, or nullptr on failure.
14075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
1411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistd::unique_ptr<XmlResource> inflate(const void* data, size_t dataLen, IDiagnostics* diag,
1421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                                     const Source& source);
1431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
144467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam LesinskiElement* findRootElement(XmlResource* doc);
145ca5638fd85098c3d0a699492751043545f75553aAdam LesinskiElement* findRootElement(Node* node);
146ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski
1471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/**
1481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * A visitor interface for the different XML Node subtypes. This will not traverse into
1491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * children. Use Visitor for that.
1501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */
1515eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskiclass RawVisitor {
1525eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskipublic:
1531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    virtual ~RawVisitor() = default;
1541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    virtual void visit(Namespace* node) {}
1561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    virtual void visit(Element* node) {}
1571ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    virtual void visit(Text* text) {}
1581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
1591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/**
1611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Visitor whose default implementation visits the children nodes of any node.
1621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */
1635eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskiclass Visitor : public RawVisitor {
1645eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskipublic:
1651ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    using RawVisitor::visit;
1661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    void visit(Namespace* node) override {
1681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        visitChildren(node);
1691ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
1701ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1711ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    void visit(Element* node) override {
1721ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        visitChildren(node);
1731ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
1741ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1751ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    void visit(Text* text) override {
1761ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        visitChildren(text);
1771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
1781ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1791ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    void visitChildren(Node* node) {
1801ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        for (auto& child : node->children) {
1811ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            child->accept(this);
1821ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
1831ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
1841ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
18575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
18675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/**
1871ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * An XML DOM visitor that will record the package name for a namespace prefix.
18875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
1891ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiclass PackageAwareVisitor : public Visitor, public IPackageDeclStack {
1905eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskipublic:
1915eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski    using Visitor::visit;
1925eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
1935eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski    void visit(Namespace* ns) override;
1945eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski    Maybe<ExtractedPackage> transformPackageAlias(
1955eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski            const StringPiece& alias, const StringPiece& localPackage) const override;
1965eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
1971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiprivate:
1981ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    struct PackageDecl {
199d0f116b619feede0cfdb647157ce5ab4d50a1c46Adam Lesinski        std::string prefix;
200467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski        ExtractedPackage package;
2011ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    };
2021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    std::vector<PackageDecl> mPackageDecls;
20475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski};
20575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
20675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski// Implementations
20775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
20875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskitemplate <typename Derived>
2091ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskivoid BaseNode<Derived>::accept(RawVisitor* visitor) {
2101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    visitor->visit(static_cast<Derived*>(this));
21175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
21275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
2131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskitemplate <typename T>
2145eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskiclass NodeCastImpl : public RawVisitor {
2155eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskipublic:
2161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    using RawVisitor::visit;
2171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    T* value = nullptr;
2191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    void visit(T* v) override {
2211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        value = v;
2221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
2231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
2241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskitemplate <typename T>
2261ab598f46c3ff520a67f9d80194847741f3467abAdam LesinskiT* nodeCast(Node* node) {
2271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    NodeCastImpl<T> visitor;
2281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    node->accept(&visitor);
2291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    return visitor.value;
23075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
23175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
23275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} // namespace xml
23375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} // namespace aapt
23475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
23575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#endif // AAPT_XML_DOM_H
236