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