文章目录
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());
}