XmlPullSubtreeParser
XMLの特定の要素だけをパースしたい場合がある。他のメソッドやクラスにパース処理を委譲してしまいたいのが主な理由だ。
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <array name="preloaded_drawables"> <item>@drawable/indicator_code_lock_drag_direction_green_up</item> <item>@drawable/indicator_code_lock_drag_direction_red_up</item> </array> <array name="preloaded_color_state_lists"> <item>@color/hint_foreground_dark</item> <item>@color/hint_foreground_light</item> </array> <integer-array name="maps_starting_lat_lng"> <item>36149777</item> <item>-95993398</item> </integer-array> <integer-array name="maps_starting_zoom"> <item>3</item> </integer-array> </resources>
こんなXMLがあったとして、
このような場合、サブツリーだけを処理するXMLパーサがあると便利であり.NET C#等では標準のプルパーサに同様の実装がありとても重宝する。残念ながらJavaのプルパーサにはそのような機能は無いが、以前にJava6用のものを作ったことがある。
[Java]無いなら作ろう - XMLStreamSubReader
同様にAndroid用にも作ったが、以前用意したものはXmlResourcePullParserがベースであり広範囲には使いづらいので、改めてXMLPullParserインタフェースをベースに作り直した。
-
- XmlPullParserDelegate.java
import java.io.IOException; import java.io.InputStream; import java.io.Reader; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; public class XmlPullParserDelegate implements XmlPullParser { protected final XmlPullParser delegate; public XmlPullParserDelegate(XmlPullParser delegate) { this.delegate = delegate; } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#defineEntityReplacementText(java.lang.String, java.lang.String) */ @Override public void defineEntityReplacementText(String entityName, String replacementText) throws XmlPullParserException { this.delegate.defineEntityReplacementText(entityName, replacementText); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getAttributeCount() */ @Override public int getAttributeCount() { return this.delegate.getAttributeCount(); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getAttributeName(int) */ @Override public String getAttributeName(int index) { return this.delegate.getAttributeName(index); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getAttributeNamespace(int) */ @Override public String getAttributeNamespace(int index) { return this.delegate.getAttributeNamespace(index); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getAttributePrefix(int) */ @Override public String getAttributePrefix(int index) { return this.delegate.getAttributePrefix(index); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getAttributeType(int) */ @Override public String getAttributeType(int index) { return this.delegate.getAttributeType(index); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getAttributeValue(int) */ @Override public String getAttributeValue(int index) { return this.delegate.getAttributeValue(index); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getAttributeValue(java.lang.String, java.lang.String) */ @Override public String getAttributeValue(String namespace, String name) { return this.delegate.getAttributeValue(namespace, name); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getColumnNumber() */ @Override public int getColumnNumber() { return this.delegate.getColumnNumber(); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getDepth() */ @Override public int getDepth() { return this.delegate.getDepth(); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getEventType() */ @Override public int getEventType() throws XmlPullParserException { return this.delegate.getEventType(); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getFeature(java.lang.String) */ @Override public boolean getFeature(String name) { return this.delegate.getFeature(name); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getInputEncoding() */ @Override public String getInputEncoding() { return this.delegate.getInputEncoding(); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getLineNumber() */ @Override public int getLineNumber() { return this.delegate.getLineNumber(); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getName() */ @Override public String getName() { return this.delegate.getName(); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getNamespace() */ @Override public String getNamespace() { return this.delegate.getNamespace(); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getNamespace(java.lang.String) */ @Override public String getNamespace(String prefix) { return this.delegate.getNamespace(prefix); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getNamespaceCount(int) */ @Override public int getNamespaceCount(int depth) throws XmlPullParserException { return this.delegate.getNamespaceCount(depth); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getNamespacePrefix(int) */ @Override public String getNamespacePrefix(int pos) throws XmlPullParserException { return this.delegate.getNamespacePrefix(pos); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getNamespaceUri(int) */ @Override public String getNamespaceUri(int pos) throws XmlPullParserException { return this.delegate.getNamespaceUri(pos); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getPositionDescription() */ @Override public String getPositionDescription() { return this.delegate.getPositionDescription(); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getPrefix() */ @Override public String getPrefix() { return this.delegate.getPrefix(); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getProperty(java.lang.String) */ @Override public Object getProperty(String name) { return this.delegate.getProperty(name); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getText() */ @Override public String getText() { return this.delegate.getText(); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#getTextCharacters(int[]) */ @Override public char[] getTextCharacters(int[] holderForStartAndLength) { return this.delegate.getTextCharacters(holderForStartAndLength); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#isAttributeDefault(int) */ @Override public boolean isAttributeDefault(int index) { return this.delegate.isAttributeDefault(index); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#isEmptyElementTag() */ @Override public boolean isEmptyElementTag() throws XmlPullParserException { return this.delegate.isEmptyElementTag(); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#isWhitespace() */ @Override public boolean isWhitespace() throws XmlPullParserException { return this.delegate.isWhitespace(); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#next() */ @Override public int next() throws XmlPullParserException, IOException { return this.delegate.next(); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#nextTag() */ @Override public int nextTag() throws XmlPullParserException, IOException { return this.delegate.nextTag(); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#nextText() */ @Override public String nextText() throws XmlPullParserException, IOException { return this.delegate.nextText(); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#nextToken() */ @Override public int nextToken() throws XmlPullParserException, IOException { return this.delegate.nextToken(); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#require(int, java.lang.String, java.lang.String) */ @Override public void require(int type, String namespace, String name) throws XmlPullParserException, IOException { this.delegate.require(type, namespace, name); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#setFeature(java.lang.String, boolean) */ @Override public void setFeature(String name, boolean state) throws XmlPullParserException { this.delegate.setFeature(name, state); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#setInput(java.io.Reader) */ @Override public void setInput(Reader in) throws XmlPullParserException { this.delegate.setInput(in); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#setInput(java.io.InputStream, java.lang.String) */ @Override public void setInput(InputStream inputStream, String inputEncoding) throws XmlPullParserException { this.delegate.setInput(inputStream, inputEncoding); } /* (non-Javadoc) * @see org.xmlpull.v1.XmlPullParser#setProperty(java.lang.String, java.lang.Object) */ @Override public void setProperty(String name, Object value) throws XmlPullParserException { this.delegate.setProperty(name, value); } }
XmlPullParserDelegateはパーサの処理を委譲するだけだ。
-
- XmlPullSubtreeParser.java
import java.io.IOException; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; public class XmlPullSubtreeParser extends XmlPullParserDelegate { protected String rootNode; protected int rootDepth; protected int lastEvent; protected int lastDepth; public XmlPullSubtreeParser(XmlPullParser delegateParser) { super(delegateParser); this.rootDepth = delegateParser.getDepth(); this.lastDepth = this.rootDepth; this.rootNode = delegateParser.getName(); } public String getRootName() { return this.rootNode; } /* (non-Javadoc) * @see org.jaffa.util.xml.XmlResourceParserDelegate#next() */ @Override public int next() throws XmlPullParserException, IOException { if ( this.hasNext() ) { this.lastEvent = super.next(); this.lastDepth = this.getDepth(); return this.lastEvent; } else { return 0; } } public boolean hasNext() throws XmlPullParserException { if ( this.rootDepth > this.lastDepth ) { return false; } if ( this.lastEvent == XmlPullParser.END_TAG ) { if ( this.getName().equals(this.rootNode)) { return false; } if ( this.rootDepth >= this.lastDepth ) { return false; } } if ( this.delegate instanceof XmlPullSubtreeParser ) { return ((XmlPullSubtreeParser)this.delegate).hasNext(); } else { return (this.lastEvent != XmlPullParser.END_DOCUMENT); } } }
XmlPullSubtreeParserはコンストラクタの引数で与えられたXmlPullParserの要素と深度を基準にしてその直下の要素だけをパースする。何をしているかは見れば解るだろう。
※コードは一応テストを通っているがその動作は保証しない。