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