XML
XML:eXtendsible markup language(可扩展的标记语言)
XML有什么用?
1.保存数据
2.做配置文件
3.数据传输载体(C/S模式,服务器将数据以XML形式回传客户端)
XML基本文档结构,倒状树形结构,从“根部”开始,然后扩展到“枝叶”。
<?xml version="1.0" encoding="UTF-8"?>
<stus>
<stu>
<name>kk</name>
<age>18</age>
</stu>
</stus>
定义XML
其实就是一个文件,文件的后缀为xml
- 文档声明
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
version:解析这个xml的时候,使用什么版本的解析器解析。
encoding:解析xml中的文字的时候,使用什么编码来翻译。
standalone(一般不使用):no -- 该文档会依赖关联其他文档,yes -- 这是一个独立的文档。
encoding
在解析的这个xml的时候,使用什么编码去解析。---- 解码
存储文字是存储这些文字对应的二进制。可以根据文件使用的编码方式来得到这些文字对应的二进制。
默认文件保存的时候,使用的是本地编码 -- GBK编码保存
所以想要让xml能够正常的显示中午,有两种方法:
- 让 encoding 也是 GBK 或者是 gb2312.
- 如果 encoding 是UTF-8,那么保存文件的时候也必须将编码方式使用为UT-8。
- 保存文件的时候见到的ANSI,对应的其实是本地编码 GBK。
为了确保通用性,最好使用UTF-8编码保存,以及encoding都是 UTF-8。
元素定义(标签)
其实就是标签,<>括起来的都叫元素。成对出现。如下:
<stu></stu>
1.文档声明下来的一个元素叫根元素(根标签)
2.标签里面可以嵌套标签
<stu>
<name>kk</name>
<age/>
</stu>
3.空标签,即是开始也是结束,一般配合属性来用
<age/>
4.标签名字可以自定义。
XML命名规则:
名称可以含有字母、数字以及其他的字符
不能以数字或者标点符号开始
不能以字符“xml”(或者XML,Xml)开始
不能包含空格
命名尽量简单,见名知意
简单元素&复杂元素
- 简单元素
元素里面包含了普通的文字
- 复杂元素
元素里面还可以嵌套其他的元素
属性的定义
定义在元素里面,<元素名称 属性名称=“属性的值”></元素名称>
<stus>
<!--id属性-->
<stu id="10025">
<name>安</name>
<age>18</age>
</stu>
</stus>
CDATA区
- 非法字符
在 XML 元素中,"<" 和 "&" 是非法的。
"<" 会产生错误,因为解析器会把该字符解释为新元素的开始。
"&" 也会产生错误,因为解析器会把该字符解释为字符实体的开始。
严格的讲,在XML中仅有字符“<”和 "&" 是非法的。省略号、引号和大于号是合法的,但是把它们替换为实体引用是个好习惯。
<(<)
> (> )
& (&)
...(&apps;)(省略号)
"(")(引号)
术语 CDATA 指的是不应由 XML 解析器进行解析的文本数据(Unparsed Character Data)。
如果某段字符串里面有过多的字符,并且里面包含了类似标签或者关键字的这种文字,不想让xml的解析器去解析,那么可以使用CDATA来包装,包装之后CDATA部分中的内容将会被解析器所忽略。
CDATA 部分由 "<![CDATA[" 开始,由 "]]>" 结束:
<an><![CDATA[<a href="http://wwww.baidu.com">解析器忽略测试</a>]]></an>
某些文本,比如 JavaScript 代码,包含大量 "<" 或 "&" 字符。为了避免错误,可以将脚本代码定义为 CDATA,忽略CDATA部分中的所有内容。
<script>
<![CDATA[
function matchwo(a,b)
{
if (a < b && a < 0) then
{
return 1;
}
else
{
return 0;
}
}
]]>
</script>
PS:
CDATA 部分不能包含字符串 "]]>"。也不允许嵌套的 CDATA 部分。
标记 CDATA 部分结尾的 "]]>" 不能包含空格或折行。
通常在服务器给客户端返回数据的时候使用。
XML解析
其实就是获取元素里面的字符数据或者属性数据。
XML解析方式
- DOM(Document object model)
把整个xml全部读到内存当中,形成树状结构。整个文档称之为document对象,属性对应Attribute对象,所有的元素节点对应Element对象,文本也可以称之为Text对象,以上所有的对象都可以称之为Node节点。
ps:如果xml特别大,那么将会造成内存溢出。如果xml小,则读取速度快,而且可以对文档进行增删的操作
- SAX(Simple API for Xml)基于事件驱动
读取一行,解析一行,一行行读取。
ps:不会造成内存溢出,不可以进行增删,只能查询。
针对这两种解析方式的API
- jaxp sun公司,比较繁琐
- jdom
- dom4j 使用比较广泛
Dom4j基本用法
需要要导入Dom4j的jar包,dom4j-2.1.1。
1.创建SaxReader对象
2.指定解析的xml地址
3.获取根元素
4.根据根元素获取子元素或者下面的子孙元素(根据子元素获得)
element.element("stu"):返回该元素下的第一个stu元素。
element.elements():返回该元素下的所有子元素。
Java:Main方法
public static void main(String[] args) throws DocumentException {
//1.创建sax读取对象
SAXReader reader = new SAXReader();
//2.指定解析的xml
Document document = reader.read(new File("src/xml/demo2.xml"));
//3.得到元素
//获取根元素
Element rootElement = document.getRootElement();
//获取根元素下的子元素
rootElement.element("stu");
rootElement.element("stu").element("age").getText();
//获取根元素下面的所有子元素,stu元素
List<Element> elements = rootElement.elements();
//遍历所有的stu元素
for (Element element : elements){
//获取stu元素下面的name,age元素
String name = element.element("name").getText();
String age = element.element("age").getText();
System.out.println("name = " + name + "---" + "age = " + age);
}
}
Xml:内容
<?xml version="1.0" encoding="UTF-8"?>
<stus>
<!--id属性-->
<stu id="10025">
<name>安</name>
<age>18</age>
</stu>
<stu id="10025">
<name>安1</name>
<age>16</age>
</stu>
</stus>
Dom4j 的Xpath的使用
dom4j里面支持 Xpath 的写法,xpath其实是xml的路径语言,支持我们在解析xml的时候,能够快速的定位到具体的某一个元素。
1.添加jar包,jaxen-1.1.2.jar
2.在查找指定节点的时候,根据XPath语法规则来查找
3.后续的代码与以前的解析代码一样。(区别在于获取元素节点的方法不一样)
public static void main(String[] args) throws Exception {
//1.创建sax读取对象
SAXReader reader = new SAXReader();
//2.指定解析的xml
Document document = reader.read(new File("src/xml/demo2.xml"));
//3.得到元素
//获取根元素
Element rootElement = document.getRootElement();
//使用Xpath,添加支持的jar,jaxen-1.1.2.jar。
//查找需要符合XPath语法规则
//selectSingleNode获取的是第一个元素,只返回一个。
Element nameElement = (Element) rootElement.selectSingleNode("//name");
System.out.println(nameElement.getText());
//获取文档里面的所有name元素
List<Node> list = rootElement.selectNodes("//name");
for (Node node:list){
System.out.println(node.getText());
}
}
XML约束
如下面的文档,属性定义的ID值时一样的,在我们日常中是不可能出现的。还有在一个项目中,可能大家的xml定义的标签繁多并且不统一,对于阅读和维护来说十分的讹困难,因为xml是扩展标记语言,格式由使用者来定义。所以我们有时候就需要一套规则来对xml文档进行一定的约束。
<?xml version="1.0" encoding="UTF-8"?>
<stus>
<!--id属性-->
<stu id="10025">
<name>安</name>
<name>安1</name>
<name>安2</name>
<age>18</age>
</stu>
<stu id="10025">
<name>安1</name>
<age>16</age>
</stu>
</stus>
DTD方式:
语法自成一派,早期就出现的,可读性比较差
1.引入网络上的DTD
<!--1.引入网络上的dtd来约束这个xml--> <!--文档类型 根标签名字 网络上的dtd dtd的名称 dtd的路径--> <!--<!DOCTYPE stus PUBLIC "//UNKNOWN/" "unknown.dtd">-->
2.引入本地的DTD
<!--2.引入本地的DTD:根标签名字 引入本地的DTD dtd的位置--> <!--<!DOCTYPE stus SYSTEM "demo2.dtd">-->
demo2.dtd
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT stus (stu+)> :stus下面有一个元素,一个或者多个
<!ELEMENT stu (name,age)>:stu下面有两个元素name,age 顺序必须是name-age
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)> <!--(#PCDATA) 被解析的普通字符数据 -->
<!--声明属性 <!ATTLIST 元素名称 属性名称 属性类型 默认值>-->
<!--属性类型选项:CDATA(值为字符数据),ID(值为唯一的ID)-->
<!ATTLIST stu id CDATA #IMPLIED> stu 有一个属性 文本类型,该属性可有可无
元素的个数:
+ :一个或者多个
* :零个或者多个
? :零个或者一个
属性的类型定义:
CDATA:属性是普通文字
ID:属性的值必须唯一
<!ELEMENT stu (name,age)>:stu下面有两个元素name,age ,按照顺序来
<!ELEMENT stu (name | age)>:两个中只能包含一个子元素
PS:关于dtd约束里面的语法要正确书写,如果标签不完整,可能导致解析器解析失效,导致约束文件无法生效,如 :
<!ATTLIST stu id ID > 中漏写默认值的属性
会导致dtd约束文件失效。
3.直接在XML里面嵌入DTD的规则
<!--xml文档里面直接嵌入DTD的约束法则--> <!DOCTYPE stus[ <!ELEMENT stus (stu+)> <!ELEMENT stu (name,age)> <!ELEMENT name (#PCDATA)> <!ELEMENT age (#PCDATA)> ]> <stus> <!--id属性--> <stu> <name>安</name> <age>18</age> </stu> <stu> <name>安1</name> <age>16</age> </stu> </stus>
Schema方式:
其实就是一个xml,使用xml的语法规则,xml解析器解析起来比较方便,是为了替代DTD。
但是Schema 约束文本内容比DTD的内容还要多,所以目前也没有真正意义上的替代DTD
约束文档 teacher.xsd:
<?xml version="1.0" encoding="UTF-8"?>
<!--xmlns : xml namespace : 名称空间、命名空间-->
<!--targetNamespace : 目标名称空间,下面定义的那些元素都与这个名称空间绑定上。-->
<!--elementFormDefault : 元素的格式化情况。-->
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/teacher"
elementFormDefault="qualified">
<!--复杂元素相互嵌套-->
<element name="teachers">
<complexType>
<sequence maxOccurs="unbounded">
<!--这是一个复杂元素-->
<element name="teacher">
<complexType>
<sequence>
<!--以下是两个简单元素-->
<element name="name" type="string"></element>
<element name="age" type="int"></element>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</element>
</schema>
实例文档 teacher.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!--xmlns:xsi :这里必须是这样的写法,也就是这个值已经固定了-->
<!--xmlns : 这里是名称空间,也固定了,写的是scheama里面的顶部目标名称空间,不过可以根据自己的写法改动-->
<!--xsi:schemaLocation :有两段:前半段是名称空间,也是目标空间的值,后面是约束文档的路径-->
<teachers
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.example.org/teacher"
xsi:schemaLocation="http://www.example.org/teacher teacher.xsd" >
<teacher>
<name>kk</name>
<age>18</age>
</teacher>
</teachers>
名称空间的作用:
一个xml如果想指定它的约束规则,假设使用的是DTD,那么这个xml只能指定一个DTD,不能指定多个DTD。
但是如果一个xml的约束是定义在schema里面,并且是多个schema,那么是可以的。
简单的说:一个xml 可以引用多个schema的约束,但是只能引用一个DTD的约束。
名称空间的作用就是在写元素的时候,可以指定该元素使用的是哪一套约束规则。默认情况如下。如果只有一套规则,那么都可以这么写
xmlns:aa="http://www.example.org/teacher"xmlns:bb="http://www.example.org/teacher"<name>kk</name>
<aa:name></aa:name>
<bb:name></bb:name>