2014-10-22 16:38:44 +00:00
|
|
|
package eu.siacs.conversations.xml;
|
|
|
|
|
2015-07-20 12:26:29 +00:00
|
|
|
import android.util.Log;
|
|
|
|
import android.util.Xml;
|
2014-10-22 16:38:44 +00:00
|
|
|
|
|
|
|
import org.xmlpull.v1.XmlPullParser;
|
|
|
|
import org.xmlpull.v1.XmlPullParserException;
|
|
|
|
|
2019-07-04 08:12:08 +00:00
|
|
|
import java.io.Closeable;
|
2015-07-20 12:26:29 +00:00
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.io.InputStreamReader;
|
2014-10-22 16:38:44 +00:00
|
|
|
|
2015-07-20 12:26:29 +00:00
|
|
|
import eu.siacs.conversations.Config;
|
2014-10-22 16:38:44 +00:00
|
|
|
|
2019-07-04 08:12:08 +00:00
|
|
|
public class XmlReader implements Closeable {
|
|
|
|
private final XmlPullParser parser;
|
2014-10-22 16:38:44 +00:00
|
|
|
private InputStream is;
|
|
|
|
|
2018-01-21 11:26:16 +00:00
|
|
|
public XmlReader() {
|
2014-10-22 16:38:44 +00:00
|
|
|
this.parser = Xml.newPullParser();
|
|
|
|
try {
|
2016-06-22 10:22:03 +00:00
|
|
|
this.parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
|
2014-10-22 16:38:44 +00:00
|
|
|
} catch (XmlPullParserException e) {
|
|
|
|
Log.d(Config.LOGTAG, "error setting namespace feature on parser");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setInputStream(InputStream inputStream) throws IOException {
|
|
|
|
if (inputStream == null) {
|
|
|
|
throw new IOException();
|
|
|
|
}
|
|
|
|
this.is = inputStream;
|
|
|
|
try {
|
|
|
|
parser.setInput(new InputStreamReader(this.is));
|
|
|
|
} catch (XmlPullParserException e) {
|
|
|
|
throw new IOException("error resetting parser");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void reset() throws IOException {
|
|
|
|
if (this.is == null) {
|
|
|
|
throw new IOException();
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
parser.setInput(new InputStreamReader(this.is));
|
|
|
|
} catch (XmlPullParserException e) {
|
|
|
|
throw new IOException("error resetting parser");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-04 08:12:08 +00:00
|
|
|
@Override
|
|
|
|
public void close() {
|
|
|
|
this.is = null;
|
|
|
|
}
|
|
|
|
|
2018-09-27 08:00:58 +00:00
|
|
|
public Tag readTag() throws IOException {
|
2014-10-22 16:38:44 +00:00
|
|
|
try {
|
2016-06-22 10:22:03 +00:00
|
|
|
while (this.is != null && parser.next() != XmlPullParser.END_DOCUMENT) {
|
2014-10-22 16:38:44 +00:00
|
|
|
if (parser.getEventType() == XmlPullParser.START_TAG) {
|
|
|
|
Tag tag = Tag.start(parser.getName());
|
2017-05-30 06:38:33 +00:00
|
|
|
final String xmlns = parser.getNamespace();
|
2014-10-22 16:38:44 +00:00
|
|
|
for (int i = 0; i < parser.getAttributeCount(); ++i) {
|
2017-05-30 06:38:33 +00:00
|
|
|
final String prefix = parser.getAttributePrefix(i);
|
|
|
|
String name;
|
2017-05-30 17:05:36 +00:00
|
|
|
if (prefix != null && !prefix.isEmpty()) {
|
2017-05-30 06:38:33 +00:00
|
|
|
name = prefix+":"+parser.getAttributeName(i);
|
|
|
|
} else {
|
|
|
|
name = parser.getAttributeName(i);
|
|
|
|
}
|
|
|
|
tag.setAttribute(name,parser.getAttributeValue(i));
|
2014-10-22 16:38:44 +00:00
|
|
|
}
|
|
|
|
if (xmlns != null) {
|
|
|
|
tag.setAttribute("xmlns", xmlns);
|
|
|
|
}
|
|
|
|
return tag;
|
|
|
|
} else if (parser.getEventType() == XmlPullParser.END_TAG) {
|
2016-06-22 10:22:03 +00:00
|
|
|
return Tag.end(parser.getName());
|
2014-10-22 16:38:44 +00:00
|
|
|
} else if (parser.getEventType() == XmlPullParser.TEXT) {
|
2016-06-22 10:22:03 +00:00
|
|
|
return Tag.no(parser.getText());
|
2014-10-22 16:38:44 +00:00
|
|
|
}
|
|
|
|
}
|
2016-06-22 10:22:03 +00:00
|
|
|
|
2016-08-02 08:58:54 +00:00
|
|
|
} catch (Throwable throwable) {
|
2017-01-22 11:54:39 +00:00
|
|
|
throw new IOException("xml parser mishandled "+throwable.getClass().getSimpleName()+"("+throwable.getMessage()+")", throwable);
|
2014-10-22 16:38:44 +00:00
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2020-01-24 08:14:52 +00:00
|
|
|
public Element readElement(Tag currentTag) throws IOException {
|
2014-10-22 16:38:44 +00:00
|
|
|
Element element = new Element(currentTag.getName());
|
|
|
|
element.setAttributes(currentTag.getAttributes());
|
|
|
|
Tag nextTag = this.readTag();
|
|
|
|
if (nextTag == null) {
|
2016-06-22 10:22:03 +00:00
|
|
|
throw new IOException("interrupted mid tag");
|
2014-10-22 16:38:44 +00:00
|
|
|
}
|
|
|
|
if (nextTag.isNo()) {
|
|
|
|
element.setContent(nextTag.getName());
|
|
|
|
nextTag = this.readTag();
|
|
|
|
if (nextTag == null) {
|
2016-06-22 10:22:03 +00:00
|
|
|
throw new IOException("interrupted mid tag");
|
2014-10-22 16:38:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
while (!nextTag.isEnd(element.getName())) {
|
|
|
|
if (!nextTag.isNo()) {
|
|
|
|
Element child = this.readElement(nextTag);
|
|
|
|
element.addChild(child);
|
|
|
|
}
|
|
|
|
nextTag = this.readTag();
|
|
|
|
if (nextTag == null) {
|
2016-06-22 10:22:03 +00:00
|
|
|
throw new IOException("interrupted mid tag");
|
2014-10-22 16:38:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return element;
|
|
|
|
}
|
|
|
|
}
|