XmlReader.java

  1package eu.siacs.conversations.xml;
  2
  3import android.util.Log;
  4import android.util.Xml;
  5
  6import org.xmlpull.v1.XmlPullParser;
  7import org.xmlpull.v1.XmlPullParserException;
  8
  9import java.io.IOException;
 10import java.io.InputStream;
 11import java.io.InputStreamReader;
 12
 13import eu.siacs.conversations.Config;
 14
 15public class XmlReader {
 16	private XmlPullParser parser;
 17	private InputStream is;
 18
 19	public XmlReader() {
 20		this.parser = Xml.newPullParser();
 21		try {
 22			this.parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
 23		} catch (XmlPullParserException e) {
 24			Log.d(Config.LOGTAG, "error setting namespace feature on parser");
 25		}
 26	}
 27
 28	public void setInputStream(InputStream inputStream) throws IOException {
 29		if (inputStream == null) {
 30			throw new IOException();
 31		}
 32		this.is = inputStream;
 33		try {
 34			parser.setInput(new InputStreamReader(this.is));
 35		} catch (XmlPullParserException e) {
 36			throw new IOException("error resetting parser");
 37		}
 38	}
 39
 40	public void reset() throws IOException {
 41		if (this.is == null) {
 42			throw new IOException();
 43		}
 44		try {
 45			parser.setInput(new InputStreamReader(this.is));
 46		} catch (XmlPullParserException e) {
 47			throw new IOException("error resetting parser");
 48		}
 49	}
 50
 51	public Tag readTag() throws IOException {
 52		try {
 53			while (this.is != null && parser.next() != XmlPullParser.END_DOCUMENT) {
 54				if (parser.getEventType() == XmlPullParser.START_TAG) {
 55					Tag tag = Tag.start(parser.getName());
 56					final String xmlns = parser.getNamespace();
 57					for (int i = 0; i < parser.getAttributeCount(); ++i) {
 58						final String prefix = parser.getAttributePrefix(i);
 59						String name;
 60						if (prefix != null && !prefix.isEmpty()) {
 61							name = prefix+":"+parser.getAttributeName(i);
 62						} else {
 63							name = parser.getAttributeName(i);
 64						}
 65						tag.setAttribute(name,parser.getAttributeValue(i));
 66					}
 67					if (xmlns != null) {
 68						tag.setAttribute("xmlns", xmlns);
 69					}
 70					return tag;
 71				} else if (parser.getEventType() == XmlPullParser.END_TAG) {
 72					return Tag.end(parser.getName());
 73				} else if (parser.getEventType() == XmlPullParser.TEXT) {
 74					return Tag.no(parser.getText());
 75				}
 76			}
 77
 78		} catch (Throwable throwable) {
 79			throw new IOException("xml parser mishandled "+throwable.getClass().getSimpleName()+"("+throwable.getMessage()+")", throwable);
 80		}
 81		return null;
 82	}
 83
 84	public Element readElement(Tag currentTag) throws XmlPullParserException,
 85			IOException {
 86		Element element = new Element(currentTag.getName());
 87		element.setAttributes(currentTag.getAttributes());
 88		Tag nextTag = this.readTag();
 89		if (nextTag == null) {
 90			throw new IOException("interrupted mid tag");
 91		}
 92		if (nextTag.isNo()) {
 93			element.setContent(nextTag.getName());
 94			nextTag = this.readTag();
 95			if (nextTag == null) {
 96				throw new IOException("interrupted mid tag");
 97			}
 98		}
 99		while (!nextTag.isEnd(element.getName())) {
100			if (!nextTag.isNo()) {
101				Element child = this.readElement(nextTag);
102				element.addChild(child);
103			}
104			nextTag = this.readTag();
105			if (nextTag == null) {
106				throw new IOException("interrupted mid tag");
107			}
108		}
109		return element;
110	}
111}