啃Java的日子之DOM 解析

本文介绍XML(可扩展标记语言)的基础概念及其用途,并详细讲解了如何使用Java中的DOM方法解析XML文件,包括获取节点名、节点值及属性等关键信息。

什么是XML?

渣渣在这里也是初步了解了一下。Extentsible Markup Language(可扩展标记语言)的缩 写,是用来定义其它语言的一种元语言。我们打开每一个XML 文件都可以看出来他们的标签都是成对存在的(尴尬又是成对),我们对于XML 文件来说他的存储结构是一个倒着的树状结构,开始是一个根节点。

xml的用途:
存提供的储通信信息,相同的xml 文件可以连接不同的东西,包括不同的平台不同的编辑环境

解析xml文件:

读取xml 文件的内容,获取节点名,节点值,属性名和属性值。

常用的四种解析方式:DOM SAX DOM4J JDOM 。前两中是由官方提供的。

下面我们尝试着解析一个XML 文件

随意写了一个XML 文件

<?xml version="1.0" encoding="UTF-8"?>
<studentinfo>
<student id="1">
 <name>jack</name>
 <age>19</age>
 <sex>man</sex>
</student>

<student id="2" name="sam">
 <class>1</class>
 <sex>man</sex>
 <grade>2</grade>
</student>
</studentinfo>


我们先来了解几个接口

(1)DocumentBuilderFactroy

定义工厂API ,使得程序能够从XML文档获取生成DOM 对象数的解析器。

(2)DocumentBuilder

使用此API 可以从XML 中获取到一个document。此类的实例可以从 DocumentBuilderFactory.newDocumentBuilder() 方法获取。获取此类的实例之后,将可以从各种输入源解析 XML。

(3)Document

此接口表示整个HTML或者XML 文档,它是文档的树根并提供对文档数据的基本访问。

getElementByTag(String TagName):按文档的顺序返回包含在文档中的且具有给定标记名称的所有Element的NodeList。

import java.io.IOException;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class DomText {

    /**
     * @param args
     * @throws ParserConfigurationException
     * @throws IOException
     * @throws SAXException
     */
    public static void main(String[] args) throws SAXException, IOException, ParserConfigurationException {
        // 获取DocumentBuilderFactory新实例
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        // 创建DocumentBuilder实例并且通过方法parse传入所要解析的XML 文件。获取一个document(org.w3c.dom)
        Document bd = dbf.newDocumentBuilder().parse("book.xml");

        /**
         * 解析属性
         */

        // 根据标签名获取标签集合 NodeList(org.w3c.dom)类型
        NodeList nodelist = bd.getElementsByTagName("student");
        System.out.println("总共有" + nodelist.getLength() + "个学生");
        for (int i = 0; i < nodelist.getLength(); i++) {
            // 获取NodeList中对应的mouyixian
            Node node = nodelist.item(i);
            // 获取对应的节点的属性
            NamedNodeMap nnm = node.getAttributes();
            System.out.println("第" + (i + 1) + "学生共有" + nnm.getLength() + "属性");
            System.out.print("属性有:");
            for (int j = 0; j < nnm.getLength(); j++) {
                Node nd = nnm.item(j);
                System.out.print(" " + nd.getNodeName());

            }

            /**
             * 解析子节点
             */
            System.out.println(" ");
            System.out.println("获取节点的值");
            // 获取此时对应项的子节点,返回子节点集合 NodeList 类型
            NodeList nl = node.getChildNodes();
            for (int k = 0; k < nl.getLength(); k++) {
                // 筛选显示
                if (nl.item(k).getNodeType() == Node.ELEMENT_NODE)
                { System.out.print(" " + nl.item(k).getNodeName());
                    //按照我们所想象的如果获取子节点的value或许可以这样做
                    System.out.print(": "+nl.item(k).getNodeValue());
                }
<span style="font-family: Arial, Helvetica, sans-serif;"> }</span>
            System.out.println(" ");
        }

    }
}

在上面的代码其中有一个筛选的部分。对于DOM 文件存在以下几种常用的结点类型:


那么对于要获取节点的value该如何去做,刚开始认为采用函数getNodeValue(),就可以 了,但是运行结果出来却是null。

其实答案在上面的表格就很明显,直接采用nl.item(k).getNodeValue()获取到的是Element 节点 的value固然是null

在解析的时候他会将<> XXX</>之间的取值认为是一个子节点,所以我们在取值的时候应该采用子节点的方式,所以采用如下的代码:

第一种:

  System.out.print(": "+nl.item(k).getFirstChild().getNodeValue());
第二种:

System.out.print(": "+nl.item(k).getTextContent());
 

这两种都可以获取到正确的value  但是两者有什么区别?我们改变一下最初我们的XML 文件,来进行对比。

我们在第一个student的那么之间加入子节点<front></front>

我们运行以下程序看一下两者结果的区别:

第一种:



值是null,因为此时第一个孩子结点是front,他是一个element节点 所以他的value是null

第二种:

 

正确获取!!!!!

Java API中给出了这样的解释:



以在XML 进行解析的时候,会将空格和换行符也会认为是一个结点,会已#text 输出,所以我们需要进行筛选,去掉这一项。

总结一个错误:

A pseudo attribute name is expected.  错误表XML 文件中存在错误,文件不规范,无法查找到。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值