XmlDom.h revision d5083f6f6b9bc76bbe64052bcec639eee752a321
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
20ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <istream>
21ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <memory>
22ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <string>
23ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <vector>
24ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
25d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski#include "androidfw/StringPiece.h"
26d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski
271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "Diagnostics.h"
281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "Resource.h"
291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "ResourceValues.h"
301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/Util.h"
31467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "xml/XmlUtil.h"
3275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
3375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace aapt {
3475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace xml {
3575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
365eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskiclass RawVisitor;
3775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
3875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/**
3975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Base class for all XML nodes.
4075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
415eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskiclass Node {
42cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
43cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  Node* parent = nullptr;
44ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  size_t line_number = 0;
45ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  size_t column_number = 0;
46cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::string comment;
47cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::vector<std::unique_ptr<Node>> children;
48cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
49cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  virtual ~Node() = default;
50cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
51e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski  void AppendChild(std::unique_ptr<Node> child);
52e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski  void InsertChild(size_t index, std::unique_ptr<Node> child);
53ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  virtual void Accept(RawVisitor* visitor) = 0;
54ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  virtual std::unique_ptr<Node> Clone() = 0;
5575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski};
5675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
5775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/**
5875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Base class that implements the visitor methods for a
5975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * subclass of Node.
6075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
6175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskitemplate <typename Derived>
625eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskiclass BaseNode : public Node {
63cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
64ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  virtual void Accept(RawVisitor* visitor) override;
6575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski};
6675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
6775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/**
6875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * A Namespace XML node. Can only have one child.
6975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
705eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskiclass Namespace : public BaseNode<Namespace> {
71cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
72ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string namespace_prefix;
73ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string namespace_uri;
745eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
75ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<Node> Clone() override;
761ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
7775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
781ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistruct AaptAttribute {
79cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  Maybe<ResourceId> id;
80cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  aapt::Attribute attribute;
8175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski};
8275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
8375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/**
8475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * An XML attribute.
8575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
8675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistruct Attribute {
87ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string namespace_uri;
88cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::string name;
89cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::string value;
901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
91ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<AaptAttribute> compiled_attribute;
92ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<Item> compiled_value;
9375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski};
9475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
9575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/**
9675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * An Element XML node.
9775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
985eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskiclass Element : public BaseNode<Element> {
99cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
100ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string namespace_uri;
101cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::string name;
102cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::vector<Attribute> attributes;
103cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
104d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski  Attribute* FindAttribute(const android::StringPiece& ns, const android::StringPiece& name);
105d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski  xml::Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name);
106d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski  xml::Element* FindChildWithAttribute(const android::StringPiece& ns,
107d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski                                       const android::StringPiece& name,
108d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski                                       const android::StringPiece& attr_ns,
109d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski                                       const android::StringPiece& attr_name,
110d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski                                       const android::StringPiece& attr_value);
111ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<xml::Element*> GetChildElements();
112ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<Node> Clone() override;
11375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski};
11475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
11575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/**
11675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * A Text (CDATA) XML node. Can not have any children.
11775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
1185eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskiclass Text : public BaseNode<Text> {
119cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
120cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::string text;
1215eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
122ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<Node> Clone() override;
12375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski};
12475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
12575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/**
126467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski * An XML resource with a source, name, and XML tree.
127467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski */
1285eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskiclass XmlResource {
129cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
130cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  ResourceFile file;
131cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::unique_ptr<xml::Node> root;
132467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski};
133467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
134467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski/**
13575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Inflates an XML DOM from a text stream, logging errors to the logger.
13675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Returns the root node on success, or nullptr on failure.
13775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
138ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<XmlResource> Inflate(std::istream* in, IDiagnostics* diag,
139cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                                     const Source& source);
14075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
14175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/**
14275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Inflates an XML DOM from a binary ResXMLTree, logging errors to the logger.
14375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Returns the root node on success, or nullptr on failure.
14475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
145ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len,
146cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                                     IDiagnostics* diag, const Source& source);
1471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
148ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* FindRootElement(XmlResource* doc);
149ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* FindRootElement(Node* node);
150ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski
1511ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/**
152cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * A visitor interface for the different XML Node subtypes. This will not
153cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * traverse into
1541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * children. Use Visitor for that.
1551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */
1565eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskiclass RawVisitor {
157cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
158cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  virtual ~RawVisitor() = default;
1591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
160ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  virtual void Visit(Namespace* node) {}
161ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  virtual void Visit(Element* node) {}
162ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  virtual void Visit(Text* text) {}
1631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
1641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1651ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/**
1661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Visitor whose default implementation visits the children nodes of any node.
1671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */
1685eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskiclass Visitor : public RawVisitor {
169cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
170ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  using RawVisitor::Visit;
1711ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
172ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  void Visit(Namespace* node) override { VisitChildren(node); }
1731ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
174ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  void Visit(Element* node) override { VisitChildren(node); }
1751ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
176ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  void Visit(Text* text) override { VisitChildren(text); }
1771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
178ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  void VisitChildren(Node* node) {
179cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    for (auto& child : node->children) {
180ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      child->Accept(this);
1811ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
182cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1831ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
18475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
18575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/**
1861ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * An XML DOM visitor that will record the package name for a namespace prefix.
18775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
1881ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiclass PackageAwareVisitor : public Visitor, public IPackageDeclStack {
189cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
190ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  using Visitor::Visit;
1915eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
192ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  void Visit(Namespace* ns) override;
193ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Maybe<ExtractedPackage> TransformPackageAlias(
194d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski      const android::StringPiece& alias, const android::StringPiece& local_package) const override;
1955eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
196cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski private:
197cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  struct PackageDecl {
198cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    std::string prefix;
199cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    ExtractedPackage package;
200cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  };
2011ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
202ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<PackageDecl> package_decls_;
20375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski};
20475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
20575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski// Implementations
20675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
20775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskitemplate <typename Derived>
208ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskivoid BaseNode<Derived>::Accept(RawVisitor* visitor) {
209ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  visitor->Visit(static_cast<Derived*>(this));
21075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
21175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
2121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskitemplate <typename T>
2135eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinskiclass NodeCastImpl : public RawVisitor {
214cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
215ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  using RawVisitor::Visit;
2161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
217cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  T* value = nullptr;
2181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
219ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  void Visit(T* v) override { value = v; }
2201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
2211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskitemplate <typename T>
223ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiT* NodeCast(Node* node) {
224cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  NodeCastImpl<T> visitor;
225ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  node->Accept(&visitor);
226cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return visitor.value;
22775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
22875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
229cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski}  // namespace xml
230cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski}  // namespace aapt
23175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
232cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski#endif  // AAPT_XML_DOM_H
233