package com.xenoage.utils.android.xml; import java.io.IOException; import java.io.InputStream; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; import com.xenoage.utils.jse.io.JseInputStream; import com.xenoage.utils.xml.XmlDataException; import com.xenoage.utils.xml.XmlException; import com.xenoage.utils.xml.XmlReader; /** * Android implementation of an {@link XmlReader}, * based on the Android {@link XmlPullParser}. * * @author Andreas Wenger */ public class AndroidXmlReader extends XmlReader { private InputStream inputStream; private XmlPullParser reader; private boolean cancelNextClose = false; public AndroidXmlReader(InputStream inputStream) { try { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); factory.setFeature(XmlPullParser.FEATURE_PROCESS_DOCDECL, false); factory.setNamespaceAware(false); this.inputStream = inputStream; this.reader = factory.newPullParser(); this.reader.setInput(new JseInputStream(inputStream), "UTF-8"); } catch (XmlPullParserException ex) { throw new XmlException(ex); } } @Override public String getElementName() { try { return reader.getName(); } catch (IllegalStateException ex) { throw new XmlException(ex); } } @Override public String getText() { try { int event = reader.getEventType(); while (event != XmlPullParser.END_DOCUMENT) { event = reader.next(); if (event == XmlPullParser.TEXT) { break; } else if (event == XmlPullParser.END_TAG) { cancelNextClose = true; return null; } } return reader.getText(); } catch (Exception ex) { throw new XmlException(ex); } } @Override public int getAttributeCount() { try { return reader.getAttributeCount(); } catch (IllegalStateException ex) { throw new XmlException(ex); } } @Override public String getAttributeName(int index) { try { return reader.getAttributeName(index); } catch (IllegalStateException ex) { throw new XmlException(ex); } } @Override public String getAttribute(int index) { try { return reader.getAttributeValue(index); } catch (IllegalStateException ex) { throw new XmlException(ex); } } @Override public boolean openNextChildElement() { try { int event = reader.getEventType(); while (event != XmlPullParser.END_DOCUMENT) { event = reader.next(); if (event == XmlPullParser.START_TAG) return true; else if (event == XmlPullParser.END_TAG) { cancelNextClose = true; //we already reached the end of the parent return false; } } return false; } catch (Exception ex) { throw new XmlException(ex); } } @Override public void closeElement() { if (cancelNextClose) { cancelNextClose = false; return; } try { int openChildren = 1; int event = reader.getEventType(); while (event != XmlPullParser.END_DOCUMENT) { event = reader.next(); if (event == XmlPullParser.START_TAG) { openChildren++; } else if (event == XmlPullParser.END_TAG) { openChildren--; if (openChildren == 0) return; } } } catch (Exception ex) { throw new XmlException(ex); } } private String getLocation() { return "line " + reader.getLineNumber() + ", column " + reader.getColumnNumber(); } @Override public XmlDataException dataException() { throw new XmlDataException("(at " + getLocation() + ")"); } @Override public XmlDataException dataException(String message) { throw new XmlDataException(message + " (at " + getLocation() + ")"); } @Override public int getLine() { return reader.getLineNumber(); } @Override public void close() { try { inputStream.close(); } catch (IOException ex) { } } }