第一行代码 第三版 第11章 网络技术 11.3解析XML格式

11.3 解析XML格式数据

11.3.1 Pull 解析方式

创建一个XmlPullParserFactory的实例,借助这个实例得到XmlPullParser 对象;
调用 XmlPullParser 对象的setInt()方法将服务器返回的XML数据设置进去,然后开始解析;
通过 getEventType()方法得到当前的解析事件,在一个while循环中 不断地进行解析,当前解析事件不等于XmlPullParser.END_DOCUMENT 时 说明解析工作未完成。
调用next()方法后可以获得下一个解析事件;
**getName()**方法可以得到当前节点的名字。
nextText() 方法可以获取节点内的具体内容;
在这里插入图片描述

private fun parseXMLWithPull(xmlData: String){
        try {
            val factory = XmlPullParserFactory.newInstance()//创建一个XmlPullParserFactory的实例
            val xmlPullParser = factory.newPullParser()		//得到XmlPullParser 对象
            xmlPullParser.setInput(StringReader(xmlData))	// XmlPullParser 对象的setInt()方法将服务器返回的XML数据设置进去
            var eventType = xmlPullParser.eventType			//用于判断当前节点的类型
            var id= ""
            var name = ""
            var version = ""	//三个变量用于接收数据
            while (eventType !=XmlPullParser.END_DOCUMENT){
                val nodeName = xmlPullParser.name
                when(eventType){
                    //开始解析某个节点
                    XmlPullParser.START_TAG ->{
                        when(nodeName){
                            "id" -> id=xmlPullParser.nextText()
                            "name" ->name =xmlPullParser.nextText()
                            "version" ->version =xmlPullParser.nextText()
                        }
                    }
                    //完成解析某个节点
                    XmlPullParser.END_TAG ->{
                        if("app"==nodeName){
                            Log.d("MainActivity","id is $id")
                            Log.d("MainActivity","name is $name")
                            Log.d("MainActivity","version is $version")
                        }
                    }
                }
                eventType = xmlPullParser.next()
            }
        }catch (e:Exception){e.printStackTrace()}
    }

使用明文方式传入可以用书上的代码,也可以使用usesCleartextTraffic 属性 ,(我自己运行后 这两种都可以运行出正确答案)
在这里插入图片描述

11.3.2 SAX解析方式

要使用SAX解析,需要创建一个类用于继承自DefaultHandler,并重写父类的五个方法:

class MyHandler :DefaultHandler() {
    override fun startDocument() {//在开始解析XML的时候调用
    }
    override fun startElement(//在开始解析某个节点的时候调用
        uri: String?,
        localName: String?,
        qName: String?,
        attributes: Attributes?
    ) {        
    }
    override fun characters(ch: CharArray?, start: Int, length: Int) {        //在获取节点中内容的时候调用
    }
    override fun endElement(uri: String?, localName: String?, qName: String?) {        //完成解析某个节点时盗用
    }
    override fun endDocument() {//在完成整个XML解析的时候调用
    }
}

调用方式:在创建的类中处理解析的具体逻辑
在使用处的调用方式:先创建一个SAXParserFactory 对象;
然后获取xmlReader 对象 ;接着讲我们编写的Holder 的实例设置到xmlReader中;
最后调用parse() 方法开始执行。

private fun parseXMLWithSAX(xmlData :String){
        try {
            val factory = SAXParserFactory.newInstance()
            val xmlReader = factory.newSAXParser().xmlReader
            val handler =ContentHandler()
            //将ContentHandler 的实例设置到XMLReader中
            xmlReader.contentHandler = handler
            //开始执行解析
            xmlReader.parse(InputSource(StringReader(xmlData)))
        }catch (e:Exception){
            e.printStackTrace()
        }
    }

//ContentHandler.kt文件
class ContentHandler :DefaultHandler() {
    private var nodeName :String?=" "
    private lateinit var id:StringBuilder
    private lateinit var name:StringBuilder
    private lateinit var version:StringBuilder

    override fun startDocument() {
        id= StringBuilder()
        name=StringBuilder()
        version=StringBuilder()
    }

    override fun startElement(
        uri: String?,
        localName: String?,//当前节点名
        qName: String?,
        attributes: Attributes?
    ) {
        //记录当前节点名
        nodeName = localName
        Log.d("ContentHandler","uri is $uri")
        Log.d("ContentHandler","localName is $localName")
        Log.d("ContentHandler","qName is $qName")
        Log.d("ContentHandler","attributes is $attributes")
    }

    override fun characters(ch: CharArray?, start: Int, length: Int) {
        //根据当前节点名判断将内容添加到哪一个StringBuilder对象中
        when(nodeName){
            "id" -> id.append(ch,start,length)
            "name" -> name.append(ch,start,length)
            "version" -> version.append(ch,start,length)
        }
    }

    override fun endElement(uri: String?, localName: String?, qName: String?) {
        if("app"==localName){
            Log.d("ContentHandler","id is ${id.toString().trim()}")
            Log.d("ContentHandler","name is ${name.toString().trim()}")
            Log.d("ContentHandler","version is ${version.toString().trim()}")
            //最后要将StringBuilder清空
            id.setLength(0)
            name.setLength(0)
            version.setLength(0)
        }
    }

    override fun endDocument() {
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值