1 /*
2  * Copyright (C) 2016 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 package android.net.wifi.hotspot2.omadm;
18 
19 import org.xml.sax.Attributes;
20 import org.xml.sax.InputSource;
21 import org.xml.sax.SAXException;
22 import org.xml.sax.helpers.DefaultHandler;
23 
24 import android.text.TextUtils;
25 
26 import java.io.IOException;
27 import java.io.StringReader;
28 
29 import javax.xml.parsers.ParserConfigurationException;
30 import javax.xml.parsers.SAXParser;
31 import javax.xml.parsers.SAXParserFactory;
32 
33 /**
34  * Class for parsing an XML string to an XML tree represented by {@link XMLNode}.
35  *
36  * The original XML string:
37  * <root>
38  *   <tag1>text1</tag1>
39  *   <tag2>
40  *     <tag3>text3</tag3>
41  *   </tag2>
42  * </root>
43  *
44  * The XML tree representation:
45  *                  [root]
46  *                     |
47  *                     |
48  *   [tag1, text1]-----|-----[tag2]
49  *                             |
50  *                             |
51  *                       [tag3, text3]
52  *
53  * @hide
54  */
55 public class XMLParser extends DefaultHandler {
56     private XMLNode mRoot = null;
57     private XMLNode mCurrent = null;
58 
parse(String text)59     public XMLNode parse(String text) throws IOException, SAXException {
60         if (TextUtils.isEmpty(text)) {
61             throw new IOException("XML string not provided");
62         }
63 
64         // Reset pointers.
65         mRoot = null;
66         mCurrent = null;
67 
68         try {
69             SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
70             parser.parse(new InputSource(new StringReader(text)), this);
71             return mRoot;
72         } catch (ParserConfigurationException pce) {
73             throw new SAXException(pce);
74         }
75     }
76 
77     @Override
startElement(String uri, String localName, String qName, Attributes attributes)78     public void startElement(String uri, String localName, String qName, Attributes attributes)
79             throws SAXException {
80         XMLNode parent = mCurrent;
81 
82         mCurrent = new XMLNode(parent, qName);
83 
84         if (mRoot == null) {
85             mRoot = mCurrent;
86         } else if (parent == null) {
87             throw new SAXException("More than one root nodes");
88         } else {
89             parent.addChild(mCurrent);
90         }
91     }
92 
93     @Override
endElement(String uri, String localName, String qName)94     public void endElement(String uri, String localName, String qName) throws SAXException {
95         if (!qName.equals(mCurrent.getTag())) {
96             throw new SAXException("End tag '" + qName + "' doesn't match current node: " +
97                     mCurrent);
98         }
99 
100         mCurrent.close();
101         mCurrent = mCurrent.getParent();
102     }
103 
104     @Override
characters(char[] ch, int start, int length)105     public void characters(char[] ch, int start, int length) throws SAXException {
106         mCurrent.addText(new String(ch, start, length));
107     }
108 }
109