XML介绍
XML即可扩展标记语言(Extensible Markup Language)
W3C在1998年2月发布1.0版本,2004年2月又发布1.1版本,但因为1.1版本不能向下兼容1.0版本,所以1.1没有人用
同时,在2004年2月W3C又发布了1.0版本的第三版。我们要学习的还是1.0版本
W3C是万维网联盟,HTML和XML都是来自他手
特点-----------------------
可扩展的,标签都是自定义的,语法十分严格
XML的作用-------------------------
<?xml version="1.0" encoding="UTF-8" ?>
<users>
<user id="123" number="">
<Name>张百万
<name></name>
<name/>
<name>
</name>
</Name>
<age>15</age>
</user>
<user id="456">
<name>小斌</name>
<age>18</age>
<hobby>
<pingpang>
</pingpang>
</hobby>
</user>
<close/>
</users>
<?xml version="1.0" encoding="UTF-8" ?>
<employees>
<employee eid="2">
<ename>林黛玉</ename>
<age>20</age>
<sex>女</sex>
<salary>5000</salary>
<empdate>2010-01-01</empdate>
</employee>
<employee eid="3">
<ename>杜甫</ename>
<age>40</age>
<sex>男</sex>
<salary>15000</salary>
<empdate>2010-01-01</empdate>
</employee>
</employees>
由于XML的标签是可以随便写的,没有规范
所以在XML技术里,可以编写一个文档来约束一个XML文档的书写规范,这称之为XML约束
基本各种框架,都可以解析XML,且解析不同的XML
且基本每个框架都有一套XML约束,使得你写的XML按照他的规则书写
而我们通常需要看出这个规则,来使得我们写XML时,框架解析XML,可以对该框架起作用
常见的xml约束:
DTD
Schema
DTD(Document Type Definition),文档类型定义,用来约束XML文档
规定XML文档中元素的名称,子元素的名称及顺序,元素的属性等
开发中,我们不会自己编写DTD约束文档
通常情况我们都是通过框架提供的DTD约束文档,编写对应的XML文档
常见框架使用DTD约束有:Struts2、hibernate等
<!ELEMENT students (student+) >
<!ELEMENT student (name,age,sex)>
<!ELEMENT name (#PCDATA)>
<!-- name后面必须指定一个类型或者另外一个元素,即元素里必须有值
如这里指定普通的文本内容,否则报错-->
<!ELEMENT age (#PCDATA)>
<!ELEMENT sex (#PCDATA)>
<!ATTLIST student number ID #REQUIRED><!--ID可以不写,一种规范,用来确定唯一值,可以小写-->
<!--
ELEMENT 定义元素,所有的dtd的关键字都必须大写,否则报错,如ATTLIST,REQUIRED,而#是对元素的限制
students (student+): 当xml中引入dtd时,要设置一个元素为根元素,如果设置students,那么他就为根元素
且只能写他里面的内容,如student,以此内推
若指定student为根标签,那么也只能写他里面的内容,如name
注意:内容里有下一个的,若是标签,则必须写,直到没有标签,否则报错,若是内容,则可以不写
student+ : 根标签中 至少有一个 student子元素
student (name,age,sex) : student标签中可以 包含的子元素 按顺序出现
#PCDATA : 普通的文本内容
ATTLIST : 用来定义属性
student number ID : student标签中 有一个ID属性 叫做 number
#REQUIRED : number的属性必须填写
ID 唯一的值 不能重复 值只能是字母或者下划线开头
-->
引入dtd文档到xml文档中,两种方式
内部dtd:将约束规则定义在xml文档中,写在xml里
外部dtd:将约束的规则定义在外部的dtd文件中
外部:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE students SYSTEM "student.dtd">
<students>
<student number="S1">
<name>长海</name>
<age>20</age>
<sex>男</sex>
</student>
<student number="S2">
<name>大玲子</name>
<age>18</age>
<sex>女</sex>
</student>
</students>
当xml的age标签内容为2000时,明显不合理的,于是就有了更加强大的xml约束Schema,他也可以写xml文件
Schema是新的XML文档约束, 比DTD强大很多,是DTD 替代者
Schema本身也是XML文档,但Schema文档的扩展名为xsd,而不是xml
Schema 功能更强大,内置多种简单和复杂的数据类型,如限制数字大小,对age(年龄)的限制
Schema 支持命名空间 (一个XML中可以引入多个约束文档)
注意对于特定的标签,xml基本都可以写,如Scheam的格式xml也可以写,但需要指定格式使得xml的标签名可以有":"
但基本上这样的格式我们用Schema即xsd来记录
当然dtd的格式,xml是不可以操作的,因为格式完全不同
即xml不可以写dtd,但可以写xsd(需要指定格式),即可以理解为xsd是xml的一种
而对于这两种约束,都可以写xml的,因为xml只是一个内容,基本与后缀无关,而内容是使用的,那么里面的格式也就不能随便写了
但是必须符合xml的格式或者兼容xml格式的才可以写,如java不可以写,不符合或者兼容
<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns="http://www.lagou.com/xml"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.lagou.com/xml" elementFormDefault="qualified">
<xsd:element name="students" type="studentsType"/>
<xsd:complexType name="studentsType">
<xsd:sequence>
<xsd:element name="student" type="studentType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="studentType">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="age" type="ageType" />
<xsd:element name="sex" type="sexType" />
</xsd:sequence>
<xsd:attribute name="number" type="numberType" use="required"/>
</xsd:complexType>
<xsd:simpleType name="sexType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="male"/>
<xsd:enumeration value="female"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="ageType">
<xsd:restriction base="xsd:integer">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="200"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="numberType">
<xsd:restriction base="xsd:string">
<xsd:pattern value="hehe_\d{4}"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
<?xml version="1.0" encoding="UTF-8" ?>
<students
xmlns="http://www.lagou.com/xml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.lagou.com/xml student.xsd"
>
<student number="hehe_1234">
<name>张三</name>
<age>200</age>
<sex>male</sex>
</student>
<student number="hehe_4567">
<name>张三</name>
<age>200</age>
<sex>male</sex>
</student>
</students>
当将数据存储在XML后,我们就希望通过程序获得XML的内容
如果我们使用Java基础所学习的IO知识是可以完成的,不过你需要非常繁琐的操作才可以完成
且开发中会遇到不同问题(只读、读写)
人们为不同问题提供不同的解析方式,并提交对应的解析器,方便开发人员操作XML
解析器:就是根据不同的解析方式提供的具体实现
有的解析器操作过于繁琐,为了方便开发人员,有提供易于操作的解析开发包
JAXP:sun公司提供的解析器,支持DOM和SAX两种思想
DOM4J:一款非常优秀的解析器 , Dom4j是一个易用的、开源的库,用于XML,XPath和XSLT
它应用于Java平台,采用了Java集合框架并完全支持DOM,SAX和JAXP,第三方开发出来的解析方式,需要相应jar包
Jsoup:jsoup 是一款Java 的HTML解析器 ,也可以解析XML
PULL:Android内置的XML解析方式,类似SAX
dom4j 的使用-------------
上面是需要的包
使用核心类SaxReader加载xml文档获得Document,通过Document 对象获得文档的根元素,然后就可以操作了
常用API如下:
SaxReader对象-----------------------------
read(…) 加载执行xml文档
Document对象-----------------------------
getRootElement() 获得根元素
Element对象-----------------------------
elements(…) 获得指定名称的所有子元素,可以不指定名称
element(…) 获得指定名称的第一个子元素,可以不指定名称(一般需要指定)
getName() 获得当前元素的元素名
attributeValue(…) 获得指定属性名的属性值
elementText(…) 获得指定名称子元素的文本值
getText() 获得当前元素的文本内容
若标签下只有标签,其实是有文本的,只不过为空而已
<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns="http://www.lagou.com/xml"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.lagou.com/xml" elementFormDefault="qualified">
<xsd:element name="users" type="usersType"/>
<xsd:complexType name="usersType">
<xsd:sequence>
<xsd:element name="user" type="userType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="userType">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="age" type="ageType" />
<xsd:element name="hobby" type="hobbyType" />
</xsd:sequence>
<xsd:attribute name="id" type="numberType" use="required"/>
</xsd:complexType>
<xsd:simpleType name="ageType">
<xsd:restriction base="xsd:integer">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="100"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="hobbyType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="抽烟"/>
<xsd:enumeration value="喝酒"/>
<xsd:enumeration value="烫头"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="numberType">
<xsd:restriction base="xsd:string">
<xsd:pattern value="\d{3}"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
<?xml version="1.0" encoding="UTF-8" ?>
<users
xmlns="http://www.lagou.com/xml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.lagou.com/xml user.xsd"
>
<user id="001">
<name>张百万</name>
<age>25</age>
<hobby>抽烟</hobby>
</user>
<user id="002">
<name>于谦</name>
<age>55</age>
<hobby>烫头</hobby>
</user>
<user id="003">
<name>小斌</name>
<age>25</age>
<hobby>喝酒</hobby>
</user>
</users>
package com.lagou.xml03;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;
import java.util.List;
public class TestDOM4j {
@Test
public void test1() throws DocumentException {
SAXReader reader = new SAXReader();
Document document =
reader.read("H:\\jdbc_work\\xml_task03\\src\\com\\lagou\\xml03\\user.xml");
Element rootElement = document.getRootElement();
System.out.println(rootElement.getName());
List<Element> elements = rootElement.elements();
for (Element element : elements) {
System.out.println("根标签下的子节点: " + element.getName());
List<Element> eList = element.elements();
for (Element e : eList) {
System.out.println("user标签下的子节点" + e.getName());
}
break;
}
}
@Test
public void test2() throws DocumentException {
SAXReader reader = new SAXReader();
Document document =
reader.read("H:\\jdbc_work\\xml_task03\\src\\com\\lagou\\xml03\\user.xml");
Element rootElement = document.getRootElement();
List<Element> elements = rootElement.elements();
Element user = elements.get(0);
String id = user.attributeValue("id");
String name = user.elementText("name");
String age = user.elementText("age");
String hobby = user.element("hobby").getText();
System.out.println(id + " " + name +" " + age + " " + hobby);
}
}
XPath 是一门在 XML 文档中查找信息的语言
可以使用xpath查找xml中的内容
由于DOM4J在解析XML时只能一层一层解析,所以当XML文件层数过多时使用会很不方便,结合XPATH就可以直接获取到某个元素
上面是需要的包
上述的"//"是无视语法中的路径的
不再是Element对象了,而是节点对象
常用方法:
selectSingleNode(query): 查找和 XPath 查询匹配的一个节点,参数是Xpath 查询串
selectNodes(query):得到的是xml根节点下的所有满足 xpath 的节点,参数是Xpath 查询串
Node:节点对象
<?xml version="1.0" encoding="UTF-8" ?>
<bookstore>
<book id="book1">
<name>金瓶梅</name>
<author>金圣叹</author>
<price>99</price>
</book>
<book id="book2">
<name>红楼梦</name>
<author>曹雪芹</author>
<price>69</price>
</book>
<book id="book3">
<name>Java编程思想</name>
<author>埃克尔</author>
<price>59</price>
</book>
</bookstore>
package com.lagou.xml04;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.junit.Test;
import java.util.List;
public class TestXPath {
@Test
public void test1() throws DocumentException {
SAXReader reader = new SAXReader();
Document document =
reader.read("H:\\jdbc_work\\xml_task03\\src\\com\\lagou\\xml04\\book.xml");
Node node1 = document.selectSingleNode("/bookstore/book/name");
System.out.println("节点的名称: " + node1.getName());
System.out.println("书名: " + node1.getText());
Node node2 = document.selectSingleNode("/bookstore/book[3]/name");
System.out.println("书名: " + node2.getText());
}
@Test
public void test2() throws DocumentException {
SAXReader reader = new SAXReader();
Document document =
reader.read("H:\\jdbc_work\\xml_task03\\src\\com\\lagou\\xml04\\book.xml");
Node node1 = document.selectSingleNode("/bookstore/book/attribute::id");
System.out.println("第一个book的id属性值: " + node1.getText() );
Node node2 = document.selectSingleNode("/bookstore/book[last()]/attribute::id");
System.out.println("最后一个book节点中的属性值: " + node2.getText());
Node node3 = document.selectSingleNode("/bookstore/book[@id='book2']");
String name = node3.selectSingleNode("name").getText();
System.out.println("id为book2的 节点的书名是: " + name);
}
@Test
public void test3() throws DocumentException {
SAXReader reader = new SAXReader();
Document document =
reader.read("H:\\jdbc_work\\xml_task03\\src\\com\\lagou\\xml04\\book.xml");
List<Node> list = document.selectNodes("//*");
for (Node node : list) {
System.out.println("节点名: " + node.getName());
}
List<Node> list1 = document.selectNodes("//name");
for (Node node : list1) {
System.out.println("书名: " + node.getText());
}
List<Node> list2 = document.selectNodes("/bookstore/book[@id='book1']//*");
for (Node node : list2) {
System.out.println(node.getName() + " = " + node.getText());
}
}
}
list = document.selectNodes("//*");
for (Node node : list) {
System.out.println("节点名: " + node.getName());
}
List<Node> list1 = document.selectNodes("//name");
for (Node node : list1) {
System.out.println("书名: " + node.getText());
}
List<Node> list2 = document.selectNodes("/bookstore/book[@id='book1']//*");
for (Node node : list2) {
System.out.println(node.getName() + " = " + node.getText());
}
}
}