xml的概念和基础使用
什么是xml
xml是可扩展标记语言,简单理解,就是可预定义标签的编程语言。虽然和html类似,但主要是用于数据存储和传输数据;HTML用于显示数据。
XMl的结构:
<root> <!-- 根结点-->
<child> <!-- 子结点-->
<subchild> <!-- 根节点的孙子结点,子节点的子节点-->
.....
</subchild>
</child>
<child> <!-- 上一个child的兄弟结点-->
<subchild>
.....
</subchild>
</child>
</root>
XML的结构一定含有根节点/根元素,这个节点为所有节点的父节点
语法详解
- XML以<?xml version="1.0" encoding="ISO-8859-1"?>开头,这句话用于定义XML的版本和所采用的字符集。
- 标签以成对的方式出现,如:
- XML的大小写敏感
- 因为<>被用于当做语法标签的符号,所以文本的内容的< 号就失效了,所以我们使用 ;< 来表示小于号,使用;>表示大于号 ;&quto表示双引号
- 使用 < !-- 注释内容 – >
示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE books [
<!ELEMENT books (book*)>
<!ELEMENT book (name,author,price)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT price (#PCDATA)>
<!ATTLIST book id CDATA #REQUIRED>
]>
<books>
<book id="1001">
<name>java开发实战</name>
<author>张小三</author>
<price>98.5</price>
</book>
<book id="1002">
<name>mysql从删库到跑路</name>
<author>王一一</author>
<price>89.7</price>
</book>
</books>
找到这个xml文件,显示这样的形式就是没有问题的

案例解析
我们使用DTD验证去避免XML文件给出报错提示,去验证XML的有效性
<!DOCTYPE books [
<!ELEMENT books (book*)>
<!ELEMENT book (name,author,price)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT price (#PCDATA)>
<!ATTLIST book id CDATA #REQUIRED>
]>
PCDATA(Parsed Character DATA)的意思是:被解析的字符数据
CDATA(Unparsed Character Data)意思是:不应由 XML 解析器进行解析的文本数据
DTD的局限性
- 不遵守XML语法
- DTD数据类型有限
- DTD不可以扩展
- DTD不支持命名空间
DTD的代替技术 – Schema
Schema全称为XML Schema,用于描述XML文档结构,比DTD更加强大,最关键的特征就是,Schema支持数据类型
Schema特点
- 是用于支持XML验证
- 可以使用处理XML文档的工具进行操作
- 扩充了数据类型,可以自定义数据类型
- 支持元素的继承
- 支持属性组
格式
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
</xs:schema>
注意要点
- 所有的Schema文档使用schema作为根元素
- http://www.w3.org/2001/XMLSchema:用于验证当前 Schema 文档的命名空间(用于验证 Schema 本身)
同时它还规定了来 自命名空间http://www.w3.org/2001/XMLSchema的元素和数 据类型应该使用前缀 xs: - xmlns 相当于 java 中的 import, :xs“小名”,在使用时要写加 “小名”做前缀
使用Schema去验证XML文档的流程:
- 创建Schemafactory工厂
- 建立验证文件对象
- 利用SchemaFactory工厂对象,接收验证的文件对象,生成Schema对象
- 产生对此schema的验证器
- 要验证的数据
- 开始验证
示例代码
创建一个xsd文件,存放Schema
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="books">
<xs:complexType>
<xs:sequence>
<xs:element name="book" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string"></xs:element>
<xs:element name="author" type="xs:string"></xs:element>
<xs:element name="price" type="xs:double"></xs:element>
</xs:sequence>
<xs:attribute name="id" type="xs:positiveInteger" use="required"></xs:attribute>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
在XML文件内引用xsd文件
<?xml version="1.0" encoding="UTF-8"?>
<books xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="{book.xsd}">
<book id="1001">
<name>java开发实战</name>
<author>张三</author>
<price>98.5</price>
</book>
<book id="1002">
<name>mysql开发</name>
<author>李四</author>
<price>89.7</price>
</book>
</books>
对验证器进行验证
package com.bjsxt.schema;
import java.io.File;
import java.io.IOException;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.xml.sax.SAXException;
public class Test {
public static void main(String[] args) throws SAXException {
//创建SchemaFactory工厂
SchemaFactory sch = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
//建立验证文件对象
File schemaFile = new File("book.xsd");
//利用SchemaFactory工厂对象,接收验证的文件对象,生成Schema对象
Schema schema = sch.newSchema(schemaFile);
//产生对此schema的验证器
Validator validator = schema.newValidator();
//要验证的数据(准备数据源)
Source source = new StreamSource("book.xml");
//开始验证
try {
validator.validate(source);
System.out.println("成功");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("验证失败");
}
}
}
项目格式:

运行成功,也就是说,我们使用Schema对XML文件进行验证是可以的

使用DOM解析XML数据
DOM解析就是将其转换为一个对象模型的集合,用树这种数据结构对信息进行存储。
创建流程
- 创建一个DocumentBuilderFactory的对象
- 创建一个DocumentBuilder对象
- 通过DocumentBuilder的parse(…)方法得到Document对象
- 通过getElementsByTagName(…)方法获取到节点的列表
- 通过for循环遍历每一个节点
- 得到每个节点的属性和属性值
- 得到每个节点的节点名和节点值
创建项目:

XML文件
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book id="1001">
<name>java开发实战</name>
<author>张三</author>
<price>98.5</price>
</book>
<book id="1002">
<name>my开发</name>
<author>李四</author>
<price>89.7</price>
</book>
</books>
创建DOM文件对XML文件进行验证:
package com.bjsxt.schema;
import java.io.IOException;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;
public class TestDOMParse {
public static void main(String[]args) throws ParserConfigurationException, SAXException, IOException{
// 1. 创建一个DocumentBuilderFactory的对象
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// 2. 创建一个DocumentBuilder对象
DocumentBuilder db = dbf.newDocumentBuilder();
// 3. 通过DocumentBuilder的parse(...)方法得到Document对象
Document doc = db.parse("book.xml");
// 4. 通过getElementsByTagName(...)方法获取到节点的列表
NodeList bookList = doc.getElementsByTagName("book");
System.out.println("节点个数:"+bookList.getLength());
// 5. 通过for循环遍历每一个节点
for(int i=0;i<bookList.getLength();i++) {
// 6. 得到每个节点的属性和属性值
Node book = bookList.item(i);
NamedNodeMap attrs = book.getAttributes(); //得到了属性的集合
//使用循环遍历每一个属性
for(int j=0;j<attrs.getLength();j++) {
//得到每一个属性
Node id = attrs.item(j);
System.out.println("属性的名称:"+id.getNodeName()+"\t"+id.getNodeValue());
}
}
System.out.println("\n每个节点的名和节点的值");
// 7. 得到每个节点的节点名和节点值
for(int i=0;i<bookList.getLength();i++) {
//得到每个book节点
Node book = bookList.item(i);
NodeList subNode = book.getChildNodes();
System.out.println("子节点的个数:"+subNode.getLength());
for(int j=0;j<subNode.getLength();j++) {
Node childNode = subNode.item(i);
//System.out.println(childNode.getNodeName());
short type = childNode.getNodeType(); //获取节点的类型
if(type==Node.ELEMENT_NODE) {
System.out.println("节点的名称:"+childNode.getNodeName()+"\t"+childNode.getTextContent());
}
}
}
}
}
验证结果:

使用SAX方式解析XML数据
SAX,是一种以事件驱动的XML API,SAX和DOMM不同的是它边扫描边解析,自顶向下以此解析,由于边扫描边解析,所以它解析XML速度快,占用内存少
创建流程
- 创建SAXParserFactory的对象
- 创建SAXParser对象(解析器)
- 创建一个DefaultHandler的子类
- 调用parse方法
示例:
项目结构:

book.xml
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book id="1001">
<name>java开发实战</name>
<author>张三</author>
<price>98.5</price>
</book>
<book id="1002">
<name>my开发</name>
<author>李四</author>
<price>89.7</price>
</book>
</books>
TestSAXparse.java
package com.bjsxt.schema;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
public class TestSAXparse {
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
//1.创建SAXParserFactory的对象
SAXParserFactory spf = SAXParserFactory.newInstance();
// 2. 创建SAXParser对象(解析器)
SAXParser parser = spf.newSAXParser();
// 3. 创建一个DefaultHandler的子类
BookDeaultHandler bdh = new BookDeaultHandler();
// 4. 调用parse方法
parser.parse("book.xml",bdh);
}
}
BookDeaultHandler .java
package com.bjsxt.schema;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class BookDeaultHandler extends DefaultHandler{
//重写第一个方法
/**
* 解析XML文档,开始时调用
*/
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
super.startDocument();
System.out.println("解析XML文档开始");
}
/**
* 解析XML文档,点击结束时调用
*/
@Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
super.endDocument();
System.out.println("解析XML文档结束");
}
/**
* 解析XML文档中的节点开始时要用
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
super.startElement(uri, localName, qName, attributes);
//判断book节点,我们就获取节点的属性和属性值
if("book".equals(qName)) {
//获取所有的属性
int count = attributes.getLength();//属性的个数
//循环获取每个属性
for(int i=0;i<count;i++) {
String attName = attributes.getQName(i); //属性名称
String attValue = attributes.getValue(i); //属性值
System.out.print("属性名称:"+attName+"\t属性值:"+attValue+"\t");
}
}else if(!"book".equals(qName)&&!"book".equals(qName)) {
System.out.print("节点的名称:"+qName+"\t");
}
}
/**
* 解析XML文档内的节点结束时要用
*/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// TODO Auto-generated method stub
super.endElement(uri, localName, qName);
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// TODO Auto-generated method stub
super.characters(ch, start, length);
String value = new String(ch,start,length);
if("".equals(value.trim())) {
System.out.print(value);
}
}
}
运行结果 :

使用JDOM解析XML
JDOM是一种解析XML的java工具包,它基于树型结构,利用纯java的技术对XML文档实现解析。所以是适用于java语言
创建流程
- 导入jdom.jar这个jar包
- 创建一个SAXBuilder对象
- 创建build方法,得到Document对象(通过IO流)
- 获取根节点
- 获取根节点的直接子节点的集合
- 遍历集合
示例:
项目结构:

导入jar包:这里导入的是 jdom.jar包
book.xml 内容同上
TestJDOM.java
package com.bjsxt.schema;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
public class TestJDOM {
public static void main(String[] args) throws FileNotFoundException, JDOMException, IOException {
// 1. 创建一个SAXBuilder对象
SAXBuilder sb = new SAXBuilder();
// 2. 创建build方法,得到Document对象(通过IO流)
Document doc = sb.build(new FileInputStream("book.xml"));
// 3. 获取根节点
Element root = doc.getRootElement(); //books元素
// 4. 获取根节点的直接子节点的集合
List<Element> bookEle = root.getChildren();
// 5. 遍历集合 得到book的每一个子节点(子元素)
for(int i=0;i<bookEle.size();i++) {
Element book = bookEle.get(i);
//得到属性集合
List<Attribute> attList = book.getAttributes();
//遍历属性的集合得到每一个属性
for(Attribute attr:attList) {
System.out.println(attr.getName()+"\t"+attr.getValue());
}
}
//得到每一个子节点
System.out.println("\n-------------");
for(int i=0;i<bookEle.size();i++) {
Element book = bookEle.get(i); //得到每一个book节点
List<Element> subBook = book.getChildren();
//遍历每一个节点,获取节点名称节点值
for(Element ele:subBook) {
System.out.println(ele.getName()+"\t"+ele.getValue());
}
System.out.println("=================");
}
}
}
运行结果:

使用DOM4J去解析XML(目前使用最多的一种)
DOM4J是一个java的XML API,是JDOM的升级品,是用来读写XML文件的
DOM4J解析XML的步骤
- 创建SAXReader对象
- 调用read方法
- 获取根元素
- 通过迭代器遍历直接节点
示例
项目目录:

导入jar包:这里导入的是dom4j-1.6.1.jar包
创建Book.java实体类
package com.bjsxt.entity;
public class Book {
//私有属性
private String name;
private String author;
private double price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public Book(String name, String author, double price) {
super();
this.name = name;
this.author = author;
this.price = price;
}
public Book() {
super();
}
}
创建TestDOM4J.java
package com.bjsxt.schema;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.bjsxt.entity.Book;
public class TestDOM4J {
public static void main(String[] args) throws DocumentException {
// 1. 创建SAXReader对象
SAXReader reader=new SAXReader();
// 2. 调用read方法
Document doc=reader.read(new File("book.xml"));
// 3. 获取根元素
Element root=doc.getRootElement();//books
// 4. 通过迭代器遍历直接节点
for(Iterator<Element> iteBook=root.elementIterator();iteBook.hasNext();){
Element bookEle=iteBook.next();
//得到book的属性
for(Iterator<Attribute> iteAtt=bookEle.attributeIterator();iteAtt.hasNext();){
Attribute att=iteAtt.next();
System.out.println(att.getName()+"\t"+att.getText());
}
}
System.out.println("\n----------------------");
List<Book> bookList=new ArrayList<Book>();
for(Iterator<Element> iteBook =root.elementIterator();iteBook.hasNext();){
//创建book对象
Book book = new Book();
//得到每一个子元素
Element bookEle = iteBook.next(); //得到每一个book
//使用for循环继续遍历
for(Iterator<Element> subBookEle=bookEle.elementIterator();subBookEle.hasNext();){
//得到每一个元素
Element subEle = subBookEle.next();
System.out.println(subEle.getName()+"\t"+subEle.getText());
/**
* 封装为book对象
*/
//获取节点的名称
String nodeName=subEle.getName();//name,author,price
//使用switch判断
switch (nodeName) {
case "name":
book.setName(subEle.getText());
break;
case "author":
book.setAuthor(subEle.getText());
break;
case "price":
book.setPrice(Double.parseDouble(subEle.getText()));
break;
}
}
//添加到集合中
bookList.add(book);
}
//遍历集合
System.out.println("\n遍历集合-----------------------\n");
for (Book b : bookList) {
System.out.println(b.getName()+"\t"+b.getAuthor()+"\t"+b.getPrice());
}
}
}
去解析book.xml文件
运行结果:

使用XPATH技术去快速获取节点
引入原因
使用dom4j去查询较深的节点时,比较麻烦
作用
快速获取所需的节点对象
如何在dom4j内使用xPath技术
- 导入对应的jar包 : dom4j的jar包 Jaxen的jar包
- 创建一个SAXReader对象
- 读取读取XML文件
- 得到author节点
示例:

Test.java
package com.bjsxt.xpath;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
public class Test {
public static void main(String[] args) throws DocumentException {
//1. SAXReader对象
SAXReader reader = new SAXReader();
//2. 读取XML文件
Document doc = reader.read("book.xml");
//3. 得到第一个author节点
Node node = doc.selectSingleNode("//author");
System.out.println("节点的名称:"+node.getName()+"\t"+node.getText());
System.out.println("-------------------");
//获取所有的author
List<Node> list = doc.selectNodes("//author");
for(Node n:list) {
System.out.println("节点的名称:"+n.getName()+"\t"+n.getText());
}
//选择有id属性的book元素
List<Attribute> attList = doc.selectNodes("//book/@id");
for(Attribute att:attList) {
System.out.println("属性的名称:"+att.getName()+"\t"+att.getText());
}
}
}
运行结果

最后一种,最为方便
本文详细介绍了在Java中如何正确使用XML文件,包括XML的结构、DTD和Schema的区别及使用,以及DOM、SAX、JDOM和DOM4J等解析XML的方法,并通过实例展示了XPath技术在获取XML节点中的应用。

2115

被折叠的 条评论
为什么被折叠?



