第一天XML语言
1、什么是XML?为什么学习XML?
可扩展标记语言,XML技术是w3c组织发布的,目前推荐遵循的是W3C组织于2000发布的XML1.0规范
在现实中大量存在有关系的数据
2、XML技术用于解决什么问题?
XML语言出现的根本目标在于描述上图那种,在现实生活中经常出现的有关系的数据
在XML语言中,它允许用户自定义标签,一个标签用于描述一段数据,一个标签可以分为开始标签和结束标签,在开始标签和结束标签之间,又可以使用其它标签描述其他数据,以此来实现数据关系的描述
3、XML常见应用
(1)XML技术除用了保存有关系的数据外,它还经常用做软件配置文件,以描述程序模块之间的关系
(2)在一个软件系统中,为提高系统的灵活性,它所启动的模块通常由其配置文件决定
例如一个软件在启动时,他需要启动A、B两个模块,而A、B这两个模块在启动时,又分别需要A1、A2和B1、B2模块的支持,为了准确描述这种关系,此时使用XML文件最为合适不过
(3)在Java开发中,传统的配置文件是*.properties属性文件(key=value),而XML表示的数据更为丰富。
(4)XML技术除用于描述有关系的数据外,还经常用作软件配置文件,以描述程序模块之间的关系。(如后面将要学习到的Struts2、Spring和Hibernate都是基于XML作为配置文件的)
(5)在一个软件系统中,通过XML配置文件可以提高系统的灵活性。即程序的行为是通过XML文件来配置的,而不是硬编码。
4、XML语法
一个XML文件分为如下几个部分内容:(文档声明、元素、属性、注释、CDATA区、特殊字符、处理指令)
5、XML语法——文档声明
在编写XML文档时,需要先使用文档声明,声明XML文档的类型
(1)最简单的声明语法:<?Xml version=“1.0”?>
(2)用encoding属性说明文档的字符编码:<?Xml version=“1.0” encoding=“gb2312”?>
(3)用standalone属性说明文档是否独立:<?Xml version=”1.0” encoding=”GB2312” standalone=”yes”?>
6、元素
XML元素指XML文件中出现的标签,一个标签分为开始标签和结束标签,一个标签有如下几种书写形式
例如:包含标签体:<a> hello</a>
不含标签体:<a></a>简写成:</a>
一个标签中也可以嵌套若干子标签。但所有标签必须合理的嵌套,绝对不允许交叉嵌套。
格式良好的XML文档必须有且仅有一个根标签,其他标签都是这个根标签的子孙标签
对于XML标签中出现的所有空格和换行,XML解析程序都会当作标签内容进行处理,例如下面两段内容的意义是不一样的
第一段:<百度>www.baidu.com</百度>
第二段:
<百度>
www.baidu.com
</百度>
由于在XML中,空格和换行都作为原始内容被处理,所以,在编写XML文件时,使用换行和缩进等方式来让原文件中的内容清晰可读的良好书写习惯可能要被迫改变
7、元素命名规范
一个XML元素可以包含字母、数字以及其他一些可见字符,但必须遵守下面的规范
(1)区分大小写,例如<P>和<p>是两个不同的标记
(2)不能以数字或“_”(下划线)开头
(3)不能以xml(或XML、Xml等)开头
(4)不能包含空格
(5)名称中间不能包含冒号(:)
8、属性
(1)一个标签可以有多个属性,每个属性都有它自己的名称和取值,
例如:<input name=”text”>
(2)属性值一定要用双引号(“”)或者单引号(‘’)引起来
(3)定义属性必须遵循与标签相同的命名规范
(4)多学一招:在XML技术中,标签属性所代表的信息也可以被改成子元素的形式来描述
例如:<input>
<name>text</name>
</input>
9、注释
Xml文件中的注释采用:<!--注释-->格式
注意:XML声明之前不能有注释,注释不能嵌套,不能出现在第一行
10、CDATA区(Character Data)
在编写XML时,有些内容可能不想让解析引擎解析执行,而是当原始内容处理。遇到此种情况,可以把这些内容放到CDATA区里。对于CDATA区域内的内容,XML解析程序不会处理,而是直接原封不动的输出
作用:把标签当作普通文本内容
语法:<![CDATA[内容]]>
11、转义字符
对于一些单个字符,若想显示其原始样式,也可以使用转义的形式予以处理
(1)&——& (ampersand缩写)
(2)<——< (less than缩写)
(3)>——> (grant than缩写)
(4)“——" (quotation缩写)
(5)‘——&apos (apostrophe缩写)
补充:在XML中加入CSS
<?xml-stylesheet type=”text/css”?>
12、处理指令(了解一下即可)
处理指令,简称PI(processing Instruction)处理指令用来指挥解析引擎如何解析XML文档内容
例如:在XML文档中可以使用xml-stylesheet指令,通知XML解析引擎,应用css文件显示xml文档内容
<?xml-stylesheet type=”text/css” href=”1.css”>
处理指令必须以“<?”作为开头,以“?>”作为结尾,XML声明语句就是最常见的一种处理指令
13、XML约束概述
什么是XML约束?
在XML技术里,可以编写一个文档来约束一个XML文档的书写规范,这称之为XML约束
常用的约束技术:
(1)XML DTD
(2)XML Schema(最常用)
(3)XDR
(4)SOX
两个概念:
(1) 格式良好的XML,遵循XML语法的XML
(2) 有效的XML ,遵循约束的XML
14、DTD约束快速入门
DTD(Document Type Definition),全称为文档类型定义
文件清单: book.xml
<?xml version=”1.0”?>
<!DOCTYPE 书架 SYSTEM “book dtd”> ——注意这个
<书架>
<书>
<书名>Java培训</书名>
<作者>张孝祥</作者>
<售价>30.00</售价>
</书>
<书>
<书名>JavaScript网页开发</书名>
<作者>张孝祥</作者>
<售价>28.00</售价>
</书>
</书架>
文件清单:book.dtd
<!ELEMENT 书架(书+)> //多本书
<!ELEMENT 书架 书(书名、作者、售价)> //书里可以包含书名、作者、售价
<!ELEMENT 书名(#PCDATA)> //可以解析的字符数据区
<!ELEMENT 作者(#PCDATA)>
<!ELEMENT 售价(#PCDATA)>
DTD文件应使用UTF-8或Unicode
15、编程校验XML文档正确性
IE5以上的浏览器内置了XML解析工具Microsoft.XMLDOM,开发人员可以编写JavaScript代码,利用这个解析工具装载xml文件,并对xml文件进行dtd校验
(1)创建xml文档解析器对象
Var xmldoc=new ActiveXObject(“Microsofy XMLDOM”);
(2)开启xml校验
xmldoc.validateOnParse=”true”;
(3)装载xml文档
xmldoc.load(“book.xml”);
(4)获取错误信息
xmldoc.parseError.reason;
xmldoc.parseError.line;
16、编写DTD约束的两种方式
DTD约束既可以作为一个单独的文件编写,也可以在XML文件内编写
17、在xml文件内编写DTD
<?xml version=”1.0” encoding=”UTF-8” standalone=yes””>
<!DOCTYPE 书架[
<!ELEMENT 书架(书+)>
<!ELEMENT 书架 书(书名、作者、售价)>
<!ELEMENT 书名(#PCDATA)>
<!ELEMENT 作者(#PCDATA)>
<!ELEMENT 售价(#PCDATA)>
]>
<书架>
<书>
<书名>Java培训</书名>
<作者>张孝祥</作者>
<售价>30.00</售价>
</书>
<书>
<书名>JavaScript网页开发</书名>
<作者>张孝祥</作者>
<售价>28.00</售价>
</书>
</书架>
18、引用DTD约束
XML文件使用DOCTYPE声明语句来指明它所遵循的DTD文件,DOCTYPE声明语句有两种形式:
(1)当引用文件在本地时,采用如下格式:
<!DOCTYPE 文档根节点 SYSTEM “DTD文件的URL”>
例如:<!DOCTYPE 书架 SYSTEM “book.dtd”>
(2)当引用文件是一个公共文件时,采用如下方式:
<!DOCTYPE 文档根节点 PUBLIC “DTD名称” “DTD文件的URL”>
例如:<!DOCTYPE web-app PUBLIC “-//Sun MicroSystems.Inc//DTD Web Application 2.3//EN” “http://java.sun.com/dtd/web-app_2_3.dtd”>
19、DTD约束语法的细节
元素定义、属性定义、实体定义
20、DTD语法——元素定义
在DTD文档中使用ELEMENT声明一个XML元素,语法格式如下:
<!ELEMENT 元素名称 元素类型>
元素类型可以是元素内容或类型。
如为元素内容,则需要使用括号()括起来,如:
<!ELEMENT 书架(书名,作者,售价)> ——顺序不能改变
<!ELEMENT 书名(#PCDATA)>
如为元素类型,则直接书写,DTD规范定义了如下几种类型:
EMPTY:用于定义空元素,例如<br/><hr/>
ANY:表示元素内容为任意类型
元素内容中可以使用如下方式,描述内容的组成关系
(1)用逗号分隔,表示内容出现的顺序必须与声明时一致。
<!ELEMENT MYFILE (TITLE ,AUTHOR,EMALL)>
(2)用|分隔,表示任其选一,即多个只能出现一个
<!ELEMENT MYFILE(TITLE|AYTHOR|EMAIL)>
(3)在元素内容中也可以使用+、*、?等符号表示元素出现的次数
+:一次或多次(书+)
?:0次或1次(书?)
*:0次或多次(书*)
(4)也可以使用圆括号()批量设置,例如
<!ELEMENT> MYFILE((TITLE*,AUTHOR?,EMAIL)*|COMMENT)
21、属性定义——attribute
Xml文档中的标签属性通过ATTLIST为其设置属性
语法格式:
<ATTLIST 元素名
属性名1 属性值类型 设置说明
属性名1 属性值类型 设置说明
.......
>
属性声明举例:
<!ATTLIST 商品
类别 CDATA #REQUIRED ——要求的
颜色 CDATA #IMPLTED ——暗示的,可以设置也可以不设置
>
对应XML文件:
<商品 类别=“服装” 颜色=“黄色”>...</商品>
<商品 类别=“服装”>...</商品>
22、属性定义
设置说明:
(1)#REQUIRED:必须设置该属性
(2)#IMPLIED:可以设置也可以不设置
(3)#FIXED:说明该属性的取值固定为一个值,在XML文件中不能为该属性设置其他的值,但需要为该属性提供这个值
(4)直接使用默认值:在XML中可以设置该值也可以不设置该属性值,若没使用则使用默认值
举例:
<!ATTLIST 页面作者
姓名 CDATA #IMPLIED
年龄 CDATA #IMPLIED
联系信息 CDATA #REQUIRED>
网站职务 CDATA #FIXED “页面作者”
个人爱好 CDATA “上网”
>
23、常用属性值类型
CDATA:表示属性值为普通文本字符串
ENUMERATED(枚举)
ID (身份证)
ENTITY(实体)
24、属性值类型——ENUMERATED
属性的类型可以使一组取值的列表,在XML文件中设置的属性值只能是这个列表中的某个值(枚举)
<?xml version=”1.0” encoding=”GB2312” standalone=”yes” >
<!DOCTYPE 购物篮[ ——根标签是购物篮
<!ELEMENT 肉 EMPTY> ——肉里面不能嵌套标签
<!ATTLIST 肉 品种(鸡肉|牛肉|猪肉|鱼肉)“鸡肉”>
]>
<购物篮>
<肉 品种=“鱼肉”/>
<肉 品种=“牛肉”/>
<肉/>
</购物篮>
25、属性值类型——ID
表示属性设置的值为一个唯一的值
ID属性的值只能由字母,下划线开始,不能出现空白字符
<?xml version=”1.0” encoding=”GB2312”?>
<!DOCTYPE 联系人列表[
<!ELEMENT 联系人列表 ANY>
<!ELEMENT 联系人(姓名,EMAIL)>
<!ELEMENT 姓名(#PCDATA)>
<!ELEMENT EMAIL(#PCDATA)>
<!ATTLIST 联系人 编号 ID #REQUIRED>
]>
<联系人列表>
<联系人 编号=“1”>
<姓名>张三</姓名>
<EMAIL>zhangsan@163.com</EMAIL>
</联系人>
<联系人 编号=“2”>
<姓名>李四</姓名>
</联系人>
<联系人列表>
26、实体定义
(1)实体用于为一切内容创建一个别名,以后在XML文档中就可以使用别名引用这段内容了
(2)在DTD定义中一条<!ENTITY...>语句用于定义一个实体
(3)实体可以分为两种类型:引用实体和参数实体
27、实体定义——引用实体
(1)引用实体主要在XML文档中被应用
(2)语法格式:<!ENTITY 实体名称 “实体内容”>:直接转变成实体内容
(3)引用方式:&实体名称
(4)举例:<!ENTITY copyright “I am a poogrammer”>
......
©right
28、实体定义——参数实体
参数实体被DTD文件自身使用
语法格式:<!ENTITY % 实体名称 实体内容>
引用方式:%实体名称;
举例1:<!ENTITY %TAG_NAME “姓名|EMAIL|电话|地址”>
<!ELEMENT 个人信息 (%TAG_NAME;|生日)>
<!ELEMENT 客户信息 (%TAG_NAME;|公司名)>
举例2:<!ENTITY % common.attributes “id ID #IMPLIED account CDATA #REQUIRED”>
...
<!ATTLIST purchaseOrder %common.attributes;>
<!ATTLIST item %common.attributes;>
29、XML解析技术概述
XML解析方式分为两种:dom和sax
Dom:(Document Object Model,即文档对象模型)是W3C组织推荐的解析XML的一种方式
SAX:(Simple API for XML)不是官方标准,但它是XML社区事实上的标准,几乎所有的XML解析器都支持它
XML解析开发包:Jaxp(sun)、Jdom、dom4j
DOM和SAX解析方法的区别:
(1)dom解析的优点是对文档crud比较方便,缺点是占用内存比较大
(2)Sax解析优点是占用内存小,解析速度快,缺点是只适合做文档的读取,不适合做文档的curd
30、调整jvm大小
参考资料:
Sun HotSpot 1.4.1使用分代收集器,它把堆分为三个主要的域:新域、旧域以及永久域。Jvm生成的所有新对象放在新域中。一旦对象经历了一定数量的垃圾收集循环后,便获得使用期并进入旧域。在永久域中jvm则存储class和method对象。就配置而言,永久域是一个独立域并且不认为是堆的一部分。
下面介绍如何控制这些域的大小。可使用-Xms和-Xmx 控制整个堆的原始大小或最大值。
下面的命令是把初始大小设置为128M:
java –Xms128m
–Xmx256m为控制新域的大小,可使用-XX:NewRatio设置新域在堆中所占的比例。
下面的命令把整个堆设置成128m,新域比率设置成3,即新域与旧域比例为1:3,新域为堆的1/4或32M:
java –Xms128m –Xmx128m
–XX:NewRatio =3可使用-XX:NewSize和-XX:MaxNewsize设置新域的初始值和最大值。
下面的命令把新域的初始值和最大值设置成64m:
java –Xms256m –Xmx256m –Xmn64m
永久域默认大小为4m。运行程序时,jvm会调整永久域的大小以满足需要。每次调整时,jvm会对堆进行一次完全的垃圾收集。
使用-XX:MaxPerSize标志来增加永久域搭大小。在WebLogic Server应用程序加载较多类时,经常需要增加永久域的最大值。当jvm加载类时,永久域中的对象急剧增加,从而使jvm不断调整永久域大小。为了避免调整,可使用-XX:PerSize标志设置初始值。
下面把永久域初始值设置成32m,最大值设置成64m。
java -Xms512m -Xmx512m -Xmn128m -XX:PermSize=32m -XX:MaxPermSize=64m
默认状态下,HotSpot在新域中使用复制收集器。该域一般分为三个部分。第一部分为Eden,用于生成新的对象。另两部分称为救助空间,当Eden 充满时,收集器停止应用程序,把所有可到达对象复制到当前的from救助空间,一旦当前的from救助空间充满,收集器则把可到达对象复制到当前的to救 助空间。From和to救助空间互换角色。维持活动的对象将在救助空间不断复制,直到它们获得使用期并转入旧域。使用-XX:SurvivorRatio 可控制新域子空间的大小。
同NewRation一样,SurvivorRation规定某救助域与Eden空间的比值。比如,以下命令把新域设置成64m,Eden占32m,每个救助域各占16m:
java -Xms256m -Xmx256m -Xmn64m -XX:SurvivorRation =2
如前所述,默认状态下HotSpot对新域使用复制收集器,对旧域使用标记-清除-压缩收集器。在新域中使用复制收集器有很多意义,因为应用程序生成的 大部分对象是短寿命的。理想状态下,所有过渡对象在移出Eden空间时将被收集。如果能够这样的话,并且移出Eden空间的对象是长寿命的,那么理论上可 以立即把它们移进旧域,避免在救助空间反复复制。但是,应用程序不能适合这种理想状态,因为它们有一小部分中长寿命的对象。最好是保持这些中长寿命的对象 并放在新域中,因为复制小部分的对象总比压缩旧域廉价。为控制新域中对象的复制,可用-XX:TargetSurvivorRatio控制救助空间的比例 (该值是设置救助空间的使用比例。如救助空间位1M,该值50表示可用500K)。该值是一个百分比,默认值是50。当较大的堆栈使用较低的sruvivorratio时,应增加该值到80至90,以更好利用救助空间。用-XX:maxtenuring threshold可控制上限。
为放置所有的复制全部发生以及希望对象从eden扩展到旧域,可以把MaxTenuring Threshold设置成0。设置完成后,实际上就不再使用救助空间了,因此应把SurvivorRatio设成最大值以最大化Eden空间,设置如下:
java … -XX:MaxTenuringThreshold=0 –XX:SurvivorRatio=50000 …
31、JAXP
(1)JAXP:(Java API for XML Processing)开发包是JavaSE的一部分,它由以下几个包及其子包组成:
(2)org.w3c.dom:提供DOM方式解析XML的标准接口
(3)org.xml.sax:提供SAX方式解析XML的标准接口
(4)javax.xml:提供了解析XML文档的类
(5)javax.xml.parsers包中,定义了几个工厂类。我们可以通过调用这些工厂类,得到对XML文档进行解析的DOM和SAX解析器对象:
DocumentBuilderFactory SAXParserFactory
32、使用JAXP进行DOM解析
(1)调用 DocumentBuilderFactory.newInstance() 方法得到创建 DOM 解析器的工厂。
(2)调用工厂对象的 newDocumentBuilder方法得到 DOM 解析器对象。
(3)调用 DOM 解析器对象的 parse() 方法解析 XML 文档,得到代表整个文档的 Document 对象,进而可以利用DOM特性对整个XML文档进行操作了。
33、DOM编程
DOM模型(document object model)
DOM解析器在解析XML文档时,会把文档中的所有元素,按照其出现的层次关系,解析成一个个Node对象(节点)。
在dom中,节点之间关系如下:
位于一个节点之上的节点是该节点的父节点(parent)
一个节点之下的节点是该节点的子节点(children)
同一层次,具有相同父节点的节点是兄弟节点(sibling)
一个节点的下一个层次的节点集合是节点后代(descendant)
父、祖父节点及所有位于节点上面的,都是节点的祖先(ancestor)
节点类型
34、Node对象
(1)Node对象提供了一系列常量来代表结点的类型,当开发人员获得某个Node类型后,就可以把Node节点转换成相应的节点对象(Node的子类对象),以便于调用其特有的方法。(查看API文档)
(2)Node对象提供了相应的方法去获得它的父结点或子结点。编程人员通过这些方法就可以读取整个XML文档的内容、或添加、修改、删除XML文档的内容了。
35、更新XML文档
javax.xml.transform包中的Transformer类用于把代表XML文件的Document对象转换为某种格式后进行输出,例如把xml文件应用样式表后转成一个html文档。利用这个对象,当然也可以把Document对象又重新写入到一个XML文件中。
Transformer类通过transform方法完成转换操作,该方法接收一个源和一个目的地。我们可以通过:
javax.xml.transform.dom.DOMSource类来关联要转换的document对象,
用javax.xml.transform.stream.StreamResult 对象来表示数据的目的地。
Transformer对象通过TransformerFactory获得。
36、DOM 解析练习.
1.读取节点的文本内容
2.读取属性值
3.添加节点
4.删除节点
5.更新节点
6.打印所有元素节点的名称.
package Exercise;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class dom1
{
// (1)、首先拿到 一个 documentbuilderfactory 对象.
//(2)、 通过 factory 对象拿到 一个 documentbuilder对象.
//(3)、通过 builder的 parse 方法获得一个 document 对象.
public static void main(String[]args) throws ParserConfigurationException, SAXException, IOException, TransformerException
{
//readAttribute();//读取属性
//readContext();//读取内容
//addElement();//添加节点
//deleteElement();//删除节点
//updateElement();//更新节点
treeWalk();
}
private static void readAttribute() throws ParserConfigurationException,
SAXException, IOException {
//1、读取属性值
// (1)、首先拿到 一个 documentbuilderfactory 对象.
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
//(2)、 通过 factory 对象拿到 一个 documentbuilder对象.
DocumentBuilder db=dbf.newDocumentBuilder();
//(3)、通过 builder的 parse 方法获得一个 document 对象.
Document doc = db.parse("src/book.xml");
//(4)、通过document对象获取各个节点
Node node = doc.getElementsByTagName("书").item(0);
Element e=(Element)node;
System.out.println(e.getNodeName()+"——"+e.getAttribute("出版社"));//获取属性名
}
private static void readContext() throws ParserConfigurationException,
SAXException, IOException {
//2、读取节点文本内容
// (1)、首先拿到 一个 documentbuilderfactory 对象.
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
//(2)、 通过 factory 对象拿到 一个 documentbuilder对象.
DocumentBuilder db = dbf.newDocumentBuilder();
//(3)、通过 builder的 parse 方法获得一个 document 对象.
Document doc=db.parse("src/book.xml");
//(4)获取Node节点
Node node = doc.getElementsByTagName("书").item(0);
String value=node.getTextContent();//获取节点内部的内容
//System.out.print(value);
}
private static void addElement() throws ParserConfigurationException,
SAXException, IOException, TransformerFactoryConfigurationError,
TransformerConfigurationException, TransformerException {
// 3.添加节点 : <售价>59.00</售价>
// (1)、首先拿到 一个 documentbuilderfactory 对象.
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
//(2)、 通过 factory 对象拿到 一个 documentbuilder对象.
DocumentBuilder db = dbf.newDocumentBuilder();
//(3)、通过 builder的 parse 方法获得一个 document 对象.
Document doc = db.parse("src/book.xml");
//(4)、通过document对象创建一个节点
Element newele = doc.createElement("售价");
//newele.setNodeValue("59222.00");
newele.setTextContent("69.00");
//(5)、把新添加的节点连接到内存中指定的父节点上
Node node = doc.getElementsByTagName("书").item(0);
node.appendChild(newele);
//(6)、将内存中的xml文档写入到实际文件中,这里需要用到transformer
//首先拿到一个transformer的工厂
TransformerFactory tf=TransformerFactory.newInstance();
//(7)、通过transformer工厂获取一个transformer对象
Transformer tt=tf.newTransformer();
//(8)、开始转换
tt.transform(new DOMSource(doc), new StreamResult("src/book.xml"));
}
private static void deleteElement() throws ParserConfigurationException, SAXException, IOException, TransformerException
{
//4、删除节点
// (1)、首先拿到 一个 documentbuilderfactory 对象.
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
//(2)、 通过 factory 对象拿到 一个 documentbuilder对象.
DocumentBuilder db = dbf.newDocumentBuilder();
//(3)、通过 builder的 parse 方法获得一个 document 对象.
Document doc = db.parse("src/book.xml");
//(4)、找到要删除的节点
Node node = doc.getElementsByTagName("售价").item(1);
System.out.println(node.getTextContent());
//(5)、把他从内存中删除掉
node.getParentNode().removeChild(node);
//(6)、将内存中的xml文档写入到实际文件中,这里需要用到transformer
//首先拿到一个transformer的工厂
TransformerFactory tff=TransformerFactory.newInstance();
//(7)、通过transformer工厂获取一个transformer对象
Transformer tf = tff.newTransformer();
//(8)、开始转换
tf.transform(new DOMSource(doc), new StreamResult("src/book.xml"));
}
public static void updateElement() throws SAXException, IOException, ParserConfigurationException, TransformerException
{
//5、更新节点
// (1)、首先拿到 一个 documentbuilderfactory 对象.
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
//(2)、 通过 factory 对象拿到 一个 documentbuilder对象.
DocumentBuilder db = dbf.newDocumentBuilder();
//(3)、通过 builder的 parse 方法获得一个 document 对象.
Document doc = db.parse("src/book.xml");
//(4)、通过document对象获取需要更新的节点
Node node = doc.getElementsByTagName("售价").item(1);
//(5)、修改该节点里面的内容
node.setTextContent("88.00");
//(6)、将内存中的xml文档写入到实际文件中,这里需要用到transformer
//首先拿到一个transformer的工厂
TransformerFactory tff=TransformerFactory.newInstance();
//(7)、通过transformer工厂获取一个transformer对象
Transformer tf=tff.newTransformer();
//(8)、开始转换
tf.transform(new DOMSource(doc), new StreamResult("src/book.xml") );
}
private static void treeWalk() throws ParserConfigurationException, SAXException, IOException
{
// (1)、首先拿到 一个 documentbuilderfactory 对象.
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//(2)、 通过 factory 对象拿到 一个 documentbuilder对象.
DocumentBuilder builder = factory.newDocumentBuilder();
//(3)、通过 builder的 parse 方法获得一个 document 对象.
Document document = builder.parse("src/book.xml");
listNode(document);
}
private static void listNode(Node node) {
// TODO Auto-generated method stub
//(4)、判断是否是元素节点,是的话打印出来
if(node.getNodeType() == Node.ELEMENT_NODE){
System.out.println(node.getNodeName());
}
//(5)、遍历该节点的子节点
NodeList nl = node.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node1 = nl.item(i);
//(6)、递归的思想继续调用这个函数打印
listNode(node1);
}
}
}
37、SAX解析
(1)在使用 DOM 解析 XML 文档时,需要读取整个 XML 文档,在内存中构架代表整个 DOM 树的Doucment对象,从而再对XML文档进行操作。此种情况下,如果 XML 文档特别大,就会消耗计算机的大量内存,并且容易导致内存溢出。
(2)SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才对文档进行操作。
(3)SAX采用事件处理的方式解析XML文件,利用 SAX 解析 XML 文档,涉及两个部分:解析器和事件处理器:
(4)解析器可以使用JAXP的API创建,创建出SAX解析器后,就可以指定解析器去解析某个XML文档。???
(5)解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在调用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。
(6)事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理。
38、SAX方式解析XML文档
(1)使用SAXParserFactory创建SAX解析工厂
SAXParserFactory spf = SAXParserFactory.newInstance();
(2)通过SAX解析工厂得到解析器对象
SAXParser sp = spf.newSAXParser();
(3)通过解析器对象得到一个XML的读取器
XMLReader xmlReader = sp.getXMLReader();
(4)设置读取器的事件处理器
xmlReader.setContentHandler(new BookParserHandler());
(5)解析xml文件
xmlReader.parse("book.xml");
package Exercise;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
public class Sax1 {
public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException
{
//运用SAX解析XML
//(1)使用SAXParserFactory创建SAX解析工厂
SAXParserFactory spf=SAXParserFactory.newInstance();
//(2)通过SAX解析工厂得到解析器对象
SAXParser sp = spf.newSAXParser();
//(3)通过解析器对象得到一个XML的读取器
XMLReader xr = sp.getXMLReader();
//(4)设置读取器的事件处理器
xr.setContentHandler(new MyHandle());
//(5) 解析 xml文档
xr.parse("src/book.xml");
}
}
class MyHandle extends DefaultHandler
{
boolean flag=true;
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
System.out.println("解析到文档的开始");
}
@Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
//System.out.println("解析到文档的结束");
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
// TODO Auto-generated method stub
for(int i=0;i<atts.getLength();i++)
{
String tagName=atts.getQName(i);
String value=atts.getValue(tagName);
System.out.println(tagName+"——"+value);
}
if(qName.equals("售价"))
{
flag=false;
System.out.print(qName);
}
//System.out.println("解析到文档的开始标签"+qName);
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
//System.out.println("解析到文档的结束标签"+qName);
}
public void characters(char[] ch, int start,int length)
throws SAXException
{
super.characters(ch, start, length);
//System.out.println(new String(ch,start,length));
if(flag==false)
{
System.out.println(new String(ch,start,length));
flag=true;
}
}
}
39、DOM4J解析XML文档
(1)Dom4j是一个简单、灵活的开放源代码的库。Dom4j是由早期开发JDOM的人分离出来而后独立开发的。与JDOM不同的是,dom4j使用接口和抽象基类,虽然Dom4j的API相对要复杂一些,但它提供了比JDOM更好的灵活性。
(2)Dom4j是一个非常优秀的Java XML API,具有性能优异、功能强大和极易使用的特点。现在很多软件采用的Dom4j,例如Hibernate,包括sun公司自己的JAXM也用了Dom4j。
使用Dom4j开发,需下载dom4j相应的jar文件。
40、Document对象
DOM4j中,获得Document对象的方式有三种:
1.读取XML文件,获得document对象
SAXReader reader = new SAXReader();
Document document = reader.read(new File("input.xml"));
2.解析XML形式的文本,得到document对象.
String text = "<members></members>";
Document document = DocumentHelper.parseText(text);
3.主动创建document对象.
Document document = DocumentHelper.createDocument();
//创建根节点
Element root = document.addElement("members");
41、节点对象
1.获取文档的根节点.
Element root = document.getRootElement();
2.取得某个节点的子节点.
Element element=node.element(“书名");
3.取得节点的文字
String text=node.getText();
4.取得某节点下所有名为“member”的子节点,并进行遍历.
List nodes = rootElm.elements("member");
for (Iterator it = nodes.iterator(); it.hasNext();) {
Element elm = (Element) it.next();
// do something
}
5.对某节点下的所有子节点进行遍历.
for(Iterator it=root.elementIterator();it.hasNext();){
Element element = (Element) it.next();
// do something
}
6.在某节点下添加子节点.
Element ageElm = newMemberElm.addElement("age");
7.设置节点文字.
element.setText("29");
8.删除某节点.
//childElm是待删除的节点,parentElm是其父节点
parentElm.remove(childElm);
9.添加一个CDATA节点.
Element contentElm = infoElm.addElement("content");
contentElm.addCDATA(diary.getContent());
42、节点对象属性
1.取得某节点下的某属性
Element root=document.getRootElement();
//属性名name
Attribute attribute=root.attribute("size");
2.取得属性的文字
String text=attribute.getText();
3.删除某属性
Attribute attribute=root.attribute("size");
root.remove(attribute);
3.遍历某节点的所有属性
Element root=document.getRootElement();
for(Iterator it=root.attributeIterator();it.hasNext();){
Attribute attribute = (Attribute) it.next();
String text=attribute.getText();
System.out.println(text);
}
4.设置某节点的属性和文字.
newMemberElm.addAttribute("name", "sitinspring");
5.设置属性的文字
Attribute attribute=root.attribute("name");
attribute.setText("sitinspring");
43、将文档写入XML文件
1.文档中全为英文,不设置编码,直接写入的形式.
XMLWriter writer = new XMLWriter(new FileWriter("output.xml"));
writer.write(document);
writer.close();
2.文档中含有中文,设置编码格式写入的形式.
OutputFormat format = OutputFormat.createPrettyPrint();
// 指定XML编码
format.setEncoding("GBK");
XMLWriter writer = new XMLWriter(new FileOutputStream("output.xml"),format);
writer.write(document);
writer.close();
44、字符串与XML的转换
1.将字符串转化为XML
2. String text = "<members> <member>sitinspring</member></members>";
Document document = DocumentHelper.parseText(text);
2.将文档或节点的XML转化为字符串.
SAXReader reader = new SAXReader();
Document document = reader.read(new File("input.xml"));
Element root=document.getRootElement();
String docXmlText=document.asXML();
String rootXmlText=root.asXML();
Element memberElm=root.element("member");
String memberXmlText=memberElm.asXML();
45、pull 解析器
(1)pull 解析器是一个第三方的开源api,其解析原理与sax 解析原理很相像,都是采用事件驱动的方式.
(2)不同点: pull 解析器在每次读取到一段数据之后,需要程序员手动的调用其next() 方法,将当前解析到的这一行的"指针"移到下一行.
(3)在目前的android 平台中解析xml 文件都是采用pull解析器,是谷歌力推的xml解析器。pull 解析器是一个开源的java项目,既可以用于android,也可以用于JavaEE。
(4)在android源码根目录的libcore目录下存放的是pull 解析器相关的所有类库.
package cn.itheima.pull;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import cn.itheima.domain.Book;
public class Demo2 {
public static void main(String[] args) throws Exception {
List<Book> books = getBooks();
for (Book book : books) {
System.out.println(book);
}
}
private static List<Book> getBooks() throws XmlPullParserException,
Exception {
List<Book> list = new ArrayList<Book>();
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser parser = factory.newPullParser();
parser.setInput(new FileInputStream("src/book.xml"), "UTF-8");
int eventType = parser.getEventType();
Book book = null;
while(eventType!=XmlPullParser.END_DOCUMENT){
switch (eventType) {
case XmlPullParser.START_TAG:
String name = parser.getName();
if("书".equals(name)){
String publisher = parser.getAttributeValue(0);
book = new Book();
book.setPublisher(publisher);
}
if("书名".equals(name)){
String bookName = parser.nextText();
book.setBookName(bookName);
}
if("作者".equals(name)){
String author = parser.nextText();
book.setAuthor(author);
}
if("售价".equals(name)){
String price = parser.nextText();
book.setPrice(price);
}
break;
case XmlPullParser.END_TAG:
if("书".equals(parser.getName())){
list.add(book);
book = null;
}
break;
default:
break;
}
eventType = parser.next();
}
return list;
}
}
46、XML Schema
(1)XML Schema 也是一种用于定义和描述 XML 文档结构与内容的模式语言,其出现是为了克服 DTD 的局限性
(2)XML Schema VS DTD
XML Schema符合XML语法结构。
DOM、SAX等XML API很容易解析出XML Schema文档中的内容。
XML Schema对名称空间支持得非常好。
XML Schema比XML DTD支持更多的数据类型,并支持用户自定义新的数据类型。
XML Schema定义约束的能力非常强大,可以对XML实例文档作出细致的语义限制。
XML Schema不能像DTD一样定义实体,比DTD更复杂,但Xml Schema现在已是w3c组织的标准,它正逐步取代DTD。
(3)XML Schema 文件自身就是一个XML文件,但它的扩展名通常为.xsd。
(4)一个XML Schema文档通常称之为模式文档(约束文档),遵循这个文档书写的xml文件称之为实例文档。
(5)和XML文件一样,一个XML Schema文档也必须有一个根结点,但这个根结点的名称为Schema。
(6)编写了一个XML Schema约束文档后,通常需要把这个文件中声明的元素绑定到一个URI地址上,在XML Schema技术中有一个专业术语来描述这个过程,即把XML Schema文档声明的元素绑定到一个名称空间上,以后XML文件就可以通过这个URI(即名称空间)来告诉解析引擎,xml文档中编写的元素来自哪里,被谁约束。
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.itcast.cn"
elementFormDefault="qualified">
<xs:element name='书架' >
<xs:complexType>
<xs:sequence maxOccurs='unbounded' >
<xs:element name='书' >
<xs:complexType>
<xs:sequence>
<xs:element name='书名' type='xs:string' />
<xs:element name='作者' type='xs:string' />
<xs:element name='售价' type='xs:string' />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
=====================================================================
<?xml version="1.0" encoding="UTF-8"?>
<itcast:书架 xmlns:itcast="http://www.itcast.cn"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=“http://www.itcast.cn book.xsd">
<itcast:书>
<itcast:书名>JavaScript网页开发</itcast:书名>
<itcast:作者>张孝祥</itcast:作者>
<itcast:售价>28.00元</itcast:售价>
</itcast:书>
</itcast:书架>
47、名称空间的概念
(1)在XML Schema中,每个约束模式文档都可以被赋以一个唯一的名称空间,名称空间用一个唯一的URI(Uniform Resource Identifier,统一资源标识符)表示。 在Xml文件中书写标签时,可以通过名称空间声明(xmlns),来声明当前编写的标签来自哪个Schema约束文档。如:
<itcast:书架 xmlns:itcast=“http://www.itcast.cn”>
<itcast:书>……</itcast:书>
</itcast:书架>
此处使用itcast来指向声明的名称,以便于后面对名称空间的引用。
(2)注意:名称空间的名字语法容易让人混淆,尽管以 http:// 开始,那个 URL 并不指向一个包含模式定义的文件。事实上,这个 URL:http://www.itcast.cn根本没有指向任何文件,只是一个分配的名字。
(3)为了在一个XML文档中声明它所遵循的Schema文件的具体位置,通常需要在Xml文档中的根结点中使用schemaLocation属性来指定,例如:
<itcast:书架 xmlns:itcast="http://www.itcast.cn"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=“http://www.itcast.cn book.xsd">
schemaLocation此属性有两个值。第一个值是需要使用的命名空间。第二个值是供命名空间使用的 XML schema 的位置,两者之间用空格分隔。
(4)注意,在使用schemaLocation属性时,也需要指定该属性来自哪里。
48、使用默认名称空间
基本格式:
xmlns="URI"
举例:
<书架 xmlns="http://www.it315.org/xmlbook/schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=“http://www.itcast.cn book.xsd">
<书>
<书名>JavaScript网页开发</书名>
<作者>张孝祥</作者>
<售价>28.00元</售价>
</书>
<书架>
使用名称空间引入多个XML Schema文档
文件清单:xmlbook.xml
<?xml version="1.0" encoding="UTF-8"?>
<书架 xmlns="http://www.it315.org/xmlbook/schema"
xmlns:demo="http://www.it315.org/demo/schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.it315.org/xmlbook/schema http://www.it315.org/xmlbook.xsd
http://www.it315.org/demo/schema http://www.it315.org/demo.xsd">
<书>
<书名>JavaScript网页开发</书名>
<作者>张孝祥</作者>
<售价 demo:币种=”人民币”>28.00元</售价>
</书>
</书架>
不使用名称空间引入XML Schema文档
文件清单:xmlbook.xml
<?xml version="1.0" encoding="UTF-8"?>
<书架 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="xmlbook.xsd">
<书>
<书名>JavaScript网页开发</书名>
<作者>张孝祥</作者>
<售价>28.00元</售价>
</书>
</书架>
在XML Schema文档中声明名称空间
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www. itcast.cn"
elementFormDefault="qualified">
<xs:schema>
targetNamespace元素用于指定schema文档中声明的元素属于哪个名称空间。
elementFormDefault元素用于指定,该schema文档中声明的根元素及其所有子元素都属于targetNamespace所指定的名称空间