xml学习

XML:Extensible Markup Language 用标记来修饰文本信息 标签没有预定义,可以自定义
数据相关的技术,企业开发中常用来存储数据和传输数据(而非显示数据),或者作为框架的配置文件,且与任何编程语言无关。
应用:1.充当数据库,保存数据信息 2.AJAX,WebService,网络中传输数据,可以使用xml格式
使用xml描述复杂的关系模型数据

XML语法:
1.文档声明 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
encoding属性用于指定文档中的字符编码,如果没有指定该属性,默认采用ISO-8859-1(不支持中文数据)
如果encoding编码和文件本身的编码不一致,在IE无法解析该xml中的字符,会报错。

standalone属性表示该文档是否依赖外部文件

2.元素
每个元素标签都必须结束,元素标签不能交叉嵌套,有且仅有一个根标签(格式良好的xml文档规范)

xml文档中的空格和换行都会被xml解析器解析处理的

3.属性
写在元素上,属性值用双引号或者单引号包含起来

4.注释 <!-- ... --> 存在于正文,不能在文档声明和处理指令之前

5.<![CDATA[...]]> 不会被xml解析器处理
转义字符 < less than &lt; > greater than &gt; <a> &lt;a&gt; 
特殊字符必须进行转义,CDATA节和转义字符都能实现原样输出,优先选择CDATA

6.处理指令 processing instruction
控制xml文档如何被解析引擎所解析的。控制xml数据的显示样式
 <?xml-stylesheet type="text/css" href="css.css"?>
XSLT可以实现对xml的显示控制


xml应用
1.存储和数据传输 为了方便,不使用xml约束技术
	所有xml的生成和解析都是通过程序完成
2.配置文件,为了保证元素的准确性,使用约束技术

---------------------------------------------------------------------------
为什么使用xml约束?
使用xml约束,可以使元素内容更加规范。如果企业开发中没有使用约束,是因为使生成和解析xml的过程更加简单

DTD Document Type Definition
语法 <!ELEMENT element name>  每个元素对应一个element

xml文档
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE books SYSTEM "books.dtd">
<books>
	<book>	
		<name>java编程思想</name>
		<price>108</price>
	</book>
</books>

dtd约束文档
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT books (book)>
<!ELEMENT book (name,price)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT price (#PCDATA)>

DTD约束可以作为一个单独的文件编写,也可以在xml文档内部编写
DTD与xml文档关联的三种方式
1.内部DTD
<!DOCTYPE 根元素 [..]>

<!DOCTYPE books [
	<!ELEMENT books (book)>
	<!ELEMENT book (name, price)>
	<!ELEMENT name (#PCDATA)>
	<!ELEMENT price (#PCDATA)> 
]>

2.外部DTD(引用本地dtd) <!DOCTYPE 根元素 SYSTEM "本地文件地址">
3.公共DTD(引用网络上的dtd) <!DOCTYPE 根元素 PUBLIC "DTD名称" "DTD文件的URL">

公共DTD名称 W3C官方组织规定的

元素ELEMENT定义
<!ELEMENT 元素名 (子元素或者元素类型)>

()表示子元素或者分组
,表示元素的顺序
+ * ?表示元素出现的次数,类似正则表达式
|表示多个选一个

元素类型:
#PCDATA,EMPTY,ANY,其他类型

属性ATTLIST定义
<!ATTLIST 元素名
		  属性列表(多个)>
属性列表定义
属性名 类型 约束

常用的三个类型
CDATA 文本类型属性
ID 表示属性值唯一 
(1|2|3)多选一

约束
#REQUIRED 属性必须
#IMPLIED 属性可选
#FIXED 属性值固定
Default 默认值

实体ENTITY定义(对于重复的xml数据内容,可以抽取为实体)
<!ENTITY 实体名称 "实体值">
引用实体 &实体名称;

---------------------------------------------------------------------------
XML Schema(模式文档)
包含一套预定义的元素和属性(这套元素和属性规定了schema文档的结构和内容),
可以根据这些预定义的元素和属性来编写自己的schema文档,最终用这个schema文档来完成对xml实例的约束

Schema文档本身是XML文档 DTD使用单独的语法

编写了一个XML Schema约束文档后,通常需要把这个文档中定义的元素和属性绑定到一个唯一的URI地址(名称空间)上,
XML实例文档通过这个URI告诉解析引擎,文档中包含的元素来自哪里,被谁约束

为什么需要引入名称空间?
一个xml实例可以包含多个schema文档,当多个schema中定义了同名元素,为了区分哪个元素来自哪个schema文档,就有了名称空间的概念

编写一个schma文档的步骤
1. 引入预定义的schema元素和属性的名称空间 
xmlns="http://www.w3.org/2001/XMLSchema" 
2. 在schema文档中定义自己的元素和属性,最后将这些元素和属性绑定到一个名称空间上,以供xml实例文档引用
targetNamespace="http://www.example.org/books"
3. 在xml实例文档中引入自定义的schema文档
xmlns="http://www.example.org/books"
4. 声明xml实例文档使用了schema文档约束
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5. 指定引入的自定义schema文档的位置
xsi:schemaLocation="http://www.example.org/books books.xsd"> (格式:名称空间 schema文档位置)

books.xsd
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" 
		targetNamespace="http://www.example.org/books" 
		elementFormDefault="qualified">
	
	<!-- 每个元素对应一个element -->
	<element name="books">
		<!-- 包含子元素或者属性的元素 表示一个复杂元素 -->
		<complexType>
			<!-- sequence强调子元素的顺序 -->
			<sequence>
				<element name="book">
					<complexType>
						<sequence>
							<!-- 简单元素的类型直接通过type属性指定 -->
							<element name="name" type="string"/>
							<element name="price" type="double"/>
						</sequence>
					</complexType>
				</element>
			</sequence>
		</complexType>
	</element>
</schema>

books.xml
<?xml version="1.0" encoding="UTF-8"?>
<books xmlns="http://www.example.org/books"
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xsi:schemaLocation="http://www.example.org/books books.xsd">
	<book>
		<name>Core Java</name>
		<price>222</price>
	</book>
</books>

http://www.intertech.com/Blog/xml-schema-elementformdefault-and-attributeformdefault/

elementFormDefault="qualified"(默认值,建议使用)
表示xml实例中的全局元素(schema文档中schema节点的直接节点)和局部元素(非schema节点的直接节点)都必须使用前缀
elementFormDefault="unqualified"(需要给每个引入的名称空间加一个前缀,否则,如果将引入的名称空间作为xml实例文档的默认名称空间,
使用schema文档中定义的局部元素会报错 -- 元素前没有加任何名称空间,表示属于被默认名称空间限定,这与elementFormDefault="unqualified"不符)
表示xml实例中的全局元素使用前缀,局部元素不使用前缀
attributeFormDefault="qualified"(需要给每个引入的名称空间加一个前缀,否则,如果将引入的名称空间作为xml实例文档的默认名称空间,
使用schema文档中定义的属性会报错 -- 属性前没有加任何名称空间,表示属于被不包含任何前缀,这与attributeFormDefault="qualified"不符)
表示xml实例中所有属性必须使用前缀
attributeFormDefault="unqualified"(默认值,建议使用)
表示xml实例中所有属性都不使用前缀

------------------------------------------------------
XML解析:DOM和SAX

DOM:Document Object Model(文档对象模型)
思想:将整个XML文档加载到内存中(所有的元素、属性、文本、注释、CDATA、XML文档都会被解析成一个Node对象),形成一个文档对象(树形结构),
所有对XML的操作都基于这个内存中的文档对象
W3C组织推荐的标准 -- 所有开发语言都支持

SAX:Simple API for XML (XML简单API)
非推荐标准,来自XML社区
思想:不需要将整个XML文档加载到内存中,边解析,边处理,处理完成后释放相应的内存资源

STAX:The Stream API for XML(XML流式API)从JDK1.6新加入的
STAX是一种拉模式的XML处理方式,而SAX是一种推模式的XML处理方式

推模式(push):由服务器为主导,主动向客户端发送数据
拉模式(pull): 由客户端为主导,主导向服务器申请数据

XML解析方式:解析XML的思想
XML解析开发包:解析XML思想的具体实现

常用的XML解析开发包:
JAXP(Java API for XML Processing)SUN公司实现的XML解析包,支持DOM、SAX、STAX
DOM4j 来自开源社区的XML解析的开源框架,支持DOM
XML PULL Java开源框架中的一种XML解析实现(Android内置了pull解析器),支持STAX

当SAX或STAX解析XML文档时,如果读到内存的数据不被释放,那么内存中将包含整个XML文档的数据(类型DOM 支持修改和回写)

javaee开发中,优先选择DOM方式(编程简单)解析XML,如果XML文档非常大,优先考虑使用STAX方式解析XML
移动开发中优先使用STAX方式解析XML文档


javax.xml.parsers:dom、sax解析相关的解析器和工厂类
javax.xml.stream:stax解析相关的类
org.w3c.dom:dom解析相关的类(数据节点类)
org.xml.sax:sax解析相关的类

----------------------------------------------------------
DOM解析
1、产生dom解析器工厂 
2、通过dom解析器工厂生成dom解析器
3、通过dom解析器解析xml文档,返回代表整个xml文档的document对象
4、通过document对象完成对xml文档的各种操作

Node接口:当xml文档加载到内存后,所有的数据都是一个节点(元素节点Element,属性节点Attr,文本节点Text,注释节点,CDATA节点,文档节点Document...)
所有的这些节点都是node接口的子接口

Node接口的三个通用方法:
getNodeName():返回节点的名称
getNodeType():返回节点的类型
getNodeValue():返回节点的值  ---- 所有元素节点value都是 null

<name>xxx</name>
获得name元素内容xxx的两种方法
1、node.getFirstChild().getNodeValue() 先获取name元素的第一个子节点getFirstChild(),然后获取节点的内容getNodeValue()
2、node.getTextContent() 直接获取name元素的文本节点的内容

关于节点查找,常用的几个方法
node.getChildNodes() 获得当前节点下面所有子节点
node.getFirstChild() 获得当前节点的第一个子节点
node.getLastChild() 获得当前节点的最后一个子节点
node.getParentNode() 获得当前节点的父节点
node.getPreviousSibling() 获得当前节点的前一个兄弟节点
node.getNextSibling() 获得当前节点的下一个兄弟节点

book元素包含多少个子节点?(5个,三个文本节点,两个元素节点)
<book id="b0001">
	<name>java编程思想</name>
	<price>119</price>
</book>

document.getElementById() 只有在使用了约束的xml文档中,才起作用
一般情况都使用document.getElementsByTagName()
所有开发语言中都默认支持DTD,如果需要使用schema,需要单独编程导入schema

<!DOCTYPE books [
	<!ELEMENT books (book+)>
	<!ELEMENT book (name, price)>
	<!ELEMENT name (#PCDATA)>
	<!ELEMENT price (#PCDATA)>
	<!ATTLIST book
		id ID #REQUIRED>
]>
<books>
	<book id="b0001">
		<name>java编程思想</name>
		<price>119</price>
	</book>

	<book id="b0002">
		<name>java分布式计算</name>
		<price>85</price>
	</book>
</books>

document.getDocumentElement() 获得文档根节点
document.createElement 创建一个新的节点
node.appendChild() 在node节点的最后追加一个子节点
parentNode.removeChild(node) 删除node节点

删除节点:
NodeList nodeList = doc.getElementsByTagName("name");
for (int i = 0; i < nodeList.getLength(); i++) {
	System.out.println(nodeList.getLength());
	Element name = (Element) nodeList.item(i);
	if (name.getTextContent().contains("java")) {
		Node book = name.getParentNode();
		book.getParentNode().removeChild(book);
		i--; //删除节点后,总的节点数减1,i减1
	}
}

---------------------------------------------
SAX解析 (基于事件驱动)
原理:将待解析的xml文档和事件处理器传递给sax解析器,sax解析器逐行处理xml文档,扫描到文档开始、结束,元素开始、结束,文本内容等地方时会回调
事件处理器中的事件方法,直至解析完整个xml文档

五个常用的事件处理方法:
startDocument()  文档开始事件
startElemen() 元素开始事件
characters() 文本元素事件
endElement() 元素结束事件
endDocument() 文档结束事件

为什么说SAX是推模式解析? 解析器控制xml文档解析,由解析器调用相应事件方法

在startElemen() endElement() 获得开始和结束元素名称
在characters() 获得读取到文本内容
在startElemen() 读取属性值 

--------------------------------------------
PULL解析(使用STAX方式解析,拉模式)
原理:将xml文档传递给解析器,在客户端手动通过next()获取当前事件(类型),执行相应的事件处理

STAX解析方式比SAX高校?
1、SAX处理所有的事件类型,STAX由客户端控制要处理的事件类型
2、STAX可以随时终止解析过程

你可能感兴趣的:(xml)