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