XML 解析

XML 解析


1. 解析概述

     当将数据存储在XML后,我们就希望通过程序获得XML的内容。如果我们使用Java基础所学习的IO知  识是可以完成的,不过你需要非常繁琐的操作才可以完成,且开发中会遇到不同问题(只读、读写)。  人们为不同问题提供不同的解析方式,并提交对应的解析器,方便开发人员操作XML

2.XML解析方式

开发中比较常见的解析方式有两种,如下:

2.1 DOM:要求解析器把整个XML文档装载到内存,并解析成一个Document对象。

  • 优点:元素与元素之间保留结构关系,故可以进行增删改查操作。
  • 缺点:XML文档过大,可能出现内存溢出显现。                                                      

2.2 SAX:是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。并以事件驱动的方  式进行具体解析,每执行一行,都将触发对应的事件。(了解)

  • 优点:占用内存少 处理速度快,可以处理大文件
  • 缺点:只能读,逐行后将释放资源。

3. XML常见的解析器

解析器:就是根据不同的解析方式提供的具体实现。有的解析器操作过于繁琐,为了方便开发人员,  有提供易于操作的解析开发包

  • JAXP:sun公司提供的解析器,支持DOM和SAX两种思想
  • DOM4J:一款非常优秀的解析器 , Dom4j是一个易用的、开源的库,用于XML,XPath和XSLT。它应用于Java平台,采用了Java集合框架并完全支持DOM,SAX和JAXP。
  • Jsoup:jsoup 是一款Java 的HTML解析器 ,也可以解析XML
  • PULL:Android内置的XML解析方式,类似SAX。

4. dom4j 的使用

4.1 导入JAR包

4.2 API介绍

使用核心类SaxReader加载xml文档获得Document,通过Document  对象获得文档的根元素,然后就可以操作了

常用API如下:

  • SaxReader对象

read(…) 加载执行xml文档

  • Document对象

getRootElement() 获得根元素

  • Element对象

elements(…) 获得指定名称的所有子元素。可以不指定名称

element(…) 获得指定名称的第一个子元素。可以不指定名称

getName() 获得当前元素的元素名

attributeValue(…) 获得指定属性名的属性值

elementText(…) 获得指定名称子元素的文本值

getText() 获得当前元素的文本内容

5. 准备xml文件

编写user.xsd schema约束,代码如下:

<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns="http://www.lagou.com/xml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.lagou.com/xml"
elementFormDefault="qualified">


<xsd:element name="users" type="usersType"/>
<xsd:complexType name="usersType">
<xsd:sequence>
<xsd:element name="user" type="userType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>


<xsd:complexType name="userType">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="age" type="ageType" />
<xsd:element name="hobby" type="hobbyType" />
</xsd:sequence>
<xsd:attribute name="id" type="numberType" use="required"/>
</xsd:complexType>


<xsd:simpleType name="ageType">
<xsd:restriction base="xsd:integer">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="100"/>
</xsd:restriction>
</xsd:simpleType>


<xsd:simpleType name="hobbyType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="抽烟"/>
<xsd:enumeration value="喝酒"/>
<xsd:enumeration value="烫头"/>
</xsd:restriction>
</xsd:simpleType>


<xsd:simpleType name="numberType">
<xsd:restriction base="xsd:string">
<xsd:pattern value="\d"/>
</xsd:restriction>
</xsd:simpleType>


</xsd:schema>

编写user.xml 引入约束,代码如下:

<?xml version="1.0" encoding="UTF-8" ?>
<users
xmlns="http://www.lagou.com/xml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.lagou.com/xml user.xsd"
>
<user id="1">
<name>张百万</name>
<age>20</age>
<hobby>抽烟</hobby>
</user>

<user id="2">
<name>于谦</name>
<age>50</age>
<hobby>喝酒</hobby>
</user>

<user id="3">
<name>刘能</name>
<age>40</age>
<hobby>烫头</hobby>
</user>
</users>

6. 读取XML

public class TestDOM4j {

//获取XML文件中的 所有的元素名称(标签) @Test
public void test1() throws DocumentException {

//1.获取XML解析对象
SAXReader reader = new SAXReader();

//2.解析XML 获取 文档对象 document Document document =
reader.read("H:\\jdbc_work\\xml_task03\\src\\com\\lagou\\xml03\\user.xml");

//3.获取根元素
Element rootElement = document.getRootElement();

//获取根元素名称System.out.println(rootElement.getName());

//获取 根元素下的标签
List<Element> elements = rootElement.elements(); for (Element element : elements) {
System.out.println("根标签下的子节点: " + element.getName());

List<Element> eList = element.elements(); for (Element e : eList) {
System.out.println("user标签下的子节点" + e.getName());
}

break;
}

}
/**
* 获取具体的节点内容 获取张百万的所有信息
*/ @Test
public void test2() throws DocumentException {
//1.创建XML文档解析对象
SAXReader sr = new SAXReader();

//2.读取XML获取到document对象
Document document = sr.read("src\\com\\lagou\\xml02\\user.xml");

//3.获取根节点
Element rootElement = document.getRootElement();

//4.得到当前节点的 所有子节点
List<Element> elements = rootElement.elements();

//5.获取第一个子节点
Element user = elements.get(0);

//6.获取所有信息
String id = user.attributeValue("id"); String name = user.elementText("name"); String age = user.elementText("age");
//使用getText获取当前元素的文本内容
String hobby = user.element("hobby").getText();

//打印
System.out.println(id+" " + name +" " + age +" " + hobby);
}

7. xpath方式读取xml

7.1 xpath介绍

XPath 是一门在 XML 文档中查找信息的语言。 可以是使用xpath查找xml中的内容。
XPath 的好处
     由于DOM4J在解析XML时只能一层一层解析,所以当XML文件层数过多时使用会很不方便,结合
XPATH就可以直接获取到某个元素

需要再导入 jaxen-1.1-beta-6.jar

7.2 XPath基本语法介绍

使用dom4j支持xpath的操作的几种主要形式

语法

说明

/AAA/DDD/BBB

表示一层一层的,AAA下面 DDD下面的BBB

//BBB

表示和这个名称相同,表示只要名称是BBB,都得到

//*

所有元素

BBB[1] , BBB[last()]

第一种表示第一个BBB元素, 第二种表示最后一个BBB元素

//BBB[@id]

表示只要BBB元素上面有id属性,都得到

//BBB[@id='b1']

表示元素名称是BBB,BBB上面有id属性,并且id的属性值是b1

7.3 API介绍

常用方法:

  • selectSingleNode(query): 查找和 XPath 查询匹配的一个节点。

       参数是Xpath 查询串。

  • selectNodes(query): 得到的是xml根节点下的所有满足 xpath 的节点;

       参数是Xpath 查询串。

  • Node: 节点对象

7.4 Xpath读取XML

1)数据准备book.xml 代码如下:

<?xml version="1.0" encoding="UTF-8" ?>
<bookstore>
    <book id="book1">
        <name>金瓶梅</name>
        <author>金圣叹</author>
        <price>99</price>
    </book>
    <book id="book2">
        <name>红楼梦</name>
        <author>曹雪芹</author>
        <price>69</price>
    </book>
    <book id="book3">
        <name>Java编程思想</name>
        <author>埃克尔</author>
        <price>59</price>
    </book>
</bookstore>

2)使用Xpath语法解析book.xml 代码如下:

package com.lagou.xml04;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.junit.Test;

import java.util.List;

public class TestXPath {

    /*
    *  使用selectSingleNode() 方法 查询自定的节点信息
    *
    * */
    @Test
    public void test1() throws DocumentException {

        //1.创建XML解析对象
        SAXReader reader = new SAXReader();

        //2.解析XML 获取 文档对象
        Document document = reader.read("H:\\jdbc_work\\xml_task03\\src\\com\\lagou\\xml04\\book.xml");

        //3.通过selectSingleNode() 方法获取 name节点
        Node node1 = document.selectSingleNode("/bookstore/book/name");
        System.out.println("节点的名称: " + node1.getName());
        System.out.println("书名: " + node1.getText());

        //4.获取第二本书的书名
        Node node2 = document.selectSingleNode("/bookstore/book[3]/name");
        System.out.println("书名: " + node2.getText());
    }


    /*
    * 使用 selectSIngleNode() 方法获取 属性值 或者 通过属性值获取到节点信息
    *
    * */
    @Test
    public void test2() throws DocumentException {

        SAXReader reader = new SAXReader();

        Document document = reader.read("H:\\jdbc_work\\xml_task03\\src\\com\\lagou\\xml04\\book.xml");

        //1.获取第一个booke节点中的  id属性的值
        Node node1 = document.selectSingleNode("/bookstore/book/attribute::id");
        System.out.println("第一个book的id属性值: " + node1.getText() );

        //2.获取最后一个book节点的 id属性值
        Node node2 = document.selectSingleNode("/bookstore/book[last()]/attribute::id");
        System.out.println("最后一个book节点中的属性值: " + node2.getText());

        //3.通过id的值 获取book2节点 中的书名
        Node node3 = document.selectSingleNode("/bookstore/book[@id='book2']");

        String name = node3.selectSingleNode("name").getText();
        System.out.println("id为book2的 节点的书名是: " + name);

    }

    /*
    *  使用selectNodes() 获取所有指定名称 的节点
    *
    * */
    @Test
    public void test3() throws DocumentException {

        SAXReader reader = new SAXReader();

        Document document = reader.read("H:\\jdbc_work\\xml_task03\\src\\com\\lagou\\xml04\\book.xml");

        //1.查询所有的节点
        List<Node> list = document.selectNodes("//*");

        for (Node node : list) {
            System.out.println("节点名: " + node.getName());
        }

        //2.获取所有的书名
        List<Node> list1 = document.selectNodes("//name");
        for (Node node : list1) {
            System.out.println("书名: " + node.getText());
        }

        //3.获取 id值为 book1 的节点中的所有内容
        List<Node> list2 = document.selectNodes("/bookstore/book[@id='book1']//*");
        for (Node node : list2) {
            System.out.println(node.getName() + " = " + node.getText());
        }
    }
}

节选自拉钩教育JAVA系列教程

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值