XML文件解析

入门
XML文件:XML是可扩展标识语言,(Extensible Markup Language)就是开发者在符合XML命名规则的基础之上,可以根据自己的需求定义自己的标签。

XMl文件的作用:主要是用来存储数据。

解析XML文件的方法:DOM、DOM4J(DOM for Java)、SAX
前两种是把XML文件读取到内存中然后再解析。DOM解析用起来复杂且繁琐。所以一般选择后两种方法。
SAX是事件驱动型,边读边解析。SAX适用于解析大的XML文件。

Dom4j解析xml文件

导入Dom4j.jar包
Dom4j常用的对象:
SAXReader:读取xml文件到Document树结构文件对象。
Document:是一xml文档对象树,类比HTML文档对象。
Element:元素结点。通过Document对象可以查找单个元素。

Dom4j解析步骤:
第一步:创建解析器
SAXReader reader=new SAXReader();
第二步:Document对象:通过解析器read方法获取。
Document doc=reader.read(“studentInfo.xml”);
第三步:获取xml根节点
Element root=doc.getRootElement();
第四步:遍历解析子节点

实例一:解析student.xml文件
XML文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<students>
    <student>
        <name>吴飞</name>
        <college>java学院</college>
        <telephone>62354666</telephone>
        <notes>男,1982年生,硕士,现就读于北京邮电大学</notes>
    </student>
    <student>
        <name>李雪</name>
        <college>C++学院</college>
        <telephone>62358888</telephone>
        <notes>男,1987年生,硕士,现就读于中国农业大学</notes>
    </student>
    <student>
        <name>Jack</name>
        <college>PHP学院</college>
        <telephone>66666666</telephone>
        <notes>我是澳洲人</notes>
    </student>
    <student>
        <name>Lucy</name>
        <college>Android学院</college>
        <telephone>88888888</telephone>
        <notes>我是美国人</notes>
    </student>
</students>

DOM4j解析代码如下

package com.sh.xml;

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

import javax.swing.text.ElementIterator;
import java.util.Iterator;

public class Dom4jTest {
    public static void main(String[] args) {

        try {
            //创建解析器
            SAXReader reader=new SAXReader();
            //通过解析器的read方法将配置文件读取到内存中,生成一个Document[org.dom4j]对象树
            Document document=reader.read("conf/students.xml");
            //获取根节点
            Element root=document.getRootElement();
            //开始遍历根节点
//            for(int i=0;i<root.get) 无法通过for循环遍历
            for(Iterator<Element> rootIter = root.elementIterator();rootIter.hasNext();)
            {
                Element studentElt=rootIter.next();
                /*<student>
                        <name>吴飞</name>
                        <college>java学院</college>
                        <telephone>62354666</telephone>
                         <notes>男,1982年生,硕士,现就读于北京邮电大学</notes>
                </student>*/
                //当前获取到这些,继续遍历其中各个元素
                for(Iterator<Element> innerIter=studentElt.elementIterator();innerIter.hasNext();){
                    Element innerElt=innerIter.next();
                    //获取该结点元素的文本内容
                    String innerValue=innerElt.getStringValue();
                    System.out.println(innerValue);
                }
                System.out.println("-------------------------------");
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
}

解析结果:
在这里插入图片描述
SAX方式解析xml文件:事件驱动,边度边写
优点:无需将整个文档加载到内存中,所以内存消耗少,适合解析特大文件
SAX解析四步曲:
(1)创建解析器工厂:通过newInstance()方式获取
SAXParserFactory saxParserFactory=SAXParserFactory.newInstance();
因为他的构造方法受到了保护,所以要用newInstance()来创建该对象。

由于解析器必须由SAXParserFactory 类创建,所以必须创建SAXParserFactory
(2)创建解析器:
SAXParser saxParser=saxParserFactory.newSAXParser();
在这里插入图片描述

实例二:解析Persons.xml文件输出其中内容

package com.sh.xml;

import javafx.scene.effect.Blend;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

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

public class SAXTest {
    //使用jdk,无需第三方包
    public static void main(String[] args) {
        try {
            //创建解析器工厂
            SAXParserFactory saxParserFactory=SAXParserFactory.newInstance();
            //创建解析器
            SAXParser saxParser=saxParserFactory.newSAXParser();
            //通过解析器的parse方法
            //param: 文件,DefaultHandler
            saxParser.parse("conf/persons.xml",new MyDefaultHandler());
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
class MyDefaultHandler extends DefaultHandler{
    //重写其中 startElement\endElement\characters方法
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
//        解析xml文件开始标签并输出
        System.out.print("<"+qName+">");
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
//        解析xml文件结束标签并输出
        System.out.print("</"+qName+">");
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
//        解析中间内容
        System.out.print(new String(ch,start,length));//有参构造字符串
    }
}

xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<person>
	<p1>
		<name>zhangsan</name>
		<age>20</age>
	</p1>
	<p1>
		<name>wangwu</name>
		<age>29</age>
	</p1>
</person>

解析结果:
在这里插入图片描述
使用Dom4j的XPath解析xml文件

Xpath使用路径表达式来选取xml文档种的节点或节点集。结点是通过路径(path)或者步(steps)来选取
具体可以在官方语法地址学习。

xpath语法选取结点
bookstore.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<!-- 
	1.获取bookstore节点下book属性category值为web下的第二个title节点的文本内容
	 bookstore -> book[@category='web'][2] -> title 
	 xpath路径:/bookstore/book[@category='web'][2]/title/text()
	 
	 2.获取bookstore节点下book属性category值为web的titile属性为en的节点内容
	 bookstore -> book[@category='web'] -> title[@lang='en']
	 xpath路径:/bookstore/book[@category='web']/title[@lang='en']/text()
	 
	 3.获取bookstore下book属性category值为cooking的title的lang属性的值
	 bookstore -> book[@category='cooking'] -> title ->@lang
	 xpath路径:/bookstore/book[@category='cooking']/title/@lang
	 
	 4.获取bookstore节点下所有book的节点集合
	 /bookstore/book
 -->
<bookstore>
	<book category="children">
		<title lang="en">Harry Potter</title>
		<author>J K. Rowling</author>
		<year>2005</year>
		<price>29.99</price>
	</book>
	<book category="cooking">
		<title lang="en">Everyday Italian</title>
		<author>Giada De Laurentiis</author>
		<year>2005</year>
		<price>30.00</price>
	</book>
	<book category="web">
		<title lang="en">Learning XML</title>
		<author>Erik T. Ray</author>
		<year>2003</year>
		<price>39.95</price>
	</book>
	<book category="web">
		<title lang="uk">XQuery Kick Start</title>
		<author>James McGovern</author>
		<year>2003</year>
		<price>49.99</price>
	</book>
</bookstore>

选择结点:xpath使用路径表达式在XML文档中选取结点。节点是通过沿着路径或者step来选取的。下面列出最有用的路径表达式:
在这里插入图片描述
实例:在下面的表格中,我们已经列出了一些路径表达式以及表达式的结果:
在这里插入图片描述
text()获取文本内容函数
示例一:获取sys-config.xml文件的配置信息
准备工作:
(1)导入dom4j-1.6.1.jar和jaxen-1.1-beta-7.jar
(2)sys-config.xml文档

<?xml version="1.0" encoding="UTF-8"?>
<config>
	<database-info>
		<driver-name>com.mysql.jdbc.Driver</driver-name>
		<url>jdbc:mysql://192.168.1.151:3366/bjpowernode</url>
		<user>root</user>
		<password>123</password>
	</database-info>
</config>

第一步:通过SAXReader获取解析器
SAXReader reader=new SAXReader();
第二步:通过解析器的read方法获取Document对象
Document doc=reader.read(“sys-config.xml”);
第三步:通过xpath语法获取driver-name结点
Element driverNameElt = doc.selectObject(“/config/database-info/driver-name”);
String driverName= driverNameElt.getStringValue();

package com.sh.xml;

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

public class SysConfigParser {
    public static void main(String[] args) {
        try {
            //创建解析器
            SAXReader reader=new SAXReader();
            //通过解析器的read方法将配置文件读取到内存中,生成Document
            Document doc=reader.read("conf/sys-config.xml");
            //driver-name结点元素的路径:config->database-info/driver-name
            //driver-name结点元素的xpath路径:/config/database-info/driver-name
            Element driverNameElt=(Element) doc.selectSingleNode("/config/database-info/driver-name");
            //获取driverNameElt结点元素对象的文本内容
            String driverName=driverNameElt.getStringValue();
            System.out.println(driverName);

            //url结点元素路径:config->database-info->url
            //url结点元素xpath路径:/config/data-base-info/url
            //:config//url
            //://url
            Element urlElt=(Element)doc.selectSingleNode("//url");
            String url=urlElt.getStringValue();
            System.out.println(url);

            //user结点元素路径:config-database-info-user
            //config//user
            user
            //config/database-info/user
            Element userElt=(Element)doc.selectSingleNode("//user");
            String user=userElt.getText();//获取文本
            System.out.println(user);

            Element passwordElt=(Element)doc.selectSingleNode("//password");
            String password=passwordElt.getTextTrim();
            System.out.println(password);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
}

示例二:解析server.xml文件:获取端口号
准备server.xml

<?xml version="1.0" encoding="UTF-8"?>
<server>
	<service>
		<connector port="8080"></connector>
	</service>
</server>

第一步:创建 SAXReader 解析器
SAXReader reader = new SAXReader();
第二步:通过解析器 read 方法获取 Document 对象
Document document = reader.read(“server.xml”);
第三步:通过 xpath 语法获取 connector 节点
Element connectorElt = document.selectSingleNode(“/server/service/connector”);
第四步:获取 connector 节点的 port 属性对象
Attribute portAttr = connector.attribute(“port”);
String portStr = portAttr.getStringValue();

package com.sh.xml;

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

public class ServerParser {
    public static void main(String[] args) {
        try {
            SAXReader saxReader=new SAXReader();
            Document doc=saxReader.read("conf/server.xml");
            //获取connector结点元素对象的xpath路径:/server/service/connector
            Element connectorElt=(Element)doc.selectSingleNode("//connector");
            //获取connector结点元素对象的port属性
            Attribute portAttr=connectorElt.attribute("port");
            //获取portAttr属性对象的值(两种方法)
            String port=portAttr.getStringValue();
            String portValue=connectorElt.attributeValue("port");
            System.out.println(port);
//            System.out.println(portValue);
            
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
}

示例三:解析books.xml文件(org.w3c.dom.Document)
准备books.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<bookstore> 
	<book category="children"> 
		<title lang="en">Harry Potter</title>
		<author>J K. Rowling</author>
		<year>2005</year> <price>29.99</price>
	</book> <book category="cooking">
		<title lang="en">Everyday Italian</title>
	  	<author>Giada De Laurentiis</author>
	  	<year>2005</year> <price>30.00</price>
	</book> <book category="web">
	 	<title lang="en">Learning XML</title>
	  	<author>Erik T. Ray</author>
	   	<year>2003</year>
	    <price>39.95</price>
	</book> <book category="web">
		 <title lang="uk">XQuery Kick Start</title>
		 <author>James McGovern</author>
		 <year>2003</year>
		 <price>49.99</price>
	</book>
</bookstore>

第一步:通过 DocumentBuilderFactory 获取解析工厂
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
第二步:获取解析器
DocumentBuilder builder = builderFactory.newDocumentBuilder();
第三步:通过解析的 parser 方法获取 Document 对象
Document document = builder.parse(new File(“books.xml”));
第四步:获取 XPath 对象
XPath xPath = XPathFactory.newInstance().newXPath();

//获取 bookstore 节点下 book 属性 category 值为 web 下的第二个 title 节点的文本内容

xPath.evaluate("/bookstore/book[@category=‘web’[2]/title/text()",document,XPathConstants.STRING);
在这里插入图片描述
//获取 bookstore 节点下 book 属性 category 值为 web 的 titile 属性为 en 的节点内容

xPath.evaluate("/bookstore/book[@category=‘web’]/title[@lang=‘en’]/text()",document, XPathConstants.STRING)

获取bookstore下book属性category值为cooking的title的lang属性的值

xPath.evalute(“/bookstore/book[@category=’cooking’]/title/@lang”,document,
XPathConstants.STRING);

获取 bookstore 节点下所有 book 的节点集合

NodeList books = (NodeList)xPath.evaluate(“/bookstore/book”,document,
XPathConstants.NODESET);

//遍历 books 节点
for(int i = 0; i < books.getLength(); i++){}
//获取 book 节点
Node book = books.item(i)

获取 book 标签子节点 title 的文本内容
xPath.evaluate(“title/text()”,book, XPathConstants.STRING);

package com.sh.xml;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

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

public class MyXPathTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        try {
            //创建解析工厂
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            //创建解析器
            DocumentBuilder builder = documentBuilderFactory.newDocumentBuilder();
            //通过解析器读取配置文件,生成一个Document[org.w3c.dom]对象树
            Document document = builder.parse("conf/bookstore.xml");

            //创建XPath对象
            XPath xPath = XPathFactory.newInstance().newXPath();

//			1.获取bookstore节点下book属性category值为web下的第二个title节点的文本内容
//			 bookstore -> book[@category='web'][2] -> title 
//			 xpath路径:/bookstore/book[@category='web'][2]/title/text()
            String titleXpath = "/bookstore/book[@category='web'][2]/title/text()";
            String titleValue = (String) xPath.evaluate(titleXpath, document, XPathConstants.STRING);
            System.out.println(titleValue);

//			2.获取bookstore节点下book属性category值为web的titile属性为en的节点内容
//			bookstore -> book[@category='web'] -> title[@lang='en']
//			xpath路径:/bookstore/book[@category='web']/title[@lang='en']/text()
            String titleLangXpath = "/bookstore/book[@category='web']/title[@lang='en']/text()";
            String titleLangValue = (String) xPath.evaluate(titleLangXpath, document, XPathConstants.STRING);
            System.out.println(titleLangValue);

//			 3.获取bookstore下book属性category值为cooking的title的lang属性的值
//			 bookstore -> book[@category='cooking'] -> title ->@lang
//			 xpath路径:/bookstore/book[@category='cooking']/title/@lang
            String titleLangAttrXpath = "/bookstore/book[@category='cooking']/title/@lang";
            String titleLangAttrValue = (String) xPath.evaluate(titleLangAttrXpath, document, XPathConstants.STRING);
            System.out.println(titleLangAttrValue);

//			 4.获取bookstore节点下所有book的节点集合
//			 /bookstore/book
            NodeList bookList = (NodeList) xPath.evaluate("/bookstore/book", document, XPathConstants.NODESET);
            //开始遍历bookList
            for(int i = 0; i < bookList.getLength(); i++){
                Element bookElt = (Element) bookList.item(i);
                String titleValue01 = (String) xPath.evaluate("title", bookElt, XPathConstants.STRING);
                String authorValue = (String) xPath.evaluate("author", bookElt, XPathConstants.STRING);
                String year = (String) xPath.evaluate("year", bookElt, XPathConstants.STRING);
                String price = (String) xPath.evaluate("price", bookElt, XPathConstants.STRING);
                System.out.println(titleValue01 + " " + authorValue + " " + year + " " + price);
                System.out.println("---------------");
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}


版权声明:本文为weixin_45750207原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。