Home | History | Annotate | Download | only in utils
      1 // line 1 "XmlReader.rl"
      2 // Do not edit this file! Generated by Ragel.
      3 // Ragel.exe -G2 -J -o XmlReader.java XmlReader.rl
      4 /*******************************************************************************
      5  * Copyright 2011 See AUTHORS file.
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *   http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  ******************************************************************************/
     19 
     20 package com.badlogic.gdx.utils;
     21 
     22 import java.io.IOException;
     23 import java.io.InputStream;
     24 import java.io.InputStreamReader;
     25 import java.io.Reader;
     26 
     27 import com.badlogic.gdx.files.FileHandle;
     28 import com.badlogic.gdx.utils.ObjectMap.Entry;
     29 
     30 /** Lightweight XML parser. Supports a subset of XML features: elements, attributes, text, predefined entities, CDATA, mixed
     31  * content. Namespaces are parsed as part of the element or attribute name. Prologs and doctypes are ignored. Only 8-bit character
     32  * encodings are supported. Input is assumed to be well formed.<br>
     33  * <br>
     34  * The default behavior is to parse the XML into a DOM. Extends this class and override methods to perform event driven parsing.
     35  * When this is done, the parse methods will return null.
     36  * @author Nathan Sweet */
     37 public class XmlReader {
     38 	private final Array<Element> elements = new Array(8);
     39 	private Element root, current;
     40 	private final StringBuilder textBuffer = new StringBuilder(64);
     41 
     42 	public Element parse (String xml) {
     43 		char[] data = xml.toCharArray();
     44 		return parse(data, 0, data.length);
     45 	}
     46 
     47 	public Element parse (Reader reader) throws IOException {
     48 		try {
     49 			char[] data = new char[1024];
     50 			int offset = 0;
     51 			while (true) {
     52 				int length = reader.read(data, offset, data.length - offset);
     53 				if (length == -1) break;
     54 				if (length == 0) {
     55 					char[] newData = new char[data.length * 2];
     56 					System.arraycopy(data, 0, newData, 0, data.length);
     57 					data = newData;
     58 				} else
     59 					offset += length;
     60 			}
     61 			return parse(data, 0, offset);
     62 		} catch (IOException ex) {
     63 			throw new SerializationException(ex);
     64 		} finally {
     65 			StreamUtils.closeQuietly(reader);
     66 		}
     67 	}
     68 
     69 	public Element parse (InputStream input) throws IOException {
     70 		try {
     71 			return parse(new InputStreamReader(input, "UTF-8"));
     72 		} catch (IOException ex) {
     73 			throw new SerializationException(ex);
     74 		} finally {
     75 			StreamUtils.closeQuietly(input);
     76 		}
     77 	}
     78 
     79 	public Element parse (FileHandle file) throws IOException {
     80 		try {
     81 			return parse(file.reader("UTF-8"));
     82 		} catch (Exception ex) {
     83 			throw new SerializationException("Error parsing file: " + file, ex);
     84 		}
     85 	}
     86 
     87 	public Element parse (char[] data, int offset, int length) {
     88 		int cs, p = offset, pe = length;
     89 
     90 		int s = 0;
     91 		String attributeName = null;
     92 		boolean hasBody = false;
     93 
     94 		// line 93 "XmlReader.java"
     95 		{
     96 			cs = xml_start;
     97 		}
     98 
     99 		// line 97 "XmlReader.java"
    100 		{
    101 			int _klen;
    102 			int _trans = 0;
    103 			int _acts;
    104 			int _nacts;
    105 			int _keys;
    106 			int _goto_targ = 0;
    107 
    108 			_goto:
    109 			while (true) {
    110 				switch (_goto_targ) {
    111 				case 0:
    112 					if (p == pe) {
    113 						_goto_targ = 4;
    114 						continue _goto;
    115 					}
    116 					if (cs == 0) {
    117 						_goto_targ = 5;
    118 						continue _goto;
    119 					}
    120 				case 1:
    121 					_match:
    122 					do {
    123 						_keys = _xml_key_offsets[cs];
    124 						_trans = _xml_index_offsets[cs];
    125 						_klen = _xml_single_lengths[cs];
    126 						if (_klen > 0) {
    127 							int _lower = _keys;
    128 							int _mid;
    129 							int _upper = _keys + _klen - 1;
    130 							while (true) {
    131 								if (_upper < _lower) break;
    132 
    133 								_mid = _lower + ((_upper - _lower) >> 1);
    134 								if (data[p] < _xml_trans_keys[_mid])
    135 									_upper = _mid - 1;
    136 								else if (data[p] > _xml_trans_keys[_mid])
    137 									_lower = _mid + 1;
    138 								else {
    139 									_trans += (_mid - _keys);
    140 									break _match;
    141 								}
    142 							}
    143 							_keys += _klen;
    144 							_trans += _klen;
    145 						}
    146 
    147 						_klen = _xml_range_lengths[cs];
    148 						if (_klen > 0) {
    149 							int _lower = _keys;
    150 							int _mid;
    151 							int _upper = _keys + (_klen << 1) - 2;
    152 							while (true) {
    153 								if (_upper < _lower) break;
    154 
    155 								_mid = _lower + (((_upper - _lower) >> 1) & ~1);
    156 								if (data[p] < _xml_trans_keys[_mid])
    157 									_upper = _mid - 2;
    158 								else if (data[p] > _xml_trans_keys[_mid + 1])
    159 									_lower = _mid + 2;
    160 								else {
    161 									_trans += ((_mid - _keys) >> 1);
    162 									break _match;
    163 								}
    164 							}
    165 							_trans += _klen;
    166 						}
    167 					} while (false);
    168 
    169 					_trans = _xml_indicies[_trans];
    170 					cs = _xml_trans_targs[_trans];
    171 
    172 					if (_xml_trans_actions[_trans] != 0) {
    173 						_acts = _xml_trans_actions[_trans];
    174 						_nacts = (int)_xml_actions[_acts++];
    175 						while (_nacts-- > 0) {
    176 							switch (_xml_actions[_acts++]) {
    177 							case 0:
    178 							// line 94 "XmlReader.rl"
    179 							{
    180 								s = p;
    181 							}
    182 								break;
    183 							case 1:
    184 							// line 95 "XmlReader.rl"
    185 							{
    186 								char c = data[s];
    187 								if (c == '?' || c == '!') {
    188 									if (data[s + 1] == '[' && //
    189 										data[s + 2] == 'C' && //
    190 										data[s + 3] == 'D' && //
    191 										data[s + 4] == 'A' && //
    192 										data[s + 5] == 'T' && //
    193 										data[s + 6] == 'A' && //
    194 										data[s + 7] == '[') {
    195 										s += 8;
    196 										p = s + 2;
    197 										while (data[p - 2] != ']' || data[p - 1] != ']' || data[p] != '>')
    198 											p++;
    199 										text(new String(data, s, p - s - 2));
    200 									} else if (c == '!' && data[s + 1] == '-' && data[s + 2] == '-') {
    201 										p = s + 3;
    202 										while (data[p] != '-' || data[p + 1] != '-' || data[p + 2] != '>')
    203 											p++;
    204 										p += 2;
    205 									} else
    206 										while (data[p] != '>')
    207 											p++;
    208 									{
    209 										cs = 15;
    210 										_goto_targ = 2;
    211 										if (true) continue _goto;
    212 									}
    213 								}
    214 								hasBody = true;
    215 								open(new String(data, s, p - s));
    216 							}
    217 								break;
    218 							case 2:
    219 							// line 125 "XmlReader.rl"
    220 							{
    221 								hasBody = false;
    222 								close();
    223 								{
    224 									cs = 15;
    225 									_goto_targ = 2;
    226 									if (true) continue _goto;
    227 								}
    228 							}
    229 								break;
    230 							case 3:
    231 							// line 130 "XmlReader.rl"
    232 							{
    233 								close();
    234 								{
    235 									cs = 15;
    236 									_goto_targ = 2;
    237 									if (true) continue _goto;
    238 								}
    239 							}
    240 								break;
    241 							case 4:
    242 							// line 134 "XmlReader.rl"
    243 							{
    244 								if (hasBody) {
    245 									cs = 15;
    246 									_goto_targ = 2;
    247 									if (true) continue _goto;
    248 								}
    249 							}
    250 								break;
    251 							case 5:
    252 							// line 137 "XmlReader.rl"
    253 							{
    254 								attributeName = new String(data, s, p - s);
    255 							}
    256 								break;
    257 							case 6:
    258 							// line 140 "XmlReader.rl"
    259 							{
    260 								attribute(attributeName, new String(data, s, p - s));
    261 							}
    262 								break;
    263 							case 7:
    264 							// line 143 "XmlReader.rl"
    265 							{
    266 								int end = p;
    267 								while (end != s) {
    268 									switch (data[end - 1]) {
    269 									case ' ':
    270 									case '\t':
    271 									case '\n':
    272 									case '\r':
    273 										end--;
    274 										continue;
    275 									}
    276 									break;
    277 								}
    278 								int current = s;
    279 								boolean entityFound = false;
    280 								while (current != end) {
    281 									if (data[current++] != '&') continue;
    282 									int entityStart = current;
    283 									while (current != end) {
    284 										if (data[current++] != ';') continue;
    285 										textBuffer.append(data, s, entityStart - s - 1);
    286 										String name = new String(data, entityStart, current - entityStart - 1);
    287 										String value = entity(name);
    288 										textBuffer.append(value != null ? value : name);
    289 										s = current;
    290 										entityFound = true;
    291 										break;
    292 									}
    293 								}
    294 								if (entityFound) {
    295 									if (s < end) textBuffer.append(data, s, end - s);
    296 									text(textBuffer.toString());
    297 									textBuffer.setLength(0);
    298 								} else
    299 									text(new String(data, s, end - s));
    300 							}
    301 								break;
    302 							// line 286 "XmlReader.java"
    303 							}
    304 						}
    305 					}
    306 
    307 				case 2:
    308 					if (cs == 0) {
    309 						_goto_targ = 5;
    310 						continue _goto;
    311 					}
    312 					if (++p != pe) {
    313 						_goto_targ = 1;
    314 						continue _goto;
    315 					}
    316 				case 4:
    317 				case 5:
    318 				}
    319 				break;
    320 			}
    321 		}
    322 
    323 		// line 190 "XmlReader.rl"
    324 
    325 		if (p < pe) {
    326 			int lineNumber = 1;
    327 			for (int i = 0; i < p; i++)
    328 				if (data[i] == '\n') lineNumber++;
    329 			throw new SerializationException("Error parsing XML on line " + lineNumber + " near: "
    330 				+ new String(data, p, Math.min(32, pe - p)));
    331 		} else if (elements.size != 0) {
    332 			Element element = elements.peek();
    333 			elements.clear();
    334 			throw new SerializationException("Error parsing XML, unclosed element: " + element.getName());
    335 		}
    336 		Element root = this.root;
    337 		this.root = null;
    338 		return root;
    339 	}
    340 
    341 	// line 324 "XmlReader.java"
    342 	private static byte[] init__xml_actions_0 () {
    343 		return new byte[] {0, 1, 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 2, 0, 6, 2, 1, 4, 2, 2, 4};
    344 	}
    345 
    346 	private static final byte _xml_actions[] = init__xml_actions_0();
    347 
    348 	private static byte[] init__xml_key_offsets_0 () {
    349 		return new byte[] {0, 0, 4, 9, 14, 20, 26, 30, 35, 36, 37, 42, 46, 50, 51, 52, 56, 57, 62, 67, 73, 79, 83, 88, 89, 90, 95,
    350 			99, 103, 104, 108, 109, 110, 111, 112, 115};
    351 	}
    352 
    353 	private static final byte _xml_key_offsets[] = init__xml_key_offsets_0();
    354 
    355 	private static char[] init__xml_trans_keys_0 () {
    356 		return new char[] {32, 60, 9, 13, 32, 47, 62, 9, 13, 32, 47, 62, 9, 13, 32, 47, 61, 62, 9, 13, 32, 47, 61, 62, 9, 13, 32,
    357 			61, 9, 13, 32, 34, 39, 9, 13, 34, 34, 32, 47, 62, 9, 13, 32, 62, 9, 13, 32, 62, 9, 13, 39, 39, 32, 60, 9, 13, 60, 32,
    358 			47, 62, 9, 13, 32, 47, 62, 9, 13, 32, 47, 61, 62, 9, 13, 32, 47, 61, 62, 9, 13, 32, 61, 9, 13, 32, 34, 39, 9, 13, 34,
    359 			34, 32, 47, 62, 9, 13, 32, 62, 9, 13, 32, 62, 9, 13, 60, 32, 47, 9, 13, 62, 62, 39, 39, 32, 9, 13, 0};
    360 	}
    361 
    362 	private static final char _xml_trans_keys[] = init__xml_trans_keys_0();
    363 
    364 	private static byte[] init__xml_single_lengths_0 () {
    365 		return new byte[] {0, 2, 3, 3, 4, 4, 2, 3, 1, 1, 3, 2, 2, 1, 1, 2, 1, 3, 3, 4, 4, 2, 3, 1, 1, 3, 2, 2, 1, 2, 1, 1, 1, 1, 1,
    366 			0};
    367 	}
    368 
    369 	private static final byte _xml_single_lengths[] = init__xml_single_lengths_0();
    370 
    371 	private static byte[] init__xml_range_lengths_0 () {
    372 		return new byte[] {0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1,
    373 			0};
    374 	}
    375 
    376 	private static final byte _xml_range_lengths[] = init__xml_range_lengths_0();
    377 
    378 	private static short[] init__xml_index_offsets_0 () {
    379 		return new short[] {0, 0, 4, 9, 14, 20, 26, 30, 35, 37, 39, 44, 48, 52, 54, 56, 60, 62, 67, 72, 78, 84, 88, 93, 95, 97,
    380 			102, 106, 110, 112, 116, 118, 120, 122, 124, 127};
    381 	}
    382 
    383 	private static final short _xml_index_offsets[] = init__xml_index_offsets_0();
    384 
    385 	private static byte[] init__xml_indicies_0 () {
    386 		return new byte[] {0, 2, 0, 1, 2, 1, 1, 2, 3, 5, 6, 7, 5, 4, 9, 10, 1, 11, 9, 8, 13, 1, 14, 1, 13, 12, 15, 16, 15, 1, 16,
    387 			17, 18, 16, 1, 20, 19, 22, 21, 9, 10, 11, 9, 1, 23, 24, 23, 1, 25, 11, 25, 1, 20, 26, 22, 27, 29, 30, 29, 28, 32, 31,
    388 			30, 34, 1, 30, 33, 36, 37, 38, 36, 35, 40, 41, 1, 42, 40, 39, 44, 1, 45, 1, 44, 43, 46, 47, 46, 1, 47, 48, 49, 47, 1,
    389 			51, 50, 53, 52, 40, 41, 42, 40, 1, 54, 55, 54, 1, 56, 42, 56, 1, 57, 1, 57, 34, 57, 1, 1, 58, 59, 58, 51, 60, 53, 61,
    390 			62, 62, 1, 1, 0};
    391 	}
    392 
    393 	private static final byte _xml_indicies[] = init__xml_indicies_0();
    394 
    395 	private static byte[] init__xml_trans_targs_0 () {
    396 		return new byte[] {1, 0, 2, 3, 3, 4, 11, 34, 5, 4, 11, 34, 5, 6, 7, 6, 7, 8, 13, 9, 10, 9, 10, 12, 34, 12, 14, 14, 16, 15,
    397 			17, 16, 17, 18, 30, 18, 19, 26, 28, 20, 19, 26, 28, 20, 21, 22, 21, 22, 23, 32, 24, 25, 24, 25, 27, 28, 27, 29, 31, 35,
    398 			33, 33, 34};
    399 	}
    400 
    401 	private static final byte _xml_trans_targs[] = init__xml_trans_targs_0();
    402 
    403 	private static byte[] init__xml_trans_actions_0 () {
    404 		return new byte[] {0, 0, 0, 1, 0, 3, 3, 20, 1, 0, 0, 9, 0, 11, 11, 0, 0, 0, 0, 1, 17, 0, 13, 5, 23, 0, 1, 0, 1, 0, 0, 0,
    405 			15, 1, 0, 0, 3, 3, 20, 1, 0, 0, 9, 0, 11, 11, 0, 0, 0, 0, 1, 17, 0, 13, 5, 23, 0, 0, 0, 7, 1, 0, 0};
    406 	}
    407 
    408 	private static final byte _xml_trans_actions[] = init__xml_trans_actions_0();
    409 
    410 	static final int xml_start = 1;
    411 	static final int xml_first_final = 34;
    412 	static final int xml_error = 0;
    413 
    414 	static final int xml_en_elementBody = 15;
    415 	static final int xml_en_main = 1;
    416 
    417 	// line 209 "XmlReader.rl"
    418 
    419 	protected void open (String name) {
    420 		Element child = new Element(name, current);
    421 		Element parent = current;
    422 		if (parent != null) parent.addChild(child);
    423 		elements.add(child);
    424 		current = child;
    425 	}
    426 
    427 	protected void attribute (String name, String value) {
    428 		current.setAttribute(name, value);
    429 	}
    430 
    431 	protected String entity (String name) {
    432 		if (name.equals("lt")) return "<";
    433 		if (name.equals("gt")) return ">";
    434 		if (name.equals("amp")) return "&";
    435 		if (name.equals("apos")) return "'";
    436 		if (name.equals("quot")) return "\"";
    437 		if (name.startsWith("#x")) return Character.toString((char)Integer.parseInt(name.substring(2), 16));
    438 		return null;
    439 	}
    440 
    441 	protected void text (String text) {
    442 		String existing = current.getText();
    443 		current.setText(existing != null ? existing + text : text);
    444 	}
    445 
    446 	protected void close () {
    447 		root = elements.pop();
    448 		current = elements.size > 0 ? elements.peek() : null;
    449 	}
    450 
    451 	static public class Element {
    452 		private final String name;
    453 		private ObjectMap<String, String> attributes;
    454 		private Array<Element> children;
    455 		private String text;
    456 		private Element parent;
    457 
    458 		public Element (String name, Element parent) {
    459 			this.name = name;
    460 			this.parent = parent;
    461 		}
    462 
    463 		public String getName () {
    464 			return name;
    465 		}
    466 
    467 		public ObjectMap<String, String> getAttributes () {
    468 			return attributes;
    469 		}
    470 
    471 		/** @throws GdxRuntimeException if the attribute was not found. */
    472 		public String getAttribute (String name) {
    473 			if (attributes == null) throw new GdxRuntimeException("Element " + name + " doesn't have attribute: " + name);
    474 			String value = attributes.get(name);
    475 			if (value == null) throw new GdxRuntimeException("Element " + name + " doesn't have attribute: " + name);
    476 			return value;
    477 		}
    478 
    479 		public String getAttribute (String name, String defaultValue) {
    480 			if (attributes == null) return defaultValue;
    481 			String value = attributes.get(name);
    482 			if (value == null) return defaultValue;
    483 			return value;
    484 		}
    485 
    486 		public void setAttribute (String name, String value) {
    487 			if (attributes == null) attributes = new ObjectMap(8);
    488 			attributes.put(name, value);
    489 		}
    490 
    491 		public int getChildCount () {
    492 			if (children == null) return 0;
    493 			return children.size;
    494 		}
    495 
    496 		/** @throws GdxRuntimeException if the element has no children. */
    497 		public Element getChild (int index) {
    498 			if (children == null) throw new GdxRuntimeException("Element has no children: " + name);
    499 			return children.get(index);
    500 		}
    501 
    502 		public void addChild (Element element) {
    503 			if (children == null) children = new Array(8);
    504 			children.add(element);
    505 		}
    506 
    507 		public String getText () {
    508 			return text;
    509 		}
    510 
    511 		public void setText (String text) {
    512 			this.text = text;
    513 		}
    514 
    515 		public void removeChild (int index) {
    516 			if (children != null) children.removeIndex(index);
    517 		}
    518 
    519 		public void removeChild (Element child) {
    520 			if (children != null) children.removeValue(child, true);
    521 		}
    522 
    523 		public void remove () {
    524 			parent.removeChild(this);
    525 		}
    526 
    527 		public Element getParent () {
    528 			return parent;
    529 		}
    530 
    531 		public String toString () {
    532 			return toString("");
    533 		}
    534 
    535 		public String toString (String indent) {
    536 			StringBuilder buffer = new StringBuilder(128);
    537 			buffer.append(indent);
    538 			buffer.append('<');
    539 			buffer.append(name);
    540 			if (attributes != null) {
    541 				for (Entry<String, String> entry : attributes.entries()) {
    542 					buffer.append(' ');
    543 					buffer.append(entry.key);
    544 					buffer.append("=\"");
    545 					buffer.append(entry.value);
    546 					buffer.append('\"');
    547 				}
    548 			}
    549 			if (children == null && (text == null || text.length() == 0))
    550 				buffer.append("/>");
    551 			else {
    552 				buffer.append(">\n");
    553 				String childIndent = indent + '\t';
    554 				if (text != null && text.length() > 0) {
    555 					buffer.append(childIndent);
    556 					buffer.append(text);
    557 					buffer.append('\n');
    558 				}
    559 				if (children != null) {
    560 					for (Element child : children) {
    561 						buffer.append(child.toString(childIndent));
    562 						buffer.append('\n');
    563 					}
    564 				}
    565 				buffer.append(indent);
    566 				buffer.append("</");
    567 				buffer.append(name);
    568 				buffer.append('>');
    569 			}
    570 			return buffer.toString();
    571 		}
    572 
    573 		/** @param name the name of the child {@link Element}
    574 		 * @return the first child having the given name or null, does not recurse */
    575 		public Element getChildByName (String name) {
    576 			if (children == null) return null;
    577 			for (int i = 0; i < children.size; i++) {
    578 				Element element = children.get(i);
    579 				if (element.name.equals(name)) return element;
    580 			}
    581 			return null;
    582 		}
    583 
    584 		/** @param name the name of the child {@link Element}
    585 		 * @return the first child having the given name or null, recurses */
    586 		public Element getChildByNameRecursive (String name) {
    587 			if (children == null) return null;
    588 			for (int i = 0; i < children.size; i++) {
    589 				Element element = children.get(i);
    590 				if (element.name.equals(name)) return element;
    591 				Element found = element.getChildByNameRecursive(name);
    592 				if (found != null) return found;
    593 			}
    594 			return null;
    595 		}
    596 
    597 		/** @param name the name of the children
    598 		 * @return the children with the given name or an empty {@link Array} */
    599 		public Array<Element> getChildrenByName (String name) {
    600 			Array<Element> result = new Array<Element>();
    601 			if (children == null) return result;
    602 			for (int i = 0; i < children.size; i++) {
    603 				Element child = children.get(i);
    604 				if (child.name.equals(name)) result.add(child);
    605 			}
    606 			return result;
    607 		}
    608 
    609 		/** @param name the name of the children
    610 		 * @return the children with the given name or an empty {@link Array} */
    611 		public Array<Element> getChildrenByNameRecursively (String name) {
    612 			Array<Element> result = new Array<Element>();
    613 			getChildrenByNameRecursively(name, result);
    614 			return result;
    615 		}
    616 
    617 		private void getChildrenByNameRecursively (String name, Array<Element> result) {
    618 			if (children == null) return;
    619 			for (int i = 0; i < children.size; i++) {
    620 				Element child = children.get(i);
    621 				if (child.name.equals(name)) result.add(child);
    622 				child.getChildrenByNameRecursively(name, result);
    623 			}
    624 		}
    625 
    626 		/** @throws GdxRuntimeException if the attribute was not found. */
    627 		public float getFloatAttribute (String name) {
    628 			return Float.parseFloat(getAttribute(name));
    629 		}
    630 
    631 		public float getFloatAttribute (String name, float defaultValue) {
    632 			String value = getAttribute(name, null);
    633 			if (value == null) return defaultValue;
    634 			return Float.parseFloat(value);
    635 		}
    636 
    637 		/** @throws GdxRuntimeException if the attribute was not found. */
    638 		public int getIntAttribute (String name) {
    639 			return Integer.parseInt(getAttribute(name));
    640 		}
    641 
    642 		public int getIntAttribute (String name, int defaultValue) {
    643 			String value = getAttribute(name, null);
    644 			if (value == null) return defaultValue;
    645 			return Integer.parseInt(value);
    646 		}
    647 
    648 		/** @throws GdxRuntimeException if the attribute was not found. */
    649 		public boolean getBooleanAttribute (String name) {
    650 			return Boolean.parseBoolean(getAttribute(name));
    651 		}
    652 
    653 		public boolean getBooleanAttribute (String name, boolean defaultValue) {
    654 			String value = getAttribute(name, null);
    655 			if (value == null) return defaultValue;
    656 			return Boolean.parseBoolean(value);
    657 		}
    658 
    659 		/** Returns the attribute value with the specified name, or if no attribute is found, the text of a child with the name.
    660 		 * @throws GdxRuntimeException if no attribute or child was not found. */
    661 		public String get (String name) {
    662 			String value = get(name, null);
    663 			if (value == null) throw new GdxRuntimeException("Element " + this.name + " doesn't have attribute or child: " + name);
    664 			return value;
    665 		}
    666 
    667 		/** Returns the attribute value with the specified name, or if no attribute is found, the text of a child with the name.
    668 		 * @throws GdxRuntimeException if no attribute or child was not found. */
    669 		public String get (String name, String defaultValue) {
    670 			if (attributes != null) {
    671 				String value = attributes.get(name);
    672 				if (value != null) return value;
    673 			}
    674 			Element child = getChildByName(name);
    675 			if (child == null) return defaultValue;
    676 			String value = child.getText();
    677 			if (value == null) return defaultValue;
    678 			return value;
    679 		}
    680 
    681 		/** Returns the attribute value with the specified name, or if no attribute is found, the text of a child with the name.
    682 		 * @throws GdxRuntimeException if no attribute or child was not found. */
    683 		public int getInt (String name) {
    684 			String value = get(name, null);
    685 			if (value == null) throw new GdxRuntimeException("Element " + this.name + " doesn't have attribute or child: " + name);
    686 			return Integer.parseInt(value);
    687 		}
    688 
    689 		/** Returns the attribute value with the specified name, or if no attribute is found, the text of a child with the name.
    690 		 * @throws GdxRuntimeException if no attribute or child was not found. */
    691 		public int getInt (String name, int defaultValue) {
    692 			String value = get(name, null);
    693 			if (value == null) return defaultValue;
    694 			return Integer.parseInt(value);
    695 		}
    696 
    697 		/** Returns the attribute value with the specified name, or if no attribute is found, the text of a child with the name.
    698 		 * @throws GdxRuntimeException if no attribute or child was not found. */
    699 		public float getFloat (String name) {
    700 			String value = get(name, null);
    701 			if (value == null) throw new GdxRuntimeException("Element " + this.name + " doesn't have attribute or child: " + name);
    702 			return Float.parseFloat(value);
    703 		}
    704 
    705 		/** Returns the attribute value with the specified name, or if no attribute is found, the text of a child with the name.
    706 		 * @throws GdxRuntimeException if no attribute or child was not found. */
    707 		public float getFloat (String name, float defaultValue) {
    708 			String value = get(name, null);
    709 			if (value == null) return defaultValue;
    710 			return Float.parseFloat(value);
    711 		}
    712 
    713 		/** Returns the attribute value with the specified name, or if no attribute is found, the text of a child with the name.
    714 		 * @throws GdxRuntimeException if no attribute or child was not found. */
    715 		public boolean getBoolean (String name) {
    716 			String value = get(name, null);
    717 			if (value == null) throw new GdxRuntimeException("Element " + this.name + " doesn't have attribute or child: " + name);
    718 			return Boolean.parseBoolean(value);
    719 		}
    720 
    721 		/** Returns the attribute value with the specified name, or if no attribute is found, the text of a child with the name.
    722 		 * @throws GdxRuntimeException if no attribute or child was not found. */
    723 		public boolean getBoolean (String name, boolean defaultValue) {
    724 			String value = get(name, null);
    725 			if (value == null) return defaultValue;
    726 			return Boolean.parseBoolean(value);
    727 		}
    728 	}
    729 }
    730