XML技术

本文介绍了XML技术的基础知识,包括其设计目的与实际应用,并详细对比了DOM与SAX两种主流解析方法的特点与应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

XML技术

介绍

XML(EXtensible Markup Language)指可扩展标记语言,XML的设计宗旨是传输数据(具有自描述性)而非显示数据。
但是目前人们更多的是使用XML做配置文件而非作为传输数据的载体,业界更多的是使用JSON格式字符串来做载体。

XML技术其实很简单,尤其对于java程序开发人员而言XML技术非常重要XML也算是一个比较悲情的技术,
XML设计之初并不是主要为了作配置文件而设计的,然而目前XML最主要的用途就是作配置文件和数据传输格式。

XML解析

学习XML技术很重要的一点就是解析XML文件

解析XML两种方式

    官方的DOM标准解析:其实学习DOM标准接口并不仅仅有助于解析XML,学好DOM也是有助于之后学习JavaScript的。

    民间的SAX流解析:基于流来解析XML文件

两种解析方式区别

备注:DOM解析需要将整个XML文件加载到内存中,然后将其虚拟成一棵DOM树,对于比较大的文件来说,解析效率就比较低了。
而SAX是基于流(事件模型)来解析的,它不需要将XML文件都载入到内存然后才能开始解析,它可以载入一部分解析一部分。

DOM解析XML文件

DOM解析XML文件顾名思义就是将XML文件看作是DOM树来对待,所以DOM解析XML的关键就是获得文档对象(Document)。
我觉得DOM模型比XML解析技术本身更有意义,因为DOM模型是w3c抽象出来的标准接口。

要学好DOM第一步就是理解文档对象模型,在DOM定义的标准接口中,将XML中的所有元素都看作是节点Node(),注意Element也是继承Node节点的。

文档对象模型

文档对象模型

几种重要的元素(节点)类型

//元素节点
ELEMENT_NODE = 1;
//属性节点
ATTRIBUTE_NODE = 2;
//文本节点
TEXT_NODE = 3;
//CDATA节点
CDATA_SECTION_NODE = 4;
//注释节点
COMMENT_NODE = 8;
//文档节点
DOCUMENT_NODE = 9;

Node和Element类

w3c定义的DOM模型,将XML所有的元素都当作节点看待,Node表示节点,Element表示元素继承Node节点。所以它们都是节点。

备注:查看源码看Node节点和Element里面定义了哪些重要方法
掌握Node节点和Element元素非常重要。

获得文档对象Document

//获得XML文件的输入流
InputStream inputStream = new FileInputStream(new File("e:/persons.xml"));
// 创建文档构造器工厂
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
// 创建文档构造器
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();

// 获得文档对象
Document document = documentBuilder.parse(inputStream);

//获得根节点
Element root=document.getDocumentElement();

通过递归获得某个节点下所有的文本节点对应的内容

/**
 * 通过递归Node节点来获得该Node节点下所有的文本节点内容
 * 
 * @param node
 */
private static void getTextNodeValue(Node node) {

    if (node == null) {
        return;
    }
    NodeList nodeList = node.getChildNodes();
    if (nodeList.getLength() > 1) {
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node temNode = nodeList.item(i);
            if (temNode.getNodeType() == Node.ELEMENT_NODE) {
                getTextNodeValue(temNode);
            }
        }
    }
    if (node.getNodeType() == Node.ELEMENT_NODE && node.getChildNodes().getLength() == 1) {
        System.out.println(node.getNodeName() + ":" + node.getFirstChild().getNodeValue());
    }

}

SAX解析XML

相比使用DOM接口来解析XML我觉得SAX并没有DOM重要,因为SAX是为了解决当当个XML文件比较大的时候,DOM解析效率就会降低内存消耗也比较大,因为DOM解析式需要将整个XML文件都载入到内存中解析的。SAX解析可以说是一种新的思想方式来解决了这个问题,基于事件模型来解析XML文件。遇到开始标签就开始解析,直到遇到闭合标签就解析完一个元素了。

获取SAXParser解析对象

// 创建一个解析XML的工厂对象
SAXParserFactory parserFactory = SAXParserFactory.newInstance();
// 创建一个解析XML的对象
SAXParser parser = parserFactory.newSAXParser();

自定义事件处理器

通常我们自定义事件处理器来解析特定的XML文件,通常我们都是自定义一个类使其继承DefaultHandler然后覆盖里面的一些方法完成我们自己想要的逻辑。

自定义事件处理器代码参考

/**
 * 
 * 基于SAX解析XML文件,根据某个节点标签获取该节点下的所有子元素内容(只能拿到一级元素)。
 * 
 * 
 * @author xuyi3
 * @2016年7月20日 @下午1:37:48
 * @PersonHandler
 * @功能说明:<br>
 * @春风十里不如你
 * @备注
 */
public class PersonHandler extends DefaultHandler {

    // 存储正在解析的元素的数据
    private Map<String, String> map = null;
    // 存储所有解析的元素的数据
    private List<Map<String, String>> list = null;
    // 正在解析的元素的名字
    private String currentTag = null;
    // 正在解析的元素的元素值
    private String currentValue = null;
    // 开始解析的元素
    private String nodeName = null;

    public PersonHandler() {

    }

    public PersonHandler(String nodeName) {
        this.nodeName = nodeName;
    }

    public List<Map<String, String>> getList() {
        return list;
    }

    @Override
    public void startDocument() throws SAXException {

        list = new ArrayList<Map<String, String>>();

    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

        if (nodeName.equals(qName)) {
            map = new HashMap<String, String>();
        }
        if (attributes != null && map != null) {
            for (int i = 0; i < attributes.getLength(); i++) {
                String key = attributes.getQName(i);
                String value = attributes.getValue(i);
                map.put(key, value);
            }
        }
        currentTag = qName;
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {

        if (currentTag != null && map != null) {
            currentValue = new String(ch, start, length);
            if (currentValue != null && !currentValue.trim().equals("") && !currentValue.trim().equals("\n")) {
                map.put(currentTag, currentValue);
            }
        }

        currentTag = null;
        currentValue = null;

    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {

        // 解析完该元素之后,将map加入到List集合中,然后清空map解析下一个元素。
        if (nodeName.equals(qName)) {
            list.add(map);
            System.out.println("===" + list);
            map = null;
        }

    }

    @Override
    public void endDocument() throws SAXException {

    }

}

基于JDOM解析XML

TODO ...

基于DOM4J解析XML

TODO ...

基于Xstream映射XML to JavaBean

总结

XML技术并不难,但是却是比较重要的一项基本必备技术。其实现在解析xml的组件有很多,个人日常开发比较喜欢Xstream来将xml映射成java对象来处理。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值