XML第十四讲:使用DOM解析XML文档 续

    上一讲:使用DOM解析XML文档 内容我们讲解了DOM解析XML的主要内容和流程,把XML文档的内容解析到一个个的Java对象中去供程序使用,利用JAXP,我们只需几行代码就能做到这一点。

    JAXP(Java API for XML Parsing):用于XML解析的Java API。这是SUN公司为我们提供的处理XML的接口。

1. DOM的基本对象

1) Node对象:DOM结构中最为基本的对象
2) Document对象:代表整个XML的文档
3) NodeList对象:包含一个或者多个Node的列表
4) Element对象:代表XML文档中的标签元素

  通过解析XML文档,为XML文档在逻辑上建立一个树模型,树的节点是一个个对象,通过存取这些对象就能够存取XML文档的内容。遍历这个树来解析文档内容。

5)查看JDK文档中的Node,可以发现它的子接口有Attr、Document、Element、Text等 其中Text表示文本中间的内容

2. DOM解析XML中,首先,我们需要建立一个解析器工厂,以利用这个工厂来获得一个具体的解析器对象

  但是工厂在哪里呢?之前我们所讲的简单工厂模式,工厂是具体存在的,而对于DOM来说,工厂我们也要通过环境变量来设置的。下面我就来具体的剖析一下这里相关的内容。

1)建立工厂的方法[基本都是按着这种模式来进行的]

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

   我们在这里使用DocumentBuilderFacotry的目的是为了创建与具体解析器无关的程序,当DocumentBuilderFactory 类的静态方法newInstance()被调用时,它根据一个系统变量来决定具体使用哪一个解析器。又因为所有的解析器都服从于JAXP所定义的接口,所以无论具体使用哪一个解析器,代码都是一样的。所以当在不同的解析器之间进行切换时,只需要更改系统变量的值,而不用更改任何代码。这就是工厂所带来的好处。

   在上一讲的程序中,我们试着打印出解析器工厂和解析器的类名

        /*
         * Step 1: 获得dom解析器工厂(工厂的作用就是用于创建具体的解析器。)
         */
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        System.out.println("class name: " + dbf.getClass().getName());
        
        //Step 2: 获得具体的DOM解析器
        DocumentBuilder db = dbf.newDocumentBuilder();
        System.out.println("class name: " + db.getClass().getName());

[输出内容]:

class name: com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
class name: com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl

[说明]:建议在学习这一部分的内容的时候可以去参考一下JDK文档中DocumentBuilder的一些说明,知道解析器工厂和解析器之间的关系。

3. 下面我们再联系一下DOM解析XML的例子。

1) 解析下面的XML文档:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<学生名册>
	<学生 学号="1">
		<姓名>张三</姓名>
		<性别>男</性别>
		<年龄>20</年龄>
	</学生>
	<学生 学号="2">
		<姓名>李四</姓名>
		<性别>女</性别>
		<年龄>19</年龄>
	</学生>
	<学生 学号="3">
		<姓名>王五</姓名>
		<性别>男</性别>
		<年龄>21</年龄>
	</学生>
</学生名册>

2) 代码如下:

package com.ahuier.xml.dom;

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class DomTest3 {
    public static void main(String[] args) throws Exception {
        
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        
        DocumentBuilder db =  dbf.newDocumentBuilder();
        
        Document doc = db.parse(new File("student.xml"));
      
      /*
       * 打印输出student.xml的一些版本信息、编码方式等
       * 输出:1.0、UTF-8、true
       */
//        System.out.println(doc.getXmlVersion());
//        System.out.println(doc.getXmlEncoding());
//        System.out.println(doc.getXmlStandalone());
        
        /*
         * 我们上一个例子是获得Document对象,然后获得NodeList,这会我们换一下,获得文档的根元素节点
         * 查看JDK文档中的Document的方法
         * 使用 Element getDocumentElement() 方法
         */
        Element root =  doc.getDocumentElement();
        System.out.println(root.getTagName());  //打印出:学生名册
        
        /*
         * 查看Element中的方法
         * 使用这个方法:NodeList getChildNodes() 
         * 它返回这个对象节点的所有孩子孩子的列表,如果这个节点没有孩子节点,则返回为空
         */
        
        NodeList list = root.getChildNodes();
        
      //注意这边打印为7个。为什么是7个呢? 因为XML默认为空格也算是一个节点的孩子节点,可以尝试把XML中元素之间的空格去掉验证
        System.out.println(list.getLength()); 
        for(int i = 0; i < list.getLength(); i++){
            
            //打印出这个节点的各个孩子节点的节点名称
            System.out.println(list.item(i).getNodeName());
            
        }
    }
}
编译执行结果:

学生名册
7
#text
学生
#text
学生
#text
学生
#text

[说明]:

1)这边的孩子节点为7个原因是因为在XML解析中,它把元素之间的空格也算作是一个节点了,可以尝试在上诉XML中删除部分空格验证一下,如下XML文档

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<学生名册>
	<学生 学号="1">
		<姓名>张三</姓名>
		<性别>男</性别>
		<年龄>20</年龄>
	</学生><学生 学号="2">
		<姓名>李四</姓名>
		<性别>女</性别>
		<年龄>19</年龄>
	</学生>
	<学生 学号="3">
		<姓名>王五</姓名>
		<性别>男</性别>
		<年龄>21</年龄>
	</学生>
</学生名册>
[编译执行结果]:中间去点一元素之间的空格后,结果输出为6个

2) 为什么会打印出 #text 的内容呢?请查看JDK文档中的Node,这里面有很详细的描述。

nodeName,nodeValue, and attributes 等等根据节点类型的不同,他们会有这样的取值,如下图所示

  上诉例子中空格属于文本(Text)所以在遍历的时候就 nodeName就会出现 #text符号了,当然还可以发现上一讲程序中为什么Element打印出来是为 null的了。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值