解析xml文件

本文介绍了XML数据格式及其与JSON的对比,强调了XML的结构清晰但冗余字符较多。接着详细讲解了XML解析的两种主要方法:DOM解析和SAX解析,包括它们的优缺点和适用场景。此外,还提到了第三方库Dom4j和XPath解析,其中Dom4j在实际应用中表现出较高的效率和便利性。
摘要由CSDN通过智能技术生成

1. xml是什么

1.1 常见的数据传输格式

1.json数据格式

{
	"dateTime":"2019-02-04 11:23:24",
	"orderNum":2143421354325
	"address":"陕西省西安市",
	"youbian":41000,
	"phone":13991812201
}

好处: 无用字符相对于xml少很多,结构也相对清晰


2.xml数据格式

<order>
    <datetime>2019-02-04 11:23:24</datetime>
    <orderNum>2143421354325</orderNum>
    <address>陕西省西安市</address>
    <youbian>41000</youbian>
    <phone>13991812201</phone>
</order>

好处: xml的数据结构比json格式的结构要清晰

弊端: 无用的字符太多了

所以: 现在我们在商业应用中进行数据交互,一般都是采用json格式


1.2 什么是xml?

xml: 可扩展标记语言

可扩展主要体现在xml中的标签名我们可以随便定义


xml中的标签的分类:

单标签: 标签中不需要存放内容,但需要一些特殊含义的时候使用单标签;

双标签: 标签中存放内容的时候我们使用双标签

但是xml中的语法比较严谨: 单标签必须闭合;

xml中的标签的语法建议:

  • 标签名称小写
  • 标签名称中不要出现中文
  • 标签名称不能以数字开头
  • 单标签必须闭合
  • 标签的属性值一定要加 双引号 或者 单引号

1.3 xml的完整写法

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
	<book id="01">
		<name>三国演义</name>
		<author>罗贯中</author>
		<price>110</price>
	</book>
	<book id="02">
		<name>西游记</name>
		<author>吴承恩</author>
		<price>210</price>
	</book>
	<book id="03">
		<name>红楼梦</name>
		<author>曹雪芹</author>
		<price>340</price>
	</book>
</bookstore>

2. xml解析

<?xml version="1.0" encoding="UTF-8" ?>
<bookStore>
    <book id="01">
        <name>三国演义</name>
        <author>罗贯中</author>
        <price>110</price>
    </book>
    <book id="02">
        <name>西游记</name>
        <author>吴承恩</author>
        <price>210</price>
    </book>
    <book id="03">
        <name>红楼梦</name>
        <author>曹雪芹</author>
        <price>340</price>
    </book>
</bookStore>

2.1 DOM解析(重要)

dom解析是jdk给我们自带的一种解析方式;

package xmlParse.DOM;

import org.w3c.dom.*;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;

public class DomParse {
    public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
        //1.创建Dom解析器工厂
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        //2.创建Dom解析器
        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
        //3.加载文件
        File file = new File("./BookStore.xml");
        //4.解析文件,获得document对象
        Document document = documentBuilder.parse(file);
        //获取根节点元素:document.getDocumentElement();    out:bookStore
        
        NodeList bookNodeList = document.getElementsByTagName("book");
        for (int i = 0; i < bookNodeList.getLength(); i++) {
            Node bookNode = bookNodeList.item(i);
            //如果这个结点是元素节点,就进行类型转换
            if (bookNode.getNodeType() == Node.ELEMENT_NODE) {
                Element bookElement = (Element) bookNode;
                //获取元素的标签名
                String bookElementTagName = bookElement.getTagName();
                System.out.print(bookElementTagName + " ");
                //获取属性
                Attr attr = bookElement.getAttributeNode("id");
                System.out.println(attr);
                
                //获得bookElement的子节点
                NodeList childNodeList = bookElement.getChildNodes();
                for (int j = 0; j < childNodeList.getLength(); j++) {
                    Node node = childNodeList.item(j);
                    if (node.getNodeType() == Node.ELEMENT_NODE) {
                        Element nodeElement = (Element) node;
                        //获得元素标签名
                        String tagName = nodeElement.getTagName();
                        //获得元素内容
                        String textContent = nodeElement.getTextContent();
                        System.out.println(tagName + ": " + textContent);
                    }
                }
            }
            System.out.println("---------------------");
        }
    }
}

优点:

  • api使用简单
  • 把整个xml文档加载到内存中,所以解析比较快;

缺点:

  • dom解析,如果解析的文档过大,会造成内存溢出

dom解析适合文档内容较少的xml解析


2.2 SAX解析

jdk内置的实现解析xml的方式,我们并不需要额外的第三方的包;

sax解析是基于事件驱动的;

package xmlParse.SAX;

import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.File;
import java.io.IOException;

public class SaxParse {

    public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
        //1.创建sax解析器工厂
        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
        //2.创建sax解析器
        SAXParser saxParser = saxParserFactory.newSAXParser();
        //文件
        File file = new File("./BookStore.xml");
        saxParser.parse(file,new SaxHandler());
    }
}
package xmlParse.SAX;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class SaxHandler extends DefaultHandler {
    @Override
    public void startDocument() throws SAXException {
        System.out.println("文档开始解析......");
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        System.out.println("元素开始解析......");
        System.out.println("标签名: " + qName);
        if (qName.equals("book")) {
            System.out.println(attributes.getQName(0) + ": " + attributes.getValue("id"));
        }
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        System.out.println(new String(ch, start, length));
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        System.out.println("元素结束解析");
    }

    @Override
    public void endDocument() throws SAXException {
        System.out.println("文档结束解析");
    }
}

优点:

  • 占用内存极少(不会把我们整个文档都加载到内存中,Sax解析是基于事件驱动的,读一行解析一行)
  • 适合解析文档内容特别大的xml文档

缺点:

  • api设计比较复杂
  • 解析速度比较慢

所以,sax解析适合大文档解析,并不适用于小文档解析;

2.3 DOM解析与SAX解析的对比

  • dom: 速度快,api设计简单, 不适合大文档解析
  • sax: 速度较慢,api设计比较复杂,适用于大文档解析

3.第三方优秀的xml解析库

3.1 Dom4j解析

  • dom4j解析并不是jdk内置的解析方式
  • dom4j是第三方基于dom解析,来帮我们实现了很多重复操作,简化我们的使用
  • 使用dom4j首先要导入dom4j的jar包
//创建dom4j的解析器
SAXReader saxReader = new SAXReader();
//解析文件,返回document对象(dom4j包)
Document document = saxReader.read("./bookstore.xml");
//获取根节点
Element rootElement = document.getRootElement();
//elements跨级是拿不到节点的,只能拿到子节点,再下一层的节点拿不到
List<Element> bookElements = rootElement.elements("book");
//不用再判断z空文本
for (Element bookElement : bookElements) {
    System.out.println(bookElement.attributeValue("id"));
    System.out.println(bookElement.element("name").getText());;
    System.out.println(bookElement.element("author").getText());;
    System.out.println(bookElement.element("price").getText());;
    System.out.println("--------------");
}

总结: do4j在实际的生产环境中效率比dom还要高,而且使用非常方便,我们很多的开源项目都使用它;也建议大家使用dom4j解析xml


3.2 Xpath解析

  • 基于Dom4j的路径解析方式

如果出现这个错误,是因为没有引入jaxen下面的包;
在这里插入图片描述


路径表示:

/ :  代表的是文档的的开始

//:  代表的从任意位置开始查找

建议尽量使用 /;或者两个搭配使用

使用 //,这样会进行全文搜索,这样做效率很低;

<?xml version="1.0" encoding="UTF-8" ?>
<member>
    <star id="001">
        <name>麦当</name>
        <age>15</age>
        <sex></sex>
    </star>
    <star id="002">
        <name>迪亚</name>
        <age>13</age>
        <sex></sex>
    </star>
    <star id="003">
        <name>咕咚</name>
        <age>14</age>
        <sex></sex>
    </star>
    <star id="004">
        <name>米龙</name>
        <age>16</age>
        <sex></sex>
    </star>
</member>
package xmlParse.xpath;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.util.List;

public class xpathParse {
    public static void main(String[] args) throws DocumentException {
        //创建Dom4j的解析器
        SAXReader saxReader = new SAXReader();
        //解析文件
        Document document = saxReader.read("./RainBowSea.xml");
        //获取全部的star节点,通过路径表示,就可以拿到member下的子节点
        List<Element> list = document.selectNodes("/member/star");
        for (Element node : list) {
            System.out.println(node.attribute("id").getName() + ": " + node.attributeValue("id"));
            Element name = node.element("name");
            System.out.println(name.getName() + ": " + name.getText());
            Element age = node.element("age");
            System.out.println(age.getName() + ": " + age.getText());
            Element sex = node.element("sex");
            System.out.println(sex.getName() + ": " + sex.getText());
            System.out.println("===========================");
        }
    }
}

在这里插入图片描述

属性表示:

包含某个属性:
	 List<Element> list = document.selectNodes("/bookstore/book[@id]/name");
根据属性值匹配:
	 List<Element> list = document.selectNodes("/bookstore/book[@id='01']/name");

获取指定的属性(不常用):

//获取id属性 
List list = document.selectNodes("/bookstore/book/@id");

        for (Object id : list) {
            DefaultAttribute idAttr = (DefaultAttribute) id;
            System.out.println(idAttr.getName() + "="+idAttr.getValue());
        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值