XML Pull API 方式解析XML


XmlPullParser

public interface XmlPullParser {
    String NO_NAMESPACE = "";
    int START_DOCUMENT = 0;
    int END_DOCUMENT = 1;
    int START_TAG = 2;
    int END_TAG = 3;
    int TEXT = 4;
    int CDSECT = 5;
    int ENTITY_REF = 6;
    int IGNORABLE_WHITESPACE = 7;
    int PROCESSING_INSTRUCTION = 8;
    int COMMENT = 9;
    int DOCDECL = 10;

    String [] TYPES = {
        "START_DOCUMENT",
            "END_DOCUMENT",
            "START_TAG",
            "END_TAG",
            "TEXT",
            "CDSECT",
            "ENTITY_REF",
            "IGNORABLE_WHITESPACE",
            "PROCESSING_INSTRUCTION",
            "COMMENT",
            "DOCDECL"
    };

    String FEATURE_PROCESS_NAMESPACES =
        "http://xmlpull.org/v1/doc/features.html#process-namespaces";

    String FEATURE_REPORT_NAMESPACE_ATTRIBUTES =
        "http://xmlpull.org/v1/doc/features.html#report-namespace-prefixes";

    String FEATURE_PROCESS_DOCDECL =
        "http://xmlpull.org/v1/doc/features.html#process-docdecl";

    String FEATURE_VALIDATION =
        "http://xmlpull.org/v1/doc/features.html#validation";

    void setFeature(String name,
                           boolean state) throws XmlPullParserException;

    boolean getFeature(String name);

    void setProperty(String name,
                            Object value) throws XmlPullParserException;

    Object getProperty(String name);

    void setInput(Reader in) throws XmlPullParserException;

    void setInput(InputStream inputStream, String inputEncoding)
        throws XmlPullParserException;

    String getInputEncoding();

    void defineEntityReplacementText( String entityName,
                                            String replacementText ) throws XmlPullParserException;

    String getNamespacePrefix(int pos) throws XmlPullParserException;

    String getNamespace (String prefix);

    int getDepth();

    String getPositionDescription ();

    int getLineNumber();

    int getColumnNumber();

    boolean isWhitespace() throws XmlPullParserException;

    String getText ();

    char[] getTextCharacters(int [] holderForStartAndLength);

    String getName();

    String getPrefix();

    boolean isEmptyElementTag() throws XmlPullParserException;

    int getAttributeCount();

    String getAttributeNamespace (int index);

    String getAttributeName (int index);

    String getAttributePrefix(int index);

    String getAttributeType(int index);

    boolean isAttributeDefault(int index);

    String getAttributeValue(int index);

    String getAttributeValue(String namespace,
                                    String name);

    // 实际解析方法
    int getEventType()
        throws XmlPullParserException;

    int next()
        throws XmlPullParserException, IOException;

    int nextToken()
        throws XmlPullParserException, IOException;

    void require(int type, String namespace, String name)
        throws XmlPullParserException, IOException;

    String nextText() throws XmlPullParserException, IOException;

    int nextTag() throws XmlPullParserException, IOException;
}

关键API

  • int next()

    将parser移动到下一个“事件”;

    可能返回下面这些事件:

    • START_TAG

      可通过getName()获取标签名;

      可通过getAttributeCount()获取标签内属性个数;

      可通过getAttributeNamespace(index)获取属性命名空间;

      可通过getAttributeName(index)获取属性名字;

      可通过getAttributeValue(index)获取属性值;

    • TEXT

      可通过getText()获取文本内容

    • END_TAG

      可通过getName()获取标签名

    • END_DOCUMENT

  • nextToken()

  • getEventType()

    初始状态为START_DOCUMENT

一个简单的Demo

    private fun parseXmlInner(reader: Reader): String {
        val factory = XmlPullParserFactory.newInstance()
        factory.isNamespaceAware = true
        val parser = factory.newPullParser()
        parser.setInput(reader)

        val result = StringBuilder()
        var eventType = parser.eventType
        while (eventType != XmlPullParser.END_DOCUMENT) {
            when (eventType) {
                XmlPullParser.START_DOCUMENT -> {
                    result.append("Start document\n")
                    Log.d(tag, "Start document")
                }
                XmlPullParser.START_TAG -> {
                    result.append("Start tag : ${parser.name} props: ${(0 until parser.attributeCount).map { "${parser.getAttributeValue(it)} : ${parser.getAttributeValue(it)}" }}\n")
                    Log.d(tag, "Start tag : ${parser.name} props: ${(0 until parser.attributeCount).map { "${parser.getAttributeValue(it)} : ${parser.getAttributeValue(it)}" }}")
                }
                XmlPullParser.TEXT -> {
                    result.append("Text : ${parser.text}\n")
                    Log.d(tag, "Text : ${parser.text}")
                }
                XmlPullParser.END_TAG -> {
                    result.append("End tag : ${parser.name}\n")
                    Log.d(tag, "End tag : ${parser.name}")
                }
                else -> {
                }
            }
            eventType = parser.next()
        }
        result.append("End document\n")
        Log.d(tag, "End document")
        return result.toString()
    }

不是很重要的一些解释

  • CDSECT

    其实就是CDATA,即:

    <![CDATA[

    表示这部分不是字符串数据,在XML Pull API中是只读的,只有调用nextToken()的时候才有用,通过getText()可获取其中的文本内容

  • ENTITY_REF

    也是只有调用nextToken()的时候才有用

  • IGNORABLE_WHITESPACE

    也是只有调用nextToken()的时候才有用

    它与isWhitespace()方法不同,因为文本内容可能是空格,但是不能被忽略

  • PROCESSING_INSTRUCTION

    也是只有调用nextToken()的时候才有用

  • COMMENT

    也是只有调用nextToken()的时候才有用;

    调用next()的时候会自动忽略注释

  • DOCDECL

    也是只有调用nextToken()的时候才有用;


文章作者: 姜康
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 姜康 !
评论
 上一篇
LayoutInflater原理分析 LayoutInflater原理分析
两种资源 预编译的layout资源(dex文件) xml layout文件 预编译的布局目前的版本(Android 11)并没有开放这个功能. 基本的处理流程如下: 使用view_compiler将xml布局直接编译成CompiledV
2021-01-04
下一篇 
Context.getSystemService()实现解析 Context.getSystemService()实现解析
Android中经常会通过context.getSystemService(Context.XX_Service),这里简单看一下实现方式. 在ContextImpl.java中有: @Override public Obj
2020-12-28
  目录