XML解析【介绍、DOM、SAX详细说明、jaxp、dom4j、XPATH】

本文介绍了XML解析的基本概念,包括DOM和SAX解析方式,讲解了JAXP、DOM4J和XPath的使用。DOM解析将XML加载到内存中形成DOM树,适合小型文件;SAX解析则采用事件驱动,适用于大型文件。DOM4J是高效的XML API,弥补了DOM和SAX的不足。XPath则提供了一种在XML文档中查找信息的路径语言,简化了节点的定位。文章通过实例展示了XML的各种操作,如遍历、查询、增加、修改和删除。
摘要由CSDN通过智能技术生成

什么是XML解析

前面XML章节已经说了,XML被设计为“什么都不做”,XML只用于组织、存储数据,除此之外的数据生成、读取、传送等等的操作都与XML本身无关!

XML解析就是读取XML的数据!


XML解析方式

XML解析方式分为两种:

①:dom(Document Object Model)文档对象模型,是W3C组织推荐解析XML的一种方式

②:sax(Simple API For XML),它是XML社区的标准,几乎所有XML解析器都支持它!

XML解析操作

从上面的图很容易发现,应用程序不是直接对XML文档进行操作的,而是由XML解析器对XML文档进行分析,然后应用程序通过XML解析器所提供的DOM接口或者SAX接口对分析结果进行操作,从而间接地实现了对XML文档的访问!

常用的解析器和解析开发包的关系如下所示


为什么有3种开发包?

  • jaxp开发包是JDK自带的,不需要导入开发包。
  • 由于sun公司的jaxp不够完善,于是就被研发了Jdom。XML解析如果使用Jdom,需要导入开发包
  • dom4j是由于Jdom的开发人员出现了分歧,dom4j由Jdom的一批开发人员所研发。XML解析如果使用Jdom,需要导入开发包【现在用dom4j是最多的!】

jaxp

虽然jaxp解析XML的性能以及开发的简易度是没有dom4j好,但是jaxp不管怎么说都是JDK内置的开发包,我们是需要学习的

DOM解析操作

DOM解析是一个基于对象的API,它把XML的内容加载到内存中,生成与XML文档内容对应的模型!当解析完成,内存中会生成与XML文档的结构与之对应的DOM对象树,这样就能够根据树的结构,以节点的形式对文档进行操作!

简单来说:DOM解析会把XML文档加载到内存中,生成DOM树的元素都是以对象的形式存在的!我们操作这些对象就能够操作XML文档了!

  • 下面这样图就能很好地说明了,是怎么样生成与XML文档内容对应的DOM树!


既然XML文档的数据是带有关系型的,那么生成的DOM树的节点也是有关系的:

  • 位于一个节点之上的节点是该节点的父节点(parent)
  • 一个节点之下的节点是该节点的子节点(children)
  • 同一层次,具有相同父节点的节点是兄弟节点(sibling)
  • 一个节点的下一个层次的节点集合是节点后代(descendant)
  • 父、祖父节点及所有位于节点上面的,都是节点的祖先(ancestor)

在DOM解析中有几个核心的操作接口:

  • Document【代表整个XML文档,通过Document节点可以访问XML文件中所有的元素内容!】
  • Node【Node节点几乎在XML操作接口中几乎相当于普通Java类的Object,很多核心接口都实现了它,在下面的关系图可以看出!】
  • NodeList【代表着一个节点的集合,通常是一个节点中子节点的集合!】
  • NameNodeMap【表示一组节点和其唯一名称对应的一一对应关系,主要用于属性节点的表示(书上说是核心的操作接口,但我好像没用到!呃呃呃,等我用到了,我再来填坑!)】

节点之间的关系图:

  • 有人可能会很难理解,为什么Document接口比Node接口还小,呃呃呃,我是这样想的:一个Document由无数个Node组成,这样我也能把Document当然是Node呀!如果实在想不通:人家都这样设计了,你有种就不用啊!!(开玩笑的…..)

好的,不跟你们多bb,我们来使用一下Dom的方式解析XML文档吧!

  • XML文档代码

    <?xml version="1.0" encoding="UTF-8" ?>
    <china>
        <guangzhou >广州</guangzhou>
        <shenzhen>深圳</shenzhen>
        <beijing>北京</beijing>
        <shanghai>上海</shanghai>
    </china>

  • 根据XML解析的流程图,我们先要获取到解析器对象!


    public class DomParse {

        public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {

            //API规范:需要用一个工厂来造解析器对象,于是我先造了一个工厂!
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();

            //获取解析器对象
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();

            //获取到解析XML文档的流对象
            InputStream inputStream = DomParse.class.getClassLoader().getResourceAsStream("city.xml");

            //解析XML文档,得到了代表XML文档的Document对象!
            Document document = documentBuilder.parse(inputStream);

        }
    }
  • 解析XML文档的内容用来干嘛?无非就是增删改查遍历,只要我们会对XML进行增删改查,那就说明我们是会使用DOM解析的

遍历

  • 我们再来看一下XML文档的内容,如果我们要遍历该怎么做?

  • 可能我们会有两种想法

    • ①:从XML文档内容的上往下看,看到什么就输出什么!【这正是SAX解析的做法】
    • ②:把XML文档的内容分成两部分,一部分是有子节点的,一部分是没有子节点的(也就是元素节点!)。首先我们判断是否为元素节点,如果是元素节点就输出,不是元素节点就获取到子节点的集合,再判断子节点集合中的是否是元素节点,如果是元素节点就输出,如果不是元素节点获取到该子节点的集合….好的,一不小心就递归了…
  • 我们来对XML文档遍历一下吧,为了更好地重用,就将它写成一个方法吧(也是能够更好地用递归实现功能)


    public class DomParse {

        public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {

            //API规范:需要用一个工厂来造解析器对象,于是我先造了一个工厂!
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();

            //获取解析器对象
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();

            //获取到解析XML文档的File对象
            InputStream inputStream = DomParse.class.getClassLoader().getResourceAsStream("city.xml");

            //解析XML文档,得到了代表XML文档的Document对象!
            Document document = documentBuilder.parse(inputStream);

            //把代表XML文档的document对象传递进去给list方法
            list(document);

        }


        //我们这里就接收Node类型的实例对象吧!多态!!!
        private static void list(Node node) {

            //判断是否是元素节点,如果是元素节点就直接输出
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                System.out.println(node.getNodeName());
            }

            //....如果没有进入if语句,下面的肯定就不是元素节点了,所以获取到子节点集合
            NodeList nodeList = node.getChildNodes();

            //遍历子节点集合
            for (int i = 0; i < nodeList.getLength(); i++) {

                //获取到其中的一个子节点
                Node child = nodeList.item(i);

                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值