XmlUtils.java revision 9e9e2e73c6ec7bece20268196dc89ad0c8bafad4
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 17package com.android.internal.util; 18 19import android.graphics.Bitmap; 20import android.graphics.BitmapFactory; 21import android.graphics.Bitmap.CompressFormat; 22import android.net.Uri; 23import android.util.ArrayMap; 24import android.util.Base64; 25import android.util.Xml; 26 27import org.xmlpull.v1.XmlPullParser; 28import org.xmlpull.v1.XmlPullParserException; 29import org.xmlpull.v1.XmlSerializer; 30 31import java.io.ByteArrayOutputStream; 32import java.io.IOException; 33import java.io.InputStream; 34import java.io.OutputStream; 35import java.net.ProtocolException; 36import java.nio.charset.StandardCharsets; 37import java.util.ArrayList; 38import java.util.HashMap; 39import java.util.HashSet; 40import java.util.Iterator; 41import java.util.List; 42import java.util.Map; 43import java.util.Set; 44 45/** {@hide} */ 46public class XmlUtils { 47 48 public static void skipCurrentTag(XmlPullParser parser) 49 throws XmlPullParserException, IOException { 50 int outerDepth = parser.getDepth(); 51 int type; 52 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 53 && (type != XmlPullParser.END_TAG 54 || parser.getDepth() > outerDepth)) { 55 } 56 } 57 58 public static final int 59 convertValueToList(CharSequence value, String[] options, int defaultValue) 60 { 61 if (null != value) { 62 for (int i = 0; i < options.length; i++) { 63 if (value.equals(options[i])) 64 return i; 65 } 66 } 67 68 return defaultValue; 69 } 70 71 public static final boolean 72 convertValueToBoolean(CharSequence value, boolean defaultValue) 73 { 74 boolean result = false; 75 76 if (null == value) 77 return defaultValue; 78 79 if (value.equals("1") 80 || value.equals("true") 81 || value.equals("TRUE")) 82 result = true; 83 84 return result; 85 } 86 87 public static final int 88 convertValueToInt(CharSequence charSeq, int defaultValue) 89 { 90 if (null == charSeq) 91 return defaultValue; 92 93 String nm = charSeq.toString(); 94 95 // XXX This code is copied from Integer.decode() so we don't 96 // have to instantiate an Integer! 97 98 int value; 99 int sign = 1; 100 int index = 0; 101 int len = nm.length(); 102 int base = 10; 103 104 if ('-' == nm.charAt(0)) { 105 sign = -1; 106 index++; 107 } 108 109 if ('0' == nm.charAt(index)) { 110 // Quick check for a zero by itself 111 if (index == (len - 1)) 112 return 0; 113 114 char c = nm.charAt(index + 1); 115 116 if ('x' == c || 'X' == c) { 117 index += 2; 118 base = 16; 119 } else { 120 index++; 121 base = 8; 122 } 123 } 124 else if ('#' == nm.charAt(index)) 125 { 126 index++; 127 base = 16; 128 } 129 130 return Integer.parseInt(nm.substring(index), base) * sign; 131 } 132 133 public static int convertValueToUnsignedInt(String value, int defaultValue) { 134 if (null == value) { 135 return defaultValue; 136 } 137 138 return parseUnsignedIntAttribute(value); 139 } 140 141 public static int parseUnsignedIntAttribute(CharSequence charSeq) { 142 String value = charSeq.toString(); 143 144 long bits; 145 int index = 0; 146 int len = value.length(); 147 int base = 10; 148 149 if ('0' == value.charAt(index)) { 150 // Quick check for zero by itself 151 if (index == (len - 1)) 152 return 0; 153 154 char c = value.charAt(index + 1); 155 156 if ('x' == c || 'X' == c) { // check for hex 157 index += 2; 158 base = 16; 159 } else { // check for octal 160 index++; 161 base = 8; 162 } 163 } else if ('#' == value.charAt(index)) { 164 index++; 165 base = 16; 166 } 167 168 return (int) Long.parseLong(value.substring(index), base); 169 } 170 171 /** 172 * Flatten a Map into an output stream as XML. The map can later be 173 * read back with readMapXml(). 174 * 175 * @param val The map to be flattened. 176 * @param out Where to write the XML data. 177 * 178 * @see #writeMapXml(Map, String, XmlSerializer) 179 * @see #writeListXml 180 * @see #writeValueXml 181 * @see #readMapXml 182 */ 183 public static final void writeMapXml(Map val, OutputStream out) 184 throws XmlPullParserException, java.io.IOException { 185 XmlSerializer serializer = new FastXmlSerializer(); 186 serializer.setOutput(out, StandardCharsets.UTF_8.name()); 187 serializer.startDocument(null, true); 188 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); 189 writeMapXml(val, null, serializer); 190 serializer.endDocument(); 191 } 192 193 /** 194 * Flatten a List into an output stream as XML. The list can later be 195 * read back with readListXml(). 196 * 197 * @param val The list to be flattened. 198 * @param out Where to write the XML data. 199 * 200 * @see #writeListXml(List, String, XmlSerializer) 201 * @see #writeMapXml 202 * @see #writeValueXml 203 * @see #readListXml 204 */ 205 public static final void writeListXml(List val, OutputStream out) 206 throws XmlPullParserException, java.io.IOException 207 { 208 XmlSerializer serializer = Xml.newSerializer(); 209 serializer.setOutput(out, StandardCharsets.UTF_8.name()); 210 serializer.startDocument(null, true); 211 serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); 212 writeListXml(val, null, serializer); 213 serializer.endDocument(); 214 } 215 216 /** 217 * Flatten a Map into an XmlSerializer. The map can later be read back 218 * with readThisMapXml(). 219 * 220 * @param val The map to be flattened. 221 * @param name Name attribute to include with this list's tag, or null for 222 * none. 223 * @param out XmlSerializer to write the map into. 224 * 225 * @see #writeMapXml(Map, OutputStream) 226 * @see #writeListXml 227 * @see #writeValueXml 228 * @see #readMapXml 229 */ 230 public static final void writeMapXml(Map val, String name, XmlSerializer out) 231 throws XmlPullParserException, java.io.IOException { 232 writeMapXml(val, name, out, null); 233 } 234 235 /** 236 * Flatten a Map into an XmlSerializer. The map can later be read back 237 * with readThisMapXml(). 238 * 239 * @param val The map to be flattened. 240 * @param name Name attribute to include with this list's tag, or null for 241 * none. 242 * @param out XmlSerializer to write the map into. 243 * @param callback Method to call when an Object type is not recognized. 244 * 245 * @see #writeMapXml(Map, OutputStream) 246 * @see #writeListXml 247 * @see #writeValueXml 248 * @see #readMapXml 249 * 250 * @hide 251 */ 252 public static final void writeMapXml(Map val, String name, XmlSerializer out, 253 WriteMapCallback callback) throws XmlPullParserException, java.io.IOException { 254 255 if (val == null) { 256 out.startTag(null, "null"); 257 out.endTag(null, "null"); 258 return; 259 } 260 261 out.startTag(null, "map"); 262 if (name != null) { 263 out.attribute(null, "name", name); 264 } 265 266 writeMapXml(val, out, callback); 267 268 out.endTag(null, "map"); 269 } 270 271 /** 272 * Flatten a Map into an XmlSerializer. The map can later be read back 273 * with readThisMapXml(). This method presumes that the start tag and 274 * name attribute have already been written and does not write an end tag. 275 * 276 * @param val The map to be flattened. 277 * @param out XmlSerializer to write the map into. 278 * 279 * @see #writeMapXml(Map, OutputStream) 280 * @see #writeListXml 281 * @see #writeValueXml 282 * @see #readMapXml 283 * 284 * @hide 285 */ 286 public static final void writeMapXml(Map val, XmlSerializer out, 287 WriteMapCallback callback) throws XmlPullParserException, java.io.IOException { 288 if (val == null) { 289 return; 290 } 291 292 Set s = val.entrySet(); 293 Iterator i = s.iterator(); 294 295 while (i.hasNext()) { 296 Map.Entry e = (Map.Entry)i.next(); 297 writeValueXml(e.getValue(), (String)e.getKey(), out, callback); 298 } 299 } 300 301 /** 302 * Flatten a List into an XmlSerializer. The list can later be read back 303 * with readThisListXml(). 304 * 305 * @param val The list to be flattened. 306 * @param name Name attribute to include with this list's tag, or null for 307 * none. 308 * @param out XmlSerializer to write the list into. 309 * 310 * @see #writeListXml(List, OutputStream) 311 * @see #writeMapXml 312 * @see #writeValueXml 313 * @see #readListXml 314 */ 315 public static final void writeListXml(List val, String name, XmlSerializer out) 316 throws XmlPullParserException, java.io.IOException 317 { 318 if (val == null) { 319 out.startTag(null, "null"); 320 out.endTag(null, "null"); 321 return; 322 } 323 324 out.startTag(null, "list"); 325 if (name != null) { 326 out.attribute(null, "name", name); 327 } 328 329 int N = val.size(); 330 int i=0; 331 while (i < N) { 332 writeValueXml(val.get(i), null, out); 333 i++; 334 } 335 336 out.endTag(null, "list"); 337 } 338 339 public static final void writeSetXml(Set val, String name, XmlSerializer out) 340 throws XmlPullParserException, java.io.IOException { 341 if (val == null) { 342 out.startTag(null, "null"); 343 out.endTag(null, "null"); 344 return; 345 } 346 347 out.startTag(null, "set"); 348 if (name != null) { 349 out.attribute(null, "name", name); 350 } 351 352 for (Object v : val) { 353 writeValueXml(v, null, out); 354 } 355 356 out.endTag(null, "set"); 357 } 358 359 /** 360 * Flatten a byte[] into an XmlSerializer. The list can later be read back 361 * with readThisByteArrayXml(). 362 * 363 * @param val The byte array to be flattened. 364 * @param name Name attribute to include with this array's tag, or null for 365 * none. 366 * @param out XmlSerializer to write the array into. 367 * 368 * @see #writeMapXml 369 * @see #writeValueXml 370 */ 371 public static final void writeByteArrayXml(byte[] val, String name, 372 XmlSerializer out) 373 throws XmlPullParserException, java.io.IOException { 374 375 if (val == null) { 376 out.startTag(null, "null"); 377 out.endTag(null, "null"); 378 return; 379 } 380 381 out.startTag(null, "byte-array"); 382 if (name != null) { 383 out.attribute(null, "name", name); 384 } 385 386 final int N = val.length; 387 out.attribute(null, "num", Integer.toString(N)); 388 389 StringBuilder sb = new StringBuilder(val.length*2); 390 for (int i=0; i<N; i++) { 391 int b = val[i]; 392 int h = b>>4; 393 sb.append(h >= 10 ? ('a'+h-10) : ('0'+h)); 394 h = b&0xff; 395 sb.append(h >= 10 ? ('a'+h-10) : ('0'+h)); 396 } 397 398 out.text(sb.toString()); 399 400 out.endTag(null, "byte-array"); 401 } 402 403 /** 404 * Flatten an int[] into an XmlSerializer. The list can later be read back 405 * with readThisIntArrayXml(). 406 * 407 * @param val The int array to be flattened. 408 * @param name Name attribute to include with this array's tag, or null for 409 * none. 410 * @param out XmlSerializer to write the array into. 411 * 412 * @see #writeMapXml 413 * @see #writeValueXml 414 * @see #readThisIntArrayXml 415 */ 416 public static final void writeIntArrayXml(int[] val, String name, 417 XmlSerializer out) 418 throws XmlPullParserException, java.io.IOException { 419 420 if (val == null) { 421 out.startTag(null, "null"); 422 out.endTag(null, "null"); 423 return; 424 } 425 426 out.startTag(null, "int-array"); 427 if (name != null) { 428 out.attribute(null, "name", name); 429 } 430 431 final int N = val.length; 432 out.attribute(null, "num", Integer.toString(N)); 433 434 for (int i=0; i<N; i++) { 435 out.startTag(null, "item"); 436 out.attribute(null, "value", Integer.toString(val[i])); 437 out.endTag(null, "item"); 438 } 439 440 out.endTag(null, "int-array"); 441 } 442 443 /** 444 * Flatten a long[] into an XmlSerializer. The list can later be read back 445 * with readThisLongArrayXml(). 446 * 447 * @param val The long array to be flattened. 448 * @param name Name attribute to include with this array's tag, or null for 449 * none. 450 * @param out XmlSerializer to write the array into. 451 * 452 * @see #writeMapXml 453 * @see #writeValueXml 454 * @see #readThisIntArrayXml 455 */ 456 public static final void writeLongArrayXml(long[] val, String name, XmlSerializer out) 457 throws XmlPullParserException, java.io.IOException { 458 459 if (val == null) { 460 out.startTag(null, "null"); 461 out.endTag(null, "null"); 462 return; 463 } 464 465 out.startTag(null, "long-array"); 466 if (name != null) { 467 out.attribute(null, "name", name); 468 } 469 470 final int N = val.length; 471 out.attribute(null, "num", Integer.toString(N)); 472 473 for (int i=0; i<N; i++) { 474 out.startTag(null, "item"); 475 out.attribute(null, "value", Long.toString(val[i])); 476 out.endTag(null, "item"); 477 } 478 479 out.endTag(null, "long-array"); 480 } 481 482 /** 483 * Flatten a double[] into an XmlSerializer. The list can later be read back 484 * with readThisDoubleArrayXml(). 485 * 486 * @param val The double array to be flattened. 487 * @param name Name attribute to include with this array's tag, or null for 488 * none. 489 * @param out XmlSerializer to write the array into. 490 * 491 * @see #writeMapXml 492 * @see #writeValueXml 493 * @see #readThisIntArrayXml 494 */ 495 public static final void writeDoubleArrayXml(double[] val, String name, XmlSerializer out) 496 throws XmlPullParserException, java.io.IOException { 497 498 if (val == null) { 499 out.startTag(null, "null"); 500 out.endTag(null, "null"); 501 return; 502 } 503 504 out.startTag(null, "double-array"); 505 if (name != null) { 506 out.attribute(null, "name", name); 507 } 508 509 final int N = val.length; 510 out.attribute(null, "num", Integer.toString(N)); 511 512 for (int i=0; i<N; i++) { 513 out.startTag(null, "item"); 514 out.attribute(null, "value", Double.toString(val[i])); 515 out.endTag(null, "item"); 516 } 517 518 out.endTag(null, "double-array"); 519 } 520 521 /** 522 * Flatten a String[] into an XmlSerializer. The list can later be read back 523 * with readThisStringArrayXml(). 524 * 525 * @param val The String array to be flattened. 526 * @param name Name attribute to include with this array's tag, or null for 527 * none. 528 * @param out XmlSerializer to write the array into. 529 * 530 * @see #writeMapXml 531 * @see #writeValueXml 532 * @see #readThisIntArrayXml 533 */ 534 public static final void writeStringArrayXml(String[] val, String name, XmlSerializer out) 535 throws XmlPullParserException, java.io.IOException { 536 537 if (val == null) { 538 out.startTag(null, "null"); 539 out.endTag(null, "null"); 540 return; 541 } 542 543 out.startTag(null, "string-array"); 544 if (name != null) { 545 out.attribute(null, "name", name); 546 } 547 548 final int N = val.length; 549 out.attribute(null, "num", Integer.toString(N)); 550 551 for (int i=0; i<N; i++) { 552 out.startTag(null, "item"); 553 out.attribute(null, "value", val[i]); 554 out.endTag(null, "item"); 555 } 556 557 out.endTag(null, "string-array"); 558 } 559 560 /** 561 * Flatten a boolean[] into an XmlSerializer. The list can later be read back 562 * with readThisBooleanArrayXml(). 563 * 564 * @param val The boolean array to be flattened. 565 * @param name Name attribute to include with this array's tag, or null for 566 * none. 567 * @param out XmlSerializer to write the array into. 568 * 569 * @see #writeMapXml 570 * @see #writeValueXml 571 * @see #readThisIntArrayXml 572 */ 573 public static final void writeBooleanArrayXml(boolean[] val, String name, XmlSerializer out) 574 throws XmlPullParserException, java.io.IOException { 575 576 if (val == null) { 577 out.startTag(null, "null"); 578 out.endTag(null, "null"); 579 return; 580 } 581 582 out.startTag(null, "boolean-array"); 583 if (name != null) { 584 out.attribute(null, "name", name); 585 } 586 587 final int N = val.length; 588 out.attribute(null, "num", Integer.toString(N)); 589 590 for (int i=0; i<N; i++) { 591 out.startTag(null, "item"); 592 out.attribute(null, "value", Boolean.toString(val[i])); 593 out.endTag(null, "item"); 594 } 595 596 out.endTag(null, "boolean-array"); 597 } 598 599 /** 600 * Flatten an object's value into an XmlSerializer. The value can later 601 * be read back with readThisValueXml(). 602 * 603 * Currently supported value types are: null, String, Integer, Long, 604 * Float, Double Boolean, Map, List. 605 * 606 * @param v The object to be flattened. 607 * @param name Name attribute to include with this value's tag, or null 608 * for none. 609 * @param out XmlSerializer to write the object into. 610 * 611 * @see #writeMapXml 612 * @see #writeListXml 613 * @see #readValueXml 614 */ 615 public static final void writeValueXml(Object v, String name, XmlSerializer out) 616 throws XmlPullParserException, java.io.IOException { 617 writeValueXml(v, name, out, null); 618 } 619 620 /** 621 * Flatten an object's value into an XmlSerializer. The value can later 622 * be read back with readThisValueXml(). 623 * 624 * Currently supported value types are: null, String, Integer, Long, 625 * Float, Double Boolean, Map, List. 626 * 627 * @param v The object to be flattened. 628 * @param name Name attribute to include with this value's tag, or null 629 * for none. 630 * @param out XmlSerializer to write the object into. 631 * @param callback Handler for Object types not recognized. 632 * 633 * @see #writeMapXml 634 * @see #writeListXml 635 * @see #readValueXml 636 */ 637 private static final void writeValueXml(Object v, String name, XmlSerializer out, 638 WriteMapCallback callback) throws XmlPullParserException, java.io.IOException { 639 String typeStr; 640 if (v == null) { 641 out.startTag(null, "null"); 642 if (name != null) { 643 out.attribute(null, "name", name); 644 } 645 out.endTag(null, "null"); 646 return; 647 } else if (v instanceof String) { 648 out.startTag(null, "string"); 649 if (name != null) { 650 out.attribute(null, "name", name); 651 } 652 out.text(v.toString()); 653 out.endTag(null, "string"); 654 return; 655 } else if (v instanceof Integer) { 656 typeStr = "int"; 657 } else if (v instanceof Long) { 658 typeStr = "long"; 659 } else if (v instanceof Float) { 660 typeStr = "float"; 661 } else if (v instanceof Double) { 662 typeStr = "double"; 663 } else if (v instanceof Boolean) { 664 typeStr = "boolean"; 665 } else if (v instanceof byte[]) { 666 writeByteArrayXml((byte[])v, name, out); 667 return; 668 } else if (v instanceof int[]) { 669 writeIntArrayXml((int[])v, name, out); 670 return; 671 } else if (v instanceof long[]) { 672 writeLongArrayXml((long[])v, name, out); 673 return; 674 } else if (v instanceof double[]) { 675 writeDoubleArrayXml((double[])v, name, out); 676 return; 677 } else if (v instanceof String[]) { 678 writeStringArrayXml((String[])v, name, out); 679 return; 680 } else if (v instanceof boolean[]) { 681 writeBooleanArrayXml((boolean[])v, name, out); 682 return; 683 } else if (v instanceof Map) { 684 writeMapXml((Map)v, name, out); 685 return; 686 } else if (v instanceof List) { 687 writeListXml((List) v, name, out); 688 return; 689 } else if (v instanceof Set) { 690 writeSetXml((Set) v, name, out); 691 return; 692 } else if (v instanceof CharSequence) { 693 // XXX This is to allow us to at least write something if 694 // we encounter styled text... but it means we will drop all 695 // of the styling information. :( 696 out.startTag(null, "string"); 697 if (name != null) { 698 out.attribute(null, "name", name); 699 } 700 out.text(v.toString()); 701 out.endTag(null, "string"); 702 return; 703 } else if (callback != null) { 704 callback.writeUnknownObject(v, name, out); 705 return; 706 } else { 707 throw new RuntimeException("writeValueXml: unable to write value " + v); 708 } 709 710 out.startTag(null, typeStr); 711 if (name != null) { 712 out.attribute(null, "name", name); 713 } 714 out.attribute(null, "value", v.toString()); 715 out.endTag(null, typeStr); 716 } 717 718 /** 719 * Read a HashMap from an InputStream containing XML. The stream can 720 * previously have been written by writeMapXml(). 721 * 722 * @param in The InputStream from which to read. 723 * 724 * @return HashMap The resulting map. 725 * 726 * @see #readListXml 727 * @see #readValueXml 728 * @see #readThisMapXml 729 * #see #writeMapXml 730 */ 731 @SuppressWarnings("unchecked") 732 public static final HashMap<String, ?> readMapXml(InputStream in) 733 throws XmlPullParserException, java.io.IOException 734 { 735 XmlPullParser parser = Xml.newPullParser(); 736 parser.setInput(in, StandardCharsets.UTF_8.name()); 737 return (HashMap<String, ?>) readValueXml(parser, new String[1]); 738 } 739 740 /** 741 * Read an ArrayList from an InputStream containing XML. The stream can 742 * previously have been written by writeListXml(). 743 * 744 * @param in The InputStream from which to read. 745 * 746 * @return ArrayList The resulting list. 747 * 748 * @see #readMapXml 749 * @see #readValueXml 750 * @see #readThisListXml 751 * @see #writeListXml 752 */ 753 public static final ArrayList readListXml(InputStream in) 754 throws XmlPullParserException, java.io.IOException 755 { 756 XmlPullParser parser = Xml.newPullParser(); 757 parser.setInput(in, StandardCharsets.UTF_8.name()); 758 return (ArrayList)readValueXml(parser, new String[1]); 759 } 760 761 762 /** 763 * Read a HashSet from an InputStream containing XML. The stream can 764 * previously have been written by writeSetXml(). 765 * 766 * @param in The InputStream from which to read. 767 * 768 * @return HashSet The resulting set. 769 * 770 * @throws XmlPullParserException 771 * @throws java.io.IOException 772 * 773 * @see #readValueXml 774 * @see #readThisSetXml 775 * @see #writeSetXml 776 */ 777 public static final HashSet readSetXml(InputStream in) 778 throws XmlPullParserException, java.io.IOException { 779 XmlPullParser parser = Xml.newPullParser(); 780 parser.setInput(in, null); 781 return (HashSet) readValueXml(parser, new String[1]); 782 } 783 784 /** 785 * Read a HashMap object from an XmlPullParser. The XML data could 786 * previously have been generated by writeMapXml(). The XmlPullParser 787 * must be positioned <em>after</em> the tag that begins the map. 788 * 789 * @param parser The XmlPullParser from which to read the map data. 790 * @param endTag Name of the tag that will end the map, usually "map". 791 * @param name An array of one string, used to return the name attribute 792 * of the map's tag. 793 * 794 * @return HashMap The newly generated map. 795 * 796 * @see #readMapXml 797 */ 798 public static final HashMap<String, ?> readThisMapXml(XmlPullParser parser, String endTag, 799 String[] name) throws XmlPullParserException, java.io.IOException { 800 return readThisMapXml(parser, endTag, name, null); 801 } 802 803 /** 804 * Read a HashMap object from an XmlPullParser. The XML data could 805 * previously have been generated by writeMapXml(). The XmlPullParser 806 * must be positioned <em>after</em> the tag that begins the map. 807 * 808 * @param parser The XmlPullParser from which to read the map data. 809 * @param endTag Name of the tag that will end the map, usually "map". 810 * @param name An array of one string, used to return the name attribute 811 * of the map's tag. 812 * 813 * @return HashMap The newly generated map. 814 * 815 * @see #readMapXml 816 * @hide 817 */ 818 public static final HashMap<String, ?> readThisMapXml(XmlPullParser parser, String endTag, 819 String[] name, ReadMapCallback callback) 820 throws XmlPullParserException, java.io.IOException 821 { 822 HashMap<String, Object> map = new HashMap<String, Object>(); 823 824 int eventType = parser.getEventType(); 825 do { 826 if (eventType == parser.START_TAG) { 827 Object val = readThisValueXml(parser, name, callback, false); 828 map.put(name[0], val); 829 } else if (eventType == parser.END_TAG) { 830 if (parser.getName().equals(endTag)) { 831 return map; 832 } 833 throw new XmlPullParserException( 834 "Expected " + endTag + " end tag at: " + parser.getName()); 835 } 836 eventType = parser.next(); 837 } while (eventType != parser.END_DOCUMENT); 838 839 throw new XmlPullParserException( 840 "Document ended before " + endTag + " end tag"); 841 } 842 843 /** 844 * Like {@link #readThisMapXml}, but returns an ArrayMap instead of HashMap. 845 * @hide 846 */ 847 public static final ArrayMap<String, ?> readThisArrayMapXml(XmlPullParser parser, String endTag, 848 String[] name, ReadMapCallback callback) 849 throws XmlPullParserException, java.io.IOException 850 { 851 ArrayMap<String, Object> map = new ArrayMap<>(); 852 853 int eventType = parser.getEventType(); 854 do { 855 if (eventType == parser.START_TAG) { 856 Object val = readThisValueXml(parser, name, callback, true); 857 map.put(name[0], val); 858 } else if (eventType == parser.END_TAG) { 859 if (parser.getName().equals(endTag)) { 860 return map; 861 } 862 throw new XmlPullParserException( 863 "Expected " + endTag + " end tag at: " + parser.getName()); 864 } 865 eventType = parser.next(); 866 } while (eventType != parser.END_DOCUMENT); 867 868 throw new XmlPullParserException( 869 "Document ended before " + endTag + " end tag"); 870 } 871 872 /** 873 * Read an ArrayList object from an XmlPullParser. The XML data could 874 * previously have been generated by writeListXml(). The XmlPullParser 875 * must be positioned <em>after</em> the tag that begins the list. 876 * 877 * @param parser The XmlPullParser from which to read the list data. 878 * @param endTag Name of the tag that will end the list, usually "list". 879 * @param name An array of one string, used to return the name attribute 880 * of the list's tag. 881 * 882 * @return HashMap The newly generated list. 883 * 884 * @see #readListXml 885 */ 886 public static final ArrayList readThisListXml(XmlPullParser parser, String endTag, 887 String[] name) throws XmlPullParserException, java.io.IOException { 888 return readThisListXml(parser, endTag, name, null, false); 889 } 890 891 /** 892 * Read an ArrayList object from an XmlPullParser. The XML data could 893 * previously have been generated by writeListXml(). The XmlPullParser 894 * must be positioned <em>after</em> the tag that begins the list. 895 * 896 * @param parser The XmlPullParser from which to read the list data. 897 * @param endTag Name of the tag that will end the list, usually "list". 898 * @param name An array of one string, used to return the name attribute 899 * of the list's tag. 900 * 901 * @return HashMap The newly generated list. 902 * 903 * @see #readListXml 904 */ 905 private static final ArrayList readThisListXml(XmlPullParser parser, String endTag, 906 String[] name, ReadMapCallback callback, boolean arrayMap) 907 throws XmlPullParserException, java.io.IOException { 908 ArrayList list = new ArrayList(); 909 910 int eventType = parser.getEventType(); 911 do { 912 if (eventType == parser.START_TAG) { 913 Object val = readThisValueXml(parser, name, callback, arrayMap); 914 list.add(val); 915 //System.out.println("Adding to list: " + val); 916 } else if (eventType == parser.END_TAG) { 917 if (parser.getName().equals(endTag)) { 918 return list; 919 } 920 throw new XmlPullParserException( 921 "Expected " + endTag + " end tag at: " + parser.getName()); 922 } 923 eventType = parser.next(); 924 } while (eventType != parser.END_DOCUMENT); 925 926 throw new XmlPullParserException( 927 "Document ended before " + endTag + " end tag"); 928 } 929 930 /** 931 * Read a HashSet object from an XmlPullParser. The XML data could previously 932 * have been generated by writeSetXml(). The XmlPullParser must be positioned 933 * <em>after</em> the tag that begins the set. 934 * 935 * @param parser The XmlPullParser from which to read the set data. 936 * @param endTag Name of the tag that will end the set, usually "set". 937 * @param name An array of one string, used to return the name attribute 938 * of the set's tag. 939 * 940 * @return HashSet The newly generated set. 941 * 942 * @throws XmlPullParserException 943 * @throws java.io.IOException 944 * 945 * @see #readSetXml 946 */ 947 public static final HashSet readThisSetXml(XmlPullParser parser, String endTag, String[] name) 948 throws XmlPullParserException, java.io.IOException { 949 return readThisSetXml(parser, endTag, name, null, false); 950 } 951 952 /** 953 * Read a HashSet object from an XmlPullParser. The XML data could previously 954 * have been generated by writeSetXml(). The XmlPullParser must be positioned 955 * <em>after</em> the tag that begins the set. 956 * 957 * @param parser The XmlPullParser from which to read the set data. 958 * @param endTag Name of the tag that will end the set, usually "set". 959 * @param name An array of one string, used to return the name attribute 960 * of the set's tag. 961 * 962 * @return HashSet The newly generated set. 963 * 964 * @throws XmlPullParserException 965 * @throws java.io.IOException 966 * 967 * @see #readSetXml 968 * @hide 969 */ 970 private static final HashSet readThisSetXml(XmlPullParser parser, String endTag, String[] name, 971 ReadMapCallback callback, boolean arrayMap) 972 throws XmlPullParserException, java.io.IOException { 973 HashSet set = new HashSet(); 974 975 int eventType = parser.getEventType(); 976 do { 977 if (eventType == parser.START_TAG) { 978 Object val = readThisValueXml(parser, name, callback, arrayMap); 979 set.add(val); 980 //System.out.println("Adding to set: " + val); 981 } else if (eventType == parser.END_TAG) { 982 if (parser.getName().equals(endTag)) { 983 return set; 984 } 985 throw new XmlPullParserException( 986 "Expected " + endTag + " end tag at: " + parser.getName()); 987 } 988 eventType = parser.next(); 989 } while (eventType != parser.END_DOCUMENT); 990 991 throw new XmlPullParserException( 992 "Document ended before " + endTag + " end tag"); 993 } 994 995 /** 996 * Read an int[] object from an XmlPullParser. The XML data could 997 * previously have been generated by writeIntArrayXml(). The XmlPullParser 998 * must be positioned <em>after</em> the tag that begins the list. 999 * 1000 * @param parser The XmlPullParser from which to read the list data. 1001 * @param endTag Name of the tag that will end the list, usually "list". 1002 * @param name An array of one string, used to return the name attribute 1003 * of the list's tag. 1004 * 1005 * @return Returns a newly generated int[]. 1006 * 1007 * @see #readListXml 1008 */ 1009 public static final int[] readThisIntArrayXml(XmlPullParser parser, 1010 String endTag, String[] name) 1011 throws XmlPullParserException, java.io.IOException { 1012 1013 int num; 1014 try { 1015 num = Integer.parseInt(parser.getAttributeValue(null, "num")); 1016 } catch (NullPointerException e) { 1017 throw new XmlPullParserException( 1018 "Need num attribute in byte-array"); 1019 } catch (NumberFormatException e) { 1020 throw new XmlPullParserException( 1021 "Not a number in num attribute in byte-array"); 1022 } 1023 parser.next(); 1024 1025 int[] array = new int[num]; 1026 int i = 0; 1027 1028 int eventType = parser.getEventType(); 1029 do { 1030 if (eventType == parser.START_TAG) { 1031 if (parser.getName().equals("item")) { 1032 try { 1033 array[i] = Integer.parseInt( 1034 parser.getAttributeValue(null, "value")); 1035 } catch (NullPointerException e) { 1036 throw new XmlPullParserException( 1037 "Need value attribute in item"); 1038 } catch (NumberFormatException e) { 1039 throw new XmlPullParserException( 1040 "Not a number in value attribute in item"); 1041 } 1042 } else { 1043 throw new XmlPullParserException( 1044 "Expected item tag at: " + parser.getName()); 1045 } 1046 } else if (eventType == parser.END_TAG) { 1047 if (parser.getName().equals(endTag)) { 1048 return array; 1049 } else if (parser.getName().equals("item")) { 1050 i++; 1051 } else { 1052 throw new XmlPullParserException( 1053 "Expected " + endTag + " end tag at: " 1054 + parser.getName()); 1055 } 1056 } 1057 eventType = parser.next(); 1058 } while (eventType != parser.END_DOCUMENT); 1059 1060 throw new XmlPullParserException( 1061 "Document ended before " + endTag + " end tag"); 1062 } 1063 1064 /** 1065 * Read a long[] object from an XmlPullParser. The XML data could 1066 * previously have been generated by writeLongArrayXml(). The XmlPullParser 1067 * must be positioned <em>after</em> the tag that begins the list. 1068 * 1069 * @param parser The XmlPullParser from which to read the list data. 1070 * @param endTag Name of the tag that will end the list, usually "list". 1071 * @param name An array of one string, used to return the name attribute 1072 * of the list's tag. 1073 * 1074 * @return Returns a newly generated long[]. 1075 * 1076 * @see #readListXml 1077 */ 1078 public static final long[] readThisLongArrayXml(XmlPullParser parser, 1079 String endTag, String[] name) 1080 throws XmlPullParserException, java.io.IOException { 1081 1082 int num; 1083 try { 1084 num = Integer.parseInt(parser.getAttributeValue(null, "num")); 1085 } catch (NullPointerException e) { 1086 throw new XmlPullParserException("Need num attribute in long-array"); 1087 } catch (NumberFormatException e) { 1088 throw new XmlPullParserException("Not a number in num attribute in long-array"); 1089 } 1090 parser.next(); 1091 1092 long[] array = new long[num]; 1093 int i = 0; 1094 1095 int eventType = parser.getEventType(); 1096 do { 1097 if (eventType == parser.START_TAG) { 1098 if (parser.getName().equals("item")) { 1099 try { 1100 array[i] = Long.parseLong(parser.getAttributeValue(null, "value")); 1101 } catch (NullPointerException e) { 1102 throw new XmlPullParserException("Need value attribute in item"); 1103 } catch (NumberFormatException e) { 1104 throw new XmlPullParserException("Not a number in value attribute in item"); 1105 } 1106 } else { 1107 throw new XmlPullParserException("Expected item tag at: " + parser.getName()); 1108 } 1109 } else if (eventType == parser.END_TAG) { 1110 if (parser.getName().equals(endTag)) { 1111 return array; 1112 } else if (parser.getName().equals("item")) { 1113 i++; 1114 } else { 1115 throw new XmlPullParserException("Expected " + endTag + " end tag at: " + 1116 parser.getName()); 1117 } 1118 } 1119 eventType = parser.next(); 1120 } while (eventType != parser.END_DOCUMENT); 1121 1122 throw new XmlPullParserException("Document ended before " + endTag + " end tag"); 1123 } 1124 1125 /** 1126 * Read a double[] object from an XmlPullParser. The XML data could 1127 * previously have been generated by writeDoubleArrayXml(). The XmlPullParser 1128 * must be positioned <em>after</em> the tag that begins the list. 1129 * 1130 * @param parser The XmlPullParser from which to read the list data. 1131 * @param endTag Name of the tag that will end the list, usually "double-array". 1132 * @param name An array of one string, used to return the name attribute 1133 * of the list's tag. 1134 * 1135 * @return Returns a newly generated double[]. 1136 * 1137 * @see #readListXml 1138 */ 1139 public static final double[] readThisDoubleArrayXml(XmlPullParser parser, String endTag, 1140 String[] name) throws XmlPullParserException, java.io.IOException { 1141 1142 int num; 1143 try { 1144 num = Integer.parseInt(parser.getAttributeValue(null, "num")); 1145 } catch (NullPointerException e) { 1146 throw new XmlPullParserException("Need num attribute in double-array"); 1147 } catch (NumberFormatException e) { 1148 throw new XmlPullParserException("Not a number in num attribute in double-array"); 1149 } 1150 parser.next(); 1151 1152 double[] array = new double[num]; 1153 int i = 0; 1154 1155 int eventType = parser.getEventType(); 1156 do { 1157 if (eventType == parser.START_TAG) { 1158 if (parser.getName().equals("item")) { 1159 try { 1160 array[i] = Double.parseDouble(parser.getAttributeValue(null, "value")); 1161 } catch (NullPointerException e) { 1162 throw new XmlPullParserException("Need value attribute in item"); 1163 } catch (NumberFormatException e) { 1164 throw new XmlPullParserException("Not a number in value attribute in item"); 1165 } 1166 } else { 1167 throw new XmlPullParserException("Expected item tag at: " + parser.getName()); 1168 } 1169 } else if (eventType == parser.END_TAG) { 1170 if (parser.getName().equals(endTag)) { 1171 return array; 1172 } else if (parser.getName().equals("item")) { 1173 i++; 1174 } else { 1175 throw new XmlPullParserException("Expected " + endTag + " end tag at: " + 1176 parser.getName()); 1177 } 1178 } 1179 eventType = parser.next(); 1180 } while (eventType != parser.END_DOCUMENT); 1181 1182 throw new XmlPullParserException("Document ended before " + endTag + " end tag"); 1183 } 1184 1185 /** 1186 * Read a String[] object from an XmlPullParser. The XML data could 1187 * previously have been generated by writeStringArrayXml(). The XmlPullParser 1188 * must be positioned <em>after</em> the tag that begins the list. 1189 * 1190 * @param parser The XmlPullParser from which to read the list data. 1191 * @param endTag Name of the tag that will end the list, usually "string-array". 1192 * @param name An array of one string, used to return the name attribute 1193 * of the list's tag. 1194 * 1195 * @return Returns a newly generated String[]. 1196 * 1197 * @see #readListXml 1198 */ 1199 public static final String[] readThisStringArrayXml(XmlPullParser parser, String endTag, 1200 String[] name) throws XmlPullParserException, java.io.IOException { 1201 1202 int num; 1203 try { 1204 num = Integer.parseInt(parser.getAttributeValue(null, "num")); 1205 } catch (NullPointerException e) { 1206 throw new XmlPullParserException("Need num attribute in string-array"); 1207 } catch (NumberFormatException e) { 1208 throw new XmlPullParserException("Not a number in num attribute in string-array"); 1209 } 1210 parser.next(); 1211 1212 String[] array = new String[num]; 1213 int i = 0; 1214 1215 int eventType = parser.getEventType(); 1216 do { 1217 if (eventType == parser.START_TAG) { 1218 if (parser.getName().equals("item")) { 1219 try { 1220 array[i] = parser.getAttributeValue(null, "value"); 1221 } catch (NullPointerException e) { 1222 throw new XmlPullParserException("Need value attribute in item"); 1223 } catch (NumberFormatException e) { 1224 throw new XmlPullParserException("Not a number in value attribute in item"); 1225 } 1226 } else { 1227 throw new XmlPullParserException("Expected item tag at: " + parser.getName()); 1228 } 1229 } else if (eventType == parser.END_TAG) { 1230 if (parser.getName().equals(endTag)) { 1231 return array; 1232 } else if (parser.getName().equals("item")) { 1233 i++; 1234 } else { 1235 throw new XmlPullParserException("Expected " + endTag + " end tag at: " + 1236 parser.getName()); 1237 } 1238 } 1239 eventType = parser.next(); 1240 } while (eventType != parser.END_DOCUMENT); 1241 1242 throw new XmlPullParserException("Document ended before " + endTag + " end tag"); 1243 } 1244 1245 /** 1246 * Read a boolean[] object from an XmlPullParser. The XML data could 1247 * previously have been generated by writeBooleanArrayXml(). The XmlPullParser 1248 * must be positioned <em>after</em> the tag that begins the list. 1249 * 1250 * @param parser The XmlPullParser from which to read the list data. 1251 * @param endTag Name of the tag that will end the list, usually "string-array". 1252 * @param name An array of one string, used to return the name attribute 1253 * of the list's tag. 1254 * 1255 * @return Returns a newly generated boolean[]. 1256 * 1257 * @see #readListXml 1258 */ 1259 public static final boolean[] readThisBooleanArrayXml(XmlPullParser parser, String endTag, 1260 String[] name) throws XmlPullParserException, java.io.IOException { 1261 1262 int num; 1263 try { 1264 num = Integer.parseInt(parser.getAttributeValue(null, "num")); 1265 } catch (NullPointerException e) { 1266 throw new XmlPullParserException("Need num attribute in string-array"); 1267 } catch (NumberFormatException e) { 1268 throw new XmlPullParserException("Not a number in num attribute in string-array"); 1269 } 1270 parser.next(); 1271 1272 boolean[] array = new boolean[num]; 1273 int i = 0; 1274 1275 int eventType = parser.getEventType(); 1276 do { 1277 if (eventType == parser.START_TAG) { 1278 if (parser.getName().equals("item")) { 1279 try { 1280 array[i] = Boolean.valueOf(parser.getAttributeValue(null, "value")); 1281 } catch (NullPointerException e) { 1282 throw new XmlPullParserException("Need value attribute in item"); 1283 } catch (NumberFormatException e) { 1284 throw new XmlPullParserException("Not a number in value attribute in item"); 1285 } 1286 } else { 1287 throw new XmlPullParserException("Expected item tag at: " + parser.getName()); 1288 } 1289 } else if (eventType == parser.END_TAG) { 1290 if (parser.getName().equals(endTag)) { 1291 return array; 1292 } else if (parser.getName().equals("item")) { 1293 i++; 1294 } else { 1295 throw new XmlPullParserException("Expected " + endTag + " end tag at: " + 1296 parser.getName()); 1297 } 1298 } 1299 eventType = parser.next(); 1300 } while (eventType != parser.END_DOCUMENT); 1301 1302 throw new XmlPullParserException("Document ended before " + endTag + " end tag"); 1303 } 1304 1305 /** 1306 * Read a flattened object from an XmlPullParser. The XML data could 1307 * previously have been written with writeMapXml(), writeListXml(), or 1308 * writeValueXml(). The XmlPullParser must be positioned <em>at</em> the 1309 * tag that defines the value. 1310 * 1311 * @param parser The XmlPullParser from which to read the object. 1312 * @param name An array of one string, used to return the name attribute 1313 * of the value's tag. 1314 * 1315 * @return Object The newly generated value object. 1316 * 1317 * @see #readMapXml 1318 * @see #readListXml 1319 * @see #writeValueXml 1320 */ 1321 public static final Object readValueXml(XmlPullParser parser, String[] name) 1322 throws XmlPullParserException, java.io.IOException 1323 { 1324 int eventType = parser.getEventType(); 1325 do { 1326 if (eventType == parser.START_TAG) { 1327 return readThisValueXml(parser, name, null, false); 1328 } else if (eventType == parser.END_TAG) { 1329 throw new XmlPullParserException( 1330 "Unexpected end tag at: " + parser.getName()); 1331 } else if (eventType == parser.TEXT) { 1332 throw new XmlPullParserException( 1333 "Unexpected text: " + parser.getText()); 1334 } 1335 eventType = parser.next(); 1336 } while (eventType != parser.END_DOCUMENT); 1337 1338 throw new XmlPullParserException( 1339 "Unexpected end of document"); 1340 } 1341 1342 private static final Object readThisValueXml(XmlPullParser parser, String[] name, 1343 ReadMapCallback callback, boolean arrayMap) 1344 throws XmlPullParserException, java.io.IOException { 1345 final String valueName = parser.getAttributeValue(null, "name"); 1346 final String tagName = parser.getName(); 1347 1348 //System.out.println("Reading this value tag: " + tagName + ", name=" + valueName); 1349 1350 Object res; 1351 1352 if (tagName.equals("null")) { 1353 res = null; 1354 } else if (tagName.equals("string")) { 1355 String value = ""; 1356 int eventType; 1357 while ((eventType = parser.next()) != parser.END_DOCUMENT) { 1358 if (eventType == parser.END_TAG) { 1359 if (parser.getName().equals("string")) { 1360 name[0] = valueName; 1361 //System.out.println("Returning value for " + valueName + ": " + value); 1362 return value; 1363 } 1364 throw new XmlPullParserException( 1365 "Unexpected end tag in <string>: " + parser.getName()); 1366 } else if (eventType == parser.TEXT) { 1367 value += parser.getText(); 1368 } else if (eventType == parser.START_TAG) { 1369 throw new XmlPullParserException( 1370 "Unexpected start tag in <string>: " + parser.getName()); 1371 } 1372 } 1373 throw new XmlPullParserException( 1374 "Unexpected end of document in <string>"); 1375 } else if ((res = readThisPrimitiveValueXml(parser, tagName)) != null) { 1376 // all work already done by readThisPrimitiveValueXml 1377 } else if (tagName.equals("int-array")) { 1378 res = readThisIntArrayXml(parser, "int-array", name); 1379 name[0] = valueName; 1380 //System.out.println("Returning value for " + valueName + ": " + res); 1381 return res; 1382 } else if (tagName.equals("long-array")) { 1383 res = readThisLongArrayXml(parser, "long-array", name); 1384 name[0] = valueName; 1385 //System.out.println("Returning value for " + valueName + ": " + res); 1386 return res; 1387 } else if (tagName.equals("double-array")) { 1388 res = readThisDoubleArrayXml(parser, "double-array", name); 1389 name[0] = valueName; 1390 //System.out.println("Returning value for " + valueName + ": " + res); 1391 return res; 1392 } else if (tagName.equals("string-array")) { 1393 res = readThisStringArrayXml(parser, "string-array", name); 1394 name[0] = valueName; 1395 //System.out.println("Returning value for " + valueName + ": " + res); 1396 return res; 1397 } else if (tagName.equals("boolean-array")) { 1398 res = readThisBooleanArrayXml(parser, "boolean-array", name); 1399 name[0] = valueName; 1400 //System.out.println("Returning value for " + valueName + ": " + res); 1401 return res; 1402 } else if (tagName.equals("map")) { 1403 parser.next(); 1404 res = arrayMap 1405 ? readThisArrayMapXml(parser, "map", name, callback) 1406 : readThisMapXml(parser, "map", name, callback); 1407 name[0] = valueName; 1408 //System.out.println("Returning value for " + valueName + ": " + res); 1409 return res; 1410 } else if (tagName.equals("list")) { 1411 parser.next(); 1412 res = readThisListXml(parser, "list", name, callback, arrayMap); 1413 name[0] = valueName; 1414 //System.out.println("Returning value for " + valueName + ": " + res); 1415 return res; 1416 } else if (tagName.equals("set")) { 1417 parser.next(); 1418 res = readThisSetXml(parser, "set", name, callback, arrayMap); 1419 name[0] = valueName; 1420 //System.out.println("Returning value for " + valueName + ": " + res); 1421 return res; 1422 } else if (callback != null) { 1423 res = callback.readThisUnknownObjectXml(parser, tagName); 1424 name[0] = valueName; 1425 return res; 1426 } else { 1427 throw new XmlPullParserException("Unknown tag: " + tagName); 1428 } 1429 1430 // Skip through to end tag. 1431 int eventType; 1432 while ((eventType = parser.next()) != parser.END_DOCUMENT) { 1433 if (eventType == parser.END_TAG) { 1434 if (parser.getName().equals(tagName)) { 1435 name[0] = valueName; 1436 //System.out.println("Returning value for " + valueName + ": " + res); 1437 return res; 1438 } 1439 throw new XmlPullParserException( 1440 "Unexpected end tag in <" + tagName + ">: " + parser.getName()); 1441 } else if (eventType == parser.TEXT) { 1442 throw new XmlPullParserException( 1443 "Unexpected text in <" + tagName + ">: " + parser.getName()); 1444 } else if (eventType == parser.START_TAG) { 1445 throw new XmlPullParserException( 1446 "Unexpected start tag in <" + tagName + ">: " + parser.getName()); 1447 } 1448 } 1449 throw new XmlPullParserException( 1450 "Unexpected end of document in <" + tagName + ">"); 1451 } 1452 1453 private static final Object readThisPrimitiveValueXml(XmlPullParser parser, String tagName) 1454 throws XmlPullParserException, java.io.IOException 1455 { 1456 try { 1457 if (tagName.equals("int")) { 1458 return Integer.parseInt(parser.getAttributeValue(null, "value")); 1459 } else if (tagName.equals("long")) { 1460 return Long.valueOf(parser.getAttributeValue(null, "value")); 1461 } else if (tagName.equals("float")) { 1462 return new Float(parser.getAttributeValue(null, "value")); 1463 } else if (tagName.equals("double")) { 1464 return new Double(parser.getAttributeValue(null, "value")); 1465 } else if (tagName.equals("boolean")) { 1466 return Boolean.valueOf(parser.getAttributeValue(null, "value")); 1467 } else { 1468 return null; 1469 } 1470 } catch (NullPointerException e) { 1471 throw new XmlPullParserException("Need value attribute in <" + tagName + ">"); 1472 } catch (NumberFormatException e) { 1473 throw new XmlPullParserException( 1474 "Not a number in value attribute in <" + tagName + ">"); 1475 } 1476 } 1477 1478 public static final void beginDocument(XmlPullParser parser, String firstElementName) throws XmlPullParserException, IOException 1479 { 1480 int type; 1481 while ((type=parser.next()) != parser.START_TAG 1482 && type != parser.END_DOCUMENT) { 1483 ; 1484 } 1485 1486 if (type != parser.START_TAG) { 1487 throw new XmlPullParserException("No start tag found"); 1488 } 1489 1490 if (!parser.getName().equals(firstElementName)) { 1491 throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() + 1492 ", expected " + firstElementName); 1493 } 1494 } 1495 1496 public static final void nextElement(XmlPullParser parser) throws XmlPullParserException, IOException 1497 { 1498 int type; 1499 while ((type=parser.next()) != parser.START_TAG 1500 && type != parser.END_DOCUMENT) { 1501 ; 1502 } 1503 } 1504 1505 public static boolean nextElementWithin(XmlPullParser parser, int outerDepth) 1506 throws IOException, XmlPullParserException { 1507 for (;;) { 1508 int type = parser.next(); 1509 if (type == XmlPullParser.END_DOCUMENT 1510 || (type == XmlPullParser.END_TAG && parser.getDepth() == outerDepth)) { 1511 return false; 1512 } 1513 if (type == XmlPullParser.START_TAG 1514 && parser.getDepth() == outerDepth + 1) { 1515 return true; 1516 } 1517 } 1518 } 1519 1520 public static int readIntAttribute(XmlPullParser in, String name, int defaultValue) { 1521 final String value = in.getAttributeValue(null, name); 1522 try { 1523 return Integer.parseInt(value); 1524 } catch (NumberFormatException e) { 1525 return defaultValue; 1526 } 1527 } 1528 1529 public static int readIntAttribute(XmlPullParser in, String name) throws IOException { 1530 final String value = in.getAttributeValue(null, name); 1531 try { 1532 return Integer.parseInt(value); 1533 } catch (NumberFormatException e) { 1534 throw new ProtocolException("problem parsing " + name + "=" + value + " as int"); 1535 } 1536 } 1537 1538 public static void writeIntAttribute(XmlSerializer out, String name, int value) 1539 throws IOException { 1540 out.attribute(null, name, Integer.toString(value)); 1541 } 1542 1543 public static long readLongAttribute(XmlPullParser in, String name, long defaultValue) { 1544 final String value = in.getAttributeValue(null, name); 1545 try { 1546 return Long.parseLong(value); 1547 } catch (NumberFormatException e) { 1548 return defaultValue; 1549 } 1550 } 1551 1552 public static long readLongAttribute(XmlPullParser in, String name) throws IOException { 1553 final String value = in.getAttributeValue(null, name); 1554 try { 1555 return Long.parseLong(value); 1556 } catch (NumberFormatException e) { 1557 throw new ProtocolException("problem parsing " + name + "=" + value + " as long"); 1558 } 1559 } 1560 1561 public static void writeLongAttribute(XmlSerializer out, String name, long value) 1562 throws IOException { 1563 out.attribute(null, name, Long.toString(value)); 1564 } 1565 1566 public static float readFloatAttribute(XmlPullParser in, String name) throws IOException { 1567 final String value = in.getAttributeValue(null, name); 1568 try { 1569 return Float.parseFloat(value); 1570 } catch (NumberFormatException e) { 1571 throw new ProtocolException("problem parsing " + name + "=" + value + " as long"); 1572 } 1573 } 1574 1575 public static void writeFloatAttribute(XmlSerializer out, String name, float value) 1576 throws IOException { 1577 out.attribute(null, name, Float.toString(value)); 1578 } 1579 1580 public static boolean readBooleanAttribute(XmlPullParser in, String name) { 1581 final String value = in.getAttributeValue(null, name); 1582 return Boolean.parseBoolean(value); 1583 } 1584 1585 public static boolean readBooleanAttribute(XmlPullParser in, String name, 1586 boolean defaultValue) { 1587 final String value = in.getAttributeValue(null, name); 1588 if (value == null) { 1589 return defaultValue; 1590 } else { 1591 return Boolean.parseBoolean(value); 1592 } 1593 } 1594 1595 public static void writeBooleanAttribute(XmlSerializer out, String name, boolean value) 1596 throws IOException { 1597 out.attribute(null, name, Boolean.toString(value)); 1598 } 1599 1600 public static Uri readUriAttribute(XmlPullParser in, String name) { 1601 final String value = in.getAttributeValue(null, name); 1602 return (value != null) ? Uri.parse(value) : null; 1603 } 1604 1605 public static void writeUriAttribute(XmlSerializer out, String name, Uri value) 1606 throws IOException { 1607 if (value != null) { 1608 out.attribute(null, name, value.toString()); 1609 } 1610 } 1611 1612 public static String readStringAttribute(XmlPullParser in, String name) { 1613 return in.getAttributeValue(null, name); 1614 } 1615 1616 public static void writeStringAttribute(XmlSerializer out, String name, String value) 1617 throws IOException { 1618 if (value != null) { 1619 out.attribute(null, name, value); 1620 } 1621 } 1622 1623 public static byte[] readByteArrayAttribute(XmlPullParser in, String name) { 1624 final String value = in.getAttributeValue(null, name); 1625 if (value != null) { 1626 return Base64.decode(value, Base64.DEFAULT); 1627 } else { 1628 return null; 1629 } 1630 } 1631 1632 public static void writeByteArrayAttribute(XmlSerializer out, String name, byte[] value) 1633 throws IOException { 1634 if (value != null) { 1635 out.attribute(null, name, Base64.encodeToString(value, Base64.DEFAULT)); 1636 } 1637 } 1638 1639 public static Bitmap readBitmapAttribute(XmlPullParser in, String name) { 1640 final byte[] value = readByteArrayAttribute(in, name); 1641 if (value != null) { 1642 return BitmapFactory.decodeByteArray(value, 0, value.length); 1643 } else { 1644 return null; 1645 } 1646 } 1647 1648 @Deprecated 1649 public static void writeBitmapAttribute(XmlSerializer out, String name, Bitmap value) 1650 throws IOException { 1651 if (value != null) { 1652 final ByteArrayOutputStream os = new ByteArrayOutputStream(); 1653 value.compress(CompressFormat.PNG, 90, os); 1654 writeByteArrayAttribute(out, name, os.toByteArray()); 1655 } 1656 } 1657 1658 /** @hide */ 1659 public interface WriteMapCallback { 1660 /** 1661 * Called from writeMapXml when an Object type is not recognized. The implementer 1662 * must write out the entire element including start and end tags. 1663 * 1664 * @param v The object to be written out 1665 * @param name The mapping key for v. Must be written into the "name" attribute of the 1666 * start tag. 1667 * @param out The XML output stream. 1668 * @throws XmlPullParserException on unrecognized Object type. 1669 * @throws IOException on XmlSerializer serialization errors. 1670 * @hide 1671 */ 1672 public void writeUnknownObject(Object v, String name, XmlSerializer out) 1673 throws XmlPullParserException, IOException; 1674 } 1675 1676 /** @hide */ 1677 public interface ReadMapCallback { 1678 /** 1679 * Called from readThisMapXml when a START_TAG is not recognized. The input stream 1680 * is positioned within the start tag so that attributes can be read using in.getAttribute. 1681 * 1682 * @param in the XML input stream 1683 * @param tag the START_TAG that was not recognized. 1684 * @return the Object parsed from the stream which will be put into the map. 1685 * @throws XmlPullParserException if the START_TAG is not recognized. 1686 * @throws IOException on XmlPullParser serialization errors. 1687 * @hide 1688 */ 1689 public Object readThisUnknownObjectXml(XmlPullParser in, String tag) 1690 throws XmlPullParserException, IOException; 1691 } 1692} 1693