Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2006 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 com.android.internal.util;
     18 
     19 
     20 import org.xmlpull.v1.XmlPullParser;
     21 import org.xmlpull.v1.XmlPullParserException;
     22 import org.xmlpull.v1.XmlSerializer;
     23 
     24 import java.io.IOException;
     25 import java.io.InputStream;
     26 import java.io.OutputStream;
     27 import java.util.ArrayList;
     28 import java.util.HashMap;
     29 import java.util.HashSet;
     30 import java.util.Iterator;
     31 import java.util.List;
     32 import java.util.Map;
     33 import java.util.Set;
     34 
     35 import android.util.Xml;
     36 
     37 /** {@hide} */
     38 public class XmlUtils
     39 {
     40 
     41     public static void skipCurrentTag(XmlPullParser parser)
     42             throws XmlPullParserException, IOException {
     43         int outerDepth = parser.getDepth();
     44         int type;
     45         while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
     46                && (type != XmlPullParser.END_TAG
     47                        || parser.getDepth() > outerDepth)) {
     48         }
     49     }
     50 
     51     public static final int
     52     convertValueToList(CharSequence value, String[] options, int defaultValue)
     53     {
     54         if (null != value) {
     55             for (int i = 0; i < options.length; i++) {
     56                 if (value.equals(options[i]))
     57                     return i;
     58             }
     59         }
     60 
     61         return defaultValue;
     62     }
     63 
     64     public static final boolean
     65     convertValueToBoolean(CharSequence value, boolean defaultValue)
     66     {
     67         boolean result = false;
     68 
     69         if (null == value)
     70             return defaultValue;
     71 
     72         if (value.equals("1")
     73         ||  value.equals("true")
     74         ||  value.equals("TRUE"))
     75             result = true;
     76 
     77         return result;
     78     }
     79 
     80     public static final int
     81     convertValueToInt(CharSequence charSeq, int defaultValue)
     82     {
     83         if (null == charSeq)
     84             return defaultValue;
     85 
     86         String nm = charSeq.toString();
     87 
     88         // XXX This code is copied from Integer.decode() so we don't
     89         // have to instantiate an Integer!
     90 
     91         int value;
     92         int sign = 1;
     93         int index = 0;
     94         int len = nm.length();
     95         int base = 10;
     96 
     97         if ('-' == nm.charAt(0)) {
     98             sign = -1;
     99             index++;
    100         }
    101 
    102         if ('0' == nm.charAt(index)) {
    103             //  Quick check for a zero by itself
    104             if (index == (len - 1))
    105                 return 0;
    106 
    107             char    c = nm.charAt(index + 1);
    108 
    109             if ('x' == c || 'X' == c) {
    110                 index += 2;
    111                 base = 16;
    112             } else {
    113                 index++;
    114                 base = 8;
    115             }
    116         }
    117         else if ('#' == nm.charAt(index))
    118         {
    119             index++;
    120             base = 16;
    121         }
    122 
    123         return Integer.parseInt(nm.substring(index), base) * sign;
    124     }
    125 
    126     public static final int
    127     convertValueToUnsignedInt(String value, int defaultValue)
    128     {
    129         if (null == value)
    130             return defaultValue;
    131 
    132         return parseUnsignedIntAttribute(value);
    133     }
    134 
    135     public static final int
    136     parseUnsignedIntAttribute(CharSequence charSeq)
    137     {
    138         String  value = charSeq.toString();
    139 
    140         long    bits;
    141         int     index = 0;
    142         int     len = value.length();
    143         int     base = 10;
    144 
    145         if ('0' == value.charAt(index)) {
    146             //  Quick check for zero by itself
    147             if (index == (len - 1))
    148                 return 0;
    149 
    150             char    c = value.charAt(index + 1);
    151 
    152             if ('x' == c || 'X' == c) {     //  check for hex
    153                 index += 2;
    154                 base = 16;
    155             } else {                        //  check for octal
    156                 index++;
    157                 base = 8;
    158             }
    159         } else if ('#' == value.charAt(index)) {
    160             index++;
    161             base = 16;
    162         }
    163 
    164         return (int) Long.parseLong(value.substring(index), base);
    165     }
    166 
    167     /**
    168      * Flatten a Map into an output stream as XML.  The map can later be
    169      * read back with readMapXml().
    170      *
    171      * @param val The map to be flattened.
    172      * @param out Where to write the XML data.
    173      *
    174      * @see #writeMapXml(Map, String, XmlSerializer)
    175      * @see #writeListXml
    176      * @see #writeValueXml
    177      * @see #readMapXml
    178      */
    179     public static final void writeMapXml(Map val, OutputStream out)
    180             throws XmlPullParserException, java.io.IOException {
    181         XmlSerializer serializer = new FastXmlSerializer();
    182         serializer.setOutput(out, "utf-8");
    183         serializer.startDocument(null, true);
    184         serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
    185         writeMapXml(val, null, serializer);
    186         serializer.endDocument();
    187     }
    188 
    189     /**
    190      * Flatten a List into an output stream as XML.  The list can later be
    191      * read back with readListXml().
    192      *
    193      * @param val The list to be flattened.
    194      * @param out Where to write the XML data.
    195      *
    196      * @see #writeListXml(List, String, XmlSerializer)
    197      * @see #writeMapXml
    198      * @see #writeValueXml
    199      * @see #readListXml
    200      */
    201     public static final void writeListXml(List val, OutputStream out)
    202     throws XmlPullParserException, java.io.IOException
    203     {
    204         XmlSerializer serializer = Xml.newSerializer();
    205         serializer.setOutput(out, "utf-8");
    206         serializer.startDocument(null, true);
    207         serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
    208         writeListXml(val, null, serializer);
    209         serializer.endDocument();
    210     }
    211 
    212     /**
    213      * Flatten a Map into an XmlSerializer.  The map can later be read back
    214      * with readThisMapXml().
    215      *
    216      * @param val The map to be flattened.
    217      * @param name Name attribute to include with this list's tag, or null for
    218      *             none.
    219      * @param out XmlSerializer to write the map into.
    220      *
    221      * @see #writeMapXml(Map, OutputStream)
    222      * @see #writeListXml
    223      * @see #writeValueXml
    224      * @see #readMapXml
    225      */
    226     public static final void writeMapXml(Map val, String name, XmlSerializer out)
    227     throws XmlPullParserException, java.io.IOException
    228     {
    229         if (val == null) {
    230             out.startTag(null, "null");
    231             out.endTag(null, "null");
    232             return;
    233         }
    234 
    235         Set s = val.entrySet();
    236         Iterator i = s.iterator();
    237 
    238         out.startTag(null, "map");
    239         if (name != null) {
    240             out.attribute(null, "name", name);
    241         }
    242 
    243         while (i.hasNext()) {
    244             Map.Entry e = (Map.Entry)i.next();
    245             writeValueXml(e.getValue(), (String)e.getKey(), out);
    246         }
    247 
    248         out.endTag(null, "map");
    249     }
    250 
    251     /**
    252      * Flatten a List into an XmlSerializer.  The list can later be read back
    253      * with readThisListXml().
    254      *
    255      * @param val The list to be flattened.
    256      * @param name Name attribute to include with this list's tag, or null for
    257      *             none.
    258      * @param out XmlSerializer to write the list into.
    259      *
    260      * @see #writeListXml(List, OutputStream)
    261      * @see #writeMapXml
    262      * @see #writeValueXml
    263      * @see #readListXml
    264      */
    265     public static final void writeListXml(List val, String name, XmlSerializer out)
    266     throws XmlPullParserException, java.io.IOException
    267     {
    268         if (val == null) {
    269             out.startTag(null, "null");
    270             out.endTag(null, "null");
    271             return;
    272         }
    273 
    274         out.startTag(null, "list");
    275         if (name != null) {
    276             out.attribute(null, "name", name);
    277         }
    278 
    279         int N = val.size();
    280         int i=0;
    281         while (i < N) {
    282             writeValueXml(val.get(i), null, out);
    283             i++;
    284         }
    285 
    286         out.endTag(null, "list");
    287     }
    288 
    289     public static final void writeSetXml(Set val, String name, XmlSerializer out)
    290             throws XmlPullParserException, java.io.IOException {
    291         if (val == null) {
    292             out.startTag(null, "null");
    293             out.endTag(null, "null");
    294             return;
    295         }
    296 
    297         out.startTag(null, "set");
    298         if (name != null) {
    299             out.attribute(null, "name", name);
    300         }
    301 
    302         for (Object v : val) {
    303             writeValueXml(v, null, out);
    304         }
    305 
    306         out.endTag(null, "set");
    307     }
    308 
    309     /**
    310      * Flatten a byte[] into an XmlSerializer.  The list can later be read back
    311      * with readThisByteArrayXml().
    312      *
    313      * @param val The byte array to be flattened.
    314      * @param name Name attribute to include with this array's tag, or null for
    315      *             none.
    316      * @param out XmlSerializer to write the array into.
    317      *
    318      * @see #writeMapXml
    319      * @see #writeValueXml
    320      */
    321     public static final void writeByteArrayXml(byte[] val, String name,
    322             XmlSerializer out)
    323             throws XmlPullParserException, java.io.IOException {
    324 
    325         if (val == null) {
    326             out.startTag(null, "null");
    327             out.endTag(null, "null");
    328             return;
    329         }
    330 
    331         out.startTag(null, "byte-array");
    332         if (name != null) {
    333             out.attribute(null, "name", name);
    334         }
    335 
    336         final int N = val.length;
    337         out.attribute(null, "num", Integer.toString(N));
    338 
    339         StringBuilder sb = new StringBuilder(val.length*2);
    340         for (int i=0; i<N; i++) {
    341             int b = val[i];
    342             int h = b>>4;
    343             sb.append(h >= 10 ? ('a'+h-10) : ('0'+h));
    344             h = b&0xff;
    345             sb.append(h >= 10 ? ('a'+h-10) : ('0'+h));
    346         }
    347 
    348         out.text(sb.toString());
    349 
    350         out.endTag(null, "byte-array");
    351     }
    352 
    353     /**
    354      * Flatten an int[] into an XmlSerializer.  The list can later be read back
    355      * with readThisIntArrayXml().
    356      *
    357      * @param val The int array to be flattened.
    358      * @param name Name attribute to include with this array's tag, or null for
    359      *             none.
    360      * @param out XmlSerializer to write the array into.
    361      *
    362      * @see #writeMapXml
    363      * @see #writeValueXml
    364      * @see #readThisIntArrayXml
    365      */
    366     public static final void writeIntArrayXml(int[] val, String name,
    367             XmlSerializer out)
    368             throws XmlPullParserException, java.io.IOException {
    369 
    370         if (val == null) {
    371             out.startTag(null, "null");
    372             out.endTag(null, "null");
    373             return;
    374         }
    375 
    376         out.startTag(null, "int-array");
    377         if (name != null) {
    378             out.attribute(null, "name", name);
    379         }
    380 
    381         final int N = val.length;
    382         out.attribute(null, "num", Integer.toString(N));
    383 
    384         for (int i=0; i<N; i++) {
    385             out.startTag(null, "item");
    386             out.attribute(null, "value", Integer.toString(val[i]));
    387             out.endTag(null, "item");
    388         }
    389 
    390         out.endTag(null, "int-array");
    391     }
    392 
    393     /**
    394      * Flatten an object's value into an XmlSerializer.  The value can later
    395      * be read back with readThisValueXml().
    396      *
    397      * Currently supported value types are: null, String, Integer, Long,
    398      * Float, Double Boolean, Map, List.
    399      *
    400      * @param v The object to be flattened.
    401      * @param name Name attribute to include with this value's tag, or null
    402      *             for none.
    403      * @param out XmlSerializer to write the object into.
    404      *
    405      * @see #writeMapXml
    406      * @see #writeListXml
    407      * @see #readValueXml
    408      */
    409     public static final void writeValueXml(Object v, String name, XmlSerializer out)
    410     throws XmlPullParserException, java.io.IOException
    411     {
    412         String typeStr;
    413         if (v == null) {
    414             out.startTag(null, "null");
    415             if (name != null) {
    416                 out.attribute(null, "name", name);
    417             }
    418             out.endTag(null, "null");
    419             return;
    420         } else if (v instanceof String) {
    421             out.startTag(null, "string");
    422             if (name != null) {
    423                 out.attribute(null, "name", name);
    424             }
    425             out.text(v.toString());
    426             out.endTag(null, "string");
    427             return;
    428         } else if (v instanceof Integer) {
    429             typeStr = "int";
    430         } else if (v instanceof Long) {
    431             typeStr = "long";
    432         } else if (v instanceof Float) {
    433             typeStr = "float";
    434         } else if (v instanceof Double) {
    435             typeStr = "double";
    436         } else if (v instanceof Boolean) {
    437             typeStr = "boolean";
    438         } else if (v instanceof byte[]) {
    439             writeByteArrayXml((byte[])v, name, out);
    440             return;
    441         } else if (v instanceof int[]) {
    442             writeIntArrayXml((int[])v, name, out);
    443             return;
    444         } else if (v instanceof Map) {
    445             writeMapXml((Map)v, name, out);
    446             return;
    447         } else if (v instanceof List) {
    448             writeListXml((List)v, name, out);
    449             return;
    450         } else if (v instanceof Set) {
    451             writeSetXml((Set)v, name, out);
    452             return;
    453         } else if (v instanceof CharSequence) {
    454             // XXX This is to allow us to at least write something if
    455             // we encounter styled text...  but it means we will drop all
    456             // of the styling information. :(
    457             out.startTag(null, "string");
    458             if (name != null) {
    459                 out.attribute(null, "name", name);
    460             }
    461             out.text(v.toString());
    462             out.endTag(null, "string");
    463             return;
    464         } else {
    465             throw new RuntimeException("writeValueXml: unable to write value " + v);
    466         }
    467 
    468         out.startTag(null, typeStr);
    469         if (name != null) {
    470             out.attribute(null, "name", name);
    471         }
    472         out.attribute(null, "value", v.toString());
    473         out.endTag(null, typeStr);
    474     }
    475 
    476     /**
    477      * Read a HashMap from an InputStream containing XML.  The stream can
    478      * previously have been written by writeMapXml().
    479      *
    480      * @param in The InputStream from which to read.
    481      *
    482      * @return HashMap The resulting map.
    483      *
    484      * @see #readListXml
    485      * @see #readValueXml
    486      * @see #readThisMapXml
    487      * #see #writeMapXml
    488      */
    489     public static final HashMap readMapXml(InputStream in)
    490     throws XmlPullParserException, java.io.IOException
    491     {
    492         XmlPullParser   parser = Xml.newPullParser();
    493         parser.setInput(in, null);
    494         return (HashMap)readValueXml(parser, new String[1]);
    495     }
    496 
    497     /**
    498      * Read an ArrayList from an InputStream containing XML.  The stream can
    499      * previously have been written by writeListXml().
    500      *
    501      * @param in The InputStream from which to read.
    502      *
    503      * @return ArrayList The resulting list.
    504      *
    505      * @see #readMapXml
    506      * @see #readValueXml
    507      * @see #readThisListXml
    508      * @see #writeListXml
    509      */
    510     public static final ArrayList readListXml(InputStream in)
    511     throws XmlPullParserException, java.io.IOException
    512     {
    513         XmlPullParser   parser = Xml.newPullParser();
    514         parser.setInput(in, null);
    515         return (ArrayList)readValueXml(parser, new String[1]);
    516     }
    517 
    518 
    519     /**
    520      * Read a HashSet from an InputStream containing XML. The stream can
    521      * previously have been written by writeSetXml().
    522      *
    523      * @param in The InputStream from which to read.
    524      *
    525      * @return HashSet The resulting set.
    526      *
    527      * @throws XmlPullParserException
    528      * @throws java.io.IOException
    529      *
    530      * @see #readValueXml
    531      * @see #readThisSetXml
    532      * @see #writeSetXml
    533      */
    534     public static final HashSet readSetXml(InputStream in)
    535             throws XmlPullParserException, java.io.IOException {
    536         XmlPullParser parser = Xml.newPullParser();
    537         parser.setInput(in, null);
    538         return (HashSet) readValueXml(parser, new String[1]);
    539     }
    540 
    541     /**
    542      * Read a HashMap object from an XmlPullParser.  The XML data could
    543      * previously have been generated by writeMapXml().  The XmlPullParser
    544      * must be positioned <em>after</em> the tag that begins the map.
    545      *
    546      * @param parser The XmlPullParser from which to read the map data.
    547      * @param endTag Name of the tag that will end the map, usually "map".
    548      * @param name An array of one string, used to return the name attribute
    549      *             of the map's tag.
    550      *
    551      * @return HashMap The newly generated map.
    552      *
    553      * @see #readMapXml
    554      */
    555     public static final HashMap readThisMapXml(XmlPullParser parser, String endTag, String[] name)
    556     throws XmlPullParserException, java.io.IOException
    557     {
    558         HashMap map = new HashMap();
    559 
    560         int eventType = parser.getEventType();
    561         do {
    562             if (eventType == parser.START_TAG) {
    563                 Object val = readThisValueXml(parser, name);
    564                 if (name[0] != null) {
    565                     //System.out.println("Adding to map: " + name + " -> " + val);
    566                     map.put(name[0], val);
    567                 } else {
    568                     throw new XmlPullParserException(
    569                         "Map value without name attribute: " + parser.getName());
    570                 }
    571             } else if (eventType == parser.END_TAG) {
    572                 if (parser.getName().equals(endTag)) {
    573                     return map;
    574                 }
    575                 throw new XmlPullParserException(
    576                     "Expected " + endTag + " end tag at: " + parser.getName());
    577             }
    578             eventType = parser.next();
    579         } while (eventType != parser.END_DOCUMENT);
    580 
    581         throw new XmlPullParserException(
    582             "Document ended before " + endTag + " end tag");
    583     }
    584 
    585     /**
    586      * Read an ArrayList object from an XmlPullParser.  The XML data could
    587      * previously have been generated by writeListXml().  The XmlPullParser
    588      * must be positioned <em>after</em> the tag that begins the list.
    589      *
    590      * @param parser The XmlPullParser from which to read the list data.
    591      * @param endTag Name of the tag that will end the list, usually "list".
    592      * @param name An array of one string, used to return the name attribute
    593      *             of the list's tag.
    594      *
    595      * @return HashMap The newly generated list.
    596      *
    597      * @see #readListXml
    598      */
    599     public static final ArrayList readThisListXml(XmlPullParser parser, String endTag, String[] name)
    600     throws XmlPullParserException, java.io.IOException
    601     {
    602         ArrayList list = new ArrayList();
    603 
    604         int eventType = parser.getEventType();
    605         do {
    606             if (eventType == parser.START_TAG) {
    607                 Object val = readThisValueXml(parser, name);
    608                 list.add(val);
    609                 //System.out.println("Adding to list: " + val);
    610             } else if (eventType == parser.END_TAG) {
    611                 if (parser.getName().equals(endTag)) {
    612                     return list;
    613                 }
    614                 throw new XmlPullParserException(
    615                     "Expected " + endTag + " end tag at: " + parser.getName());
    616             }
    617             eventType = parser.next();
    618         } while (eventType != parser.END_DOCUMENT);
    619 
    620         throw new XmlPullParserException(
    621             "Document ended before " + endTag + " end tag");
    622     }
    623 
    624     /**
    625      * Read a HashSet object from an XmlPullParser. The XML data could previously
    626      * have been generated by writeSetXml(). The XmlPullParser must be positioned
    627      * <em>after</em> the tag that begins the set.
    628      *
    629      * @param parser The XmlPullParser from which to read the set data.
    630      * @param endTag Name of the tag that will end the set, usually "set".
    631      * @param name An array of one string, used to return the name attribute
    632      *             of the set's tag.
    633      *
    634      * @return HashSet The newly generated set.
    635      *
    636      * @throws XmlPullParserException
    637      * @throws java.io.IOException
    638      *
    639      * @see #readSetXml
    640      */
    641     public static final HashSet readThisSetXml(XmlPullParser parser, String endTag, String[] name)
    642             throws XmlPullParserException, java.io.IOException {
    643         HashSet set = new HashSet();
    644 
    645         int eventType = parser.getEventType();
    646         do {
    647             if (eventType == parser.START_TAG) {
    648                 Object val = readThisValueXml(parser, name);
    649                 set.add(val);
    650                 //System.out.println("Adding to set: " + val);
    651             } else if (eventType == parser.END_TAG) {
    652                 if (parser.getName().equals(endTag)) {
    653                     return set;
    654                 }
    655                 throw new XmlPullParserException(
    656                         "Expected " + endTag + " end tag at: " + parser.getName());
    657             }
    658             eventType = parser.next();
    659         } while (eventType != parser.END_DOCUMENT);
    660 
    661         throw new XmlPullParserException(
    662                 "Document ended before " + endTag + " end tag");
    663     }
    664 
    665     /**
    666      * Read an int[] object from an XmlPullParser.  The XML data could
    667      * previously have been generated by writeIntArrayXml().  The XmlPullParser
    668      * must be positioned <em>after</em> the tag that begins the list.
    669      *
    670      * @param parser The XmlPullParser from which to read the list data.
    671      * @param endTag Name of the tag that will end the list, usually "list".
    672      * @param name An array of one string, used to return the name attribute
    673      *             of the list's tag.
    674      *
    675      * @return Returns a newly generated int[].
    676      *
    677      * @see #readListXml
    678      */
    679     public static final int[] readThisIntArrayXml(XmlPullParser parser,
    680             String endTag, String[] name)
    681             throws XmlPullParserException, java.io.IOException {
    682 
    683         int num;
    684         try {
    685             num = Integer.parseInt(parser.getAttributeValue(null, "num"));
    686         } catch (NullPointerException e) {
    687             throw new XmlPullParserException(
    688                     "Need num attribute in byte-array");
    689         } catch (NumberFormatException e) {
    690             throw new XmlPullParserException(
    691                     "Not a number in num attribute in byte-array");
    692         }
    693 
    694         int[] array = new int[num];
    695         int i = 0;
    696 
    697         int eventType = parser.getEventType();
    698         do {
    699             if (eventType == parser.START_TAG) {
    700                 if (parser.getName().equals("item")) {
    701                     try {
    702                         array[i] = Integer.parseInt(
    703                                 parser.getAttributeValue(null, "value"));
    704                     } catch (NullPointerException e) {
    705                         throw new XmlPullParserException(
    706                                 "Need value attribute in item");
    707                     } catch (NumberFormatException e) {
    708                         throw new XmlPullParserException(
    709                                 "Not a number in value attribute in item");
    710                     }
    711                 } else {
    712                     throw new XmlPullParserException(
    713                             "Expected item tag at: " + parser.getName());
    714                 }
    715             } else if (eventType == parser.END_TAG) {
    716                 if (parser.getName().equals(endTag)) {
    717                     return array;
    718                 } else if (parser.getName().equals("item")) {
    719                     i++;
    720                 } else {
    721                     throw new XmlPullParserException(
    722                         "Expected " + endTag + " end tag at: "
    723                         + parser.getName());
    724                 }
    725             }
    726             eventType = parser.next();
    727         } while (eventType != parser.END_DOCUMENT);
    728 
    729         throw new XmlPullParserException(
    730             "Document ended before " + endTag + " end tag");
    731     }
    732 
    733     /**
    734      * Read a flattened object from an XmlPullParser.  The XML data could
    735      * previously have been written with writeMapXml(), writeListXml(), or
    736      * writeValueXml().  The XmlPullParser must be positioned <em>at</em> the
    737      * tag that defines the value.
    738      *
    739      * @param parser The XmlPullParser from which to read the object.
    740      * @param name An array of one string, used to return the name attribute
    741      *             of the value's tag.
    742      *
    743      * @return Object The newly generated value object.
    744      *
    745      * @see #readMapXml
    746      * @see #readListXml
    747      * @see #writeValueXml
    748      */
    749     public static final Object readValueXml(XmlPullParser parser, String[] name)
    750     throws XmlPullParserException, java.io.IOException
    751     {
    752         int eventType = parser.getEventType();
    753         do {
    754             if (eventType == parser.START_TAG) {
    755                 return readThisValueXml(parser, name);
    756             } else if (eventType == parser.END_TAG) {
    757                 throw new XmlPullParserException(
    758                     "Unexpected end tag at: " + parser.getName());
    759             } else if (eventType == parser.TEXT) {
    760                 throw new XmlPullParserException(
    761                     "Unexpected text: " + parser.getText());
    762             }
    763             eventType = parser.next();
    764         } while (eventType != parser.END_DOCUMENT);
    765 
    766         throw new XmlPullParserException(
    767             "Unexpected end of document");
    768     }
    769 
    770     private static final Object readThisValueXml(XmlPullParser parser, String[] name)
    771     throws XmlPullParserException, java.io.IOException
    772     {
    773         final String valueName = parser.getAttributeValue(null, "name");
    774         final String tagName = parser.getName();
    775 
    776         //System.out.println("Reading this value tag: " + tagName + ", name=" + valueName);
    777 
    778         Object res;
    779 
    780         if (tagName.equals("null")) {
    781             res = null;
    782         } else if (tagName.equals("string")) {
    783             String value = "";
    784             int eventType;
    785             while ((eventType = parser.next()) != parser.END_DOCUMENT) {
    786                 if (eventType == parser.END_TAG) {
    787                     if (parser.getName().equals("string")) {
    788                         name[0] = valueName;
    789                         //System.out.println("Returning value for " + valueName + ": " + value);
    790                         return value;
    791                     }
    792                     throw new XmlPullParserException(
    793                         "Unexpected end tag in <string>: " + parser.getName());
    794                 } else if (eventType == parser.TEXT) {
    795                     value += parser.getText();
    796                 } else if (eventType == parser.START_TAG) {
    797                     throw new XmlPullParserException(
    798                         "Unexpected start tag in <string>: " + parser.getName());
    799                 }
    800             }
    801             throw new XmlPullParserException(
    802                 "Unexpected end of document in <string>");
    803         } else if (tagName.equals("int")) {
    804             res = Integer.parseInt(parser.getAttributeValue(null, "value"));
    805         } else if (tagName.equals("long")) {
    806             res = Long.valueOf(parser.getAttributeValue(null, "value"));
    807         } else if (tagName.equals("float")) {
    808             res = new Float(parser.getAttributeValue(null, "value"));
    809         } else if (tagName.equals("double")) {
    810             res = new Double(parser.getAttributeValue(null, "value"));
    811         } else if (tagName.equals("boolean")) {
    812             res = Boolean.valueOf(parser.getAttributeValue(null, "value"));
    813         } else if (tagName.equals("int-array")) {
    814             parser.next();
    815             res = readThisIntArrayXml(parser, "int-array", name);
    816             name[0] = valueName;
    817             //System.out.println("Returning value for " + valueName + ": " + res);
    818             return res;
    819         } else if (tagName.equals("map")) {
    820             parser.next();
    821             res = readThisMapXml(parser, "map", name);
    822             name[0] = valueName;
    823             //System.out.println("Returning value for " + valueName + ": " + res);
    824             return res;
    825         } else if (tagName.equals("list")) {
    826             parser.next();
    827             res = readThisListXml(parser, "list", name);
    828             name[0] = valueName;
    829             //System.out.println("Returning value for " + valueName + ": " + res);
    830             return res;
    831         } else if (tagName.equals("set")) {
    832             parser.next();
    833             res = readThisSetXml(parser, "set", name);
    834             name[0] = valueName;
    835             //System.out.println("Returning value for " + valueName + ": " + res);
    836             return res;
    837         } else {
    838             throw new XmlPullParserException(
    839                 "Unknown tag: " + tagName);
    840         }
    841 
    842         // Skip through to end tag.
    843         int eventType;
    844         while ((eventType = parser.next()) != parser.END_DOCUMENT) {
    845             if (eventType == parser.END_TAG) {
    846                 if (parser.getName().equals(tagName)) {
    847                     name[0] = valueName;
    848                     //System.out.println("Returning value for " + valueName + ": " + res);
    849                     return res;
    850                 }
    851                 throw new XmlPullParserException(
    852                     "Unexpected end tag in <" + tagName + ">: " + parser.getName());
    853             } else if (eventType == parser.TEXT) {
    854                 throw new XmlPullParserException(
    855                 "Unexpected text in <" + tagName + ">: " + parser.getName());
    856             } else if (eventType == parser.START_TAG) {
    857                 throw new XmlPullParserException(
    858                     "Unexpected start tag in <" + tagName + ">: " + parser.getName());
    859             }
    860         }
    861         throw new XmlPullParserException(
    862             "Unexpected end of document in <" + tagName + ">");
    863     }
    864 
    865     public static final void beginDocument(XmlPullParser parser, String firstElementName) throws XmlPullParserException, IOException
    866     {
    867         int type;
    868         while ((type=parser.next()) != parser.START_TAG
    869                    && type != parser.END_DOCUMENT) {
    870             ;
    871         }
    872 
    873         if (type != parser.START_TAG) {
    874             throw new XmlPullParserException("No start tag found");
    875         }
    876 
    877         if (!parser.getName().equals(firstElementName)) {
    878             throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() +
    879                     ", expected " + firstElementName);
    880         }
    881     }
    882 
    883     public static final void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException
    884     {
    885         int type;
    886         while ((type=parser.next()) != parser.START_TAG
    887                    && type != parser.END_DOCUMENT) {
    888             ;
    889         }
    890     }
    891 
    892     public static boolean nextElementWithin(XmlPullParser parser, int outerDepth)
    893             throws IOException, XmlPullParserException {
    894         for (;;) {
    895             int type = parser.next();
    896             if (type == XmlPullParser.END_DOCUMENT
    897                     || (type == XmlPullParser.END_TAG && parser.getDepth() == outerDepth)) {
    898                 return false;
    899             }
    900             if (type == XmlPullParser.START_TAG
    901                     && parser.getDepth() == outerDepth + 1) {
    902                 return true;
    903             }
    904         }
    905     }
    906 }
    907