1 /* 2 * Copyright (C) 2007 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.util; 18 19 import org.xml.sax.ContentHandler; 20 import org.xml.sax.InputSource; 21 import org.xml.sax.SAXException; 22 import org.xml.sax.XMLReader; 23 import org.xmlpull.v1.XmlPullParser; 24 import org.xmlpull.v1.XmlSerializer; 25 import org.xmlpull.v1.XmlPullParserException; 26 import org.xmlpull.v1.XmlPullParserFactory; 27 28 import java.io.IOException; 29 import java.io.InputStream; 30 import java.io.Reader; 31 import java.io.StringReader; 32 import java.io.UnsupportedEncodingException; 33 34 import org.apache.harmony.xml.ExpatPullParser; 35 import org.apache.harmony.xml.ExpatReader; 36 37 /** 38 * XML utility methods. 39 */ 40 public class Xml { 41 42 /** 43 * {@link org.xmlpull.v1.XmlPullParser} "relaxed" feature name. 44 * 45 * @see <a href="http://xmlpull.org/v1/doc/features.html#relaxed"> 46 * specification</a> 47 */ 48 public static String FEATURE_RELAXED = ExpatPullParser.FEATURE_RELAXED; 49 50 /** 51 * Parses the given xml string and fires events on the given SAX handler. 52 */ parse(String xml, ContentHandler contentHandler)53 public static void parse(String xml, ContentHandler contentHandler) 54 throws SAXException { 55 try { 56 XMLReader reader = new ExpatReader(); 57 reader.setContentHandler(contentHandler); 58 reader.parse(new InputSource(new StringReader(xml))); 59 } 60 catch (IOException e) { 61 throw new AssertionError(e); 62 } 63 } 64 65 /** 66 * Parses xml from the given reader and fires events on the given SAX 67 * handler. 68 */ parse(Reader in, ContentHandler contentHandler)69 public static void parse(Reader in, ContentHandler contentHandler) 70 throws IOException, SAXException { 71 XMLReader reader = new ExpatReader(); 72 reader.setContentHandler(contentHandler); 73 reader.parse(new InputSource(in)); 74 } 75 76 /** 77 * Parses xml from the given input stream and fires events on the given SAX 78 * handler. 79 */ parse(InputStream in, Encoding encoding, ContentHandler contentHandler)80 public static void parse(InputStream in, Encoding encoding, 81 ContentHandler contentHandler) throws IOException, SAXException { 82 try { 83 XMLReader reader = new ExpatReader(); 84 reader.setContentHandler(contentHandler); 85 InputSource source = new InputSource(in); 86 source.setEncoding(encoding.expatName); 87 reader.parse(source); 88 } catch (IOException e) { 89 throw new AssertionError(e); 90 } 91 } 92 93 /** 94 * Creates a new pull parser with namespace support. 95 * 96 * <p><b>Note:</b> This is actually slower than the SAX parser, and it's not 97 * fully implemented. If you need a fast, mostly implemented pull parser, 98 * use this. If you need a complete implementation, use KXML. 99 */ newPullParser()100 public static XmlPullParser newPullParser() { 101 ExpatPullParser parser = new ExpatPullParser(); 102 parser.setNamespaceProcessingEnabled(true); 103 return parser; 104 } 105 106 /** 107 * Creates a new xml serializer. 108 */ newSerializer()109 public static XmlSerializer newSerializer() { 110 try { 111 return XmlSerializerFactory.instance.newSerializer(); 112 } catch (XmlPullParserException e) { 113 throw new AssertionError(e); 114 } 115 } 116 117 /** Factory for xml serializers. Initialized on demand. */ 118 static class XmlSerializerFactory { 119 static final String TYPE 120 = "org.kxml2.io.KXmlParser,org.kxml2.io.KXmlSerializer"; 121 static final XmlPullParserFactory instance; 122 static { 123 try { 124 instance = XmlPullParserFactory.newInstance(TYPE, null); 125 } catch (XmlPullParserException e) { 126 throw new AssertionError(e); 127 } 128 } 129 } 130 131 /** 132 * Supported character encodings. 133 */ 134 public enum Encoding { 135 136 US_ASCII("US-ASCII"), 137 UTF_8("UTF-8"), 138 UTF_16("UTF-16"), 139 ISO_8859_1("ISO-8859-1"); 140 141 final String expatName; 142 Encoding(String expatName)143 Encoding(String expatName) { 144 this.expatName = expatName; 145 } 146 } 147 148 /** 149 * Finds an encoding by name. Returns UTF-8 if you pass {@code null}. 150 */ findEncodingByName(String encodingName)151 public static Encoding findEncodingByName(String encodingName) 152 throws UnsupportedEncodingException { 153 if (encodingName == null) { 154 return Encoding.UTF_8; 155 } 156 157 for (Encoding encoding : Encoding.values()) { 158 if (encoding.expatName.equalsIgnoreCase(encodingName)) 159 return encoding; 160 } 161 throw new UnsupportedEncodingException(encodingName); 162 } 163 164 /** 165 * Return an AttributeSet interface for use with the given XmlPullParser. 166 * If the given parser itself implements AttributeSet, that implementation 167 * is simply returned. Otherwise a wrapper class is 168 * instantiated on top of the XmlPullParser, as a proxy for retrieving its 169 * attributes, and returned to you. 170 * 171 * @param parser The existing parser for which you would like an 172 * AttributeSet. 173 * 174 * @return An AttributeSet you can use to retrieve the 175 * attribute values at each of the tags as the parser moves 176 * through its XML document. 177 * 178 * @see AttributeSet 179 */ asAttributeSet(XmlPullParser parser)180 public static AttributeSet asAttributeSet(XmlPullParser parser) { 181 return (parser instanceof AttributeSet) 182 ? (AttributeSet) parser 183 : new XmlPullAttributes(parser); 184 } 185 } 186