JavaEE开发——XML、DTD、Schema、Dom、Sax

XML

名称:可扩展标记语言,Extendsible Markup Language

用途:xml的出现就是描述一些有关系的数据,现在主要作为软件的配置文件以描述程序模块之间的关系

明确:我们学习的是w3c组织2000年发布的XML1.0规范

一. XML

1.文档声明

(1)如果没有此XML文档是一个格式不良好的文档,一个XML文档必须要有文档说明。文档说明是告诉处理引擎如何解析xml文档中的内容

(2)最简单的声明:<?xml version="1.0"?>

(3)用encoding属性说明文档的字符编码:<?xml version="1.0"     encoding="utf-8"?>——指的是浏览器打开时使用的码表,如果有除ASCII码表以外码表字符时,必须要指定这个属性,否则XML文档无法被浏览器所打开

(4)用standalone属性说明文档是否独立:<?xml version="1.0"    encoding="GB2312"    standalone=“yes"?>——当这个文档是依赖于另外一个文档而存在的,这里属性值应该为"no"

2.元素——> 标签

(1)格式良好的xml文档有且仅有一个根标签

(2)标签体中的空格和换行都会作为原始内容被处理,所有有时不能够输入

(3)便签名区分大小写

3.属性

(1)属性名区分大小写

(2)属性所代表的信息也可以改为子元素(子标签)的形式来描述

4.注释

(1)格式与html注释相同,不过要注意文档声明钱不能有注释

5.CDATA区

特点:不会被xml解析引擎解析处理,而是作为原始内容直接输出表示

语法格式:<![CDATA[内容]]>

<?xml version="1.0" encoding="gbk"?>
<!--我是注释-->
<黑马>
	<我 property="我是属性">
		<JavaSE>毕向东</JavaSE>
		<JavaEE>方立勋</JavaEE>
	</我>
	<![CDATA[
		<前我>
			<html_css>张鹏</html_css>
		</前我>
	]]>
</黑马>

6.转义字符

(1)【&】——>&amp;

(1)【>】——>&gt;

(1)【<】——>&lt;

(1)【"】——>&quot;

(1)【'】——>&apos;

7.处理指令

用法:简称PI(processing instruction)处理指令用来指挥解析引擎如何解析xml文档内容——>说明文档就是一个处理指令

例如:<?xml-stylesheet     type="text/css"    href="css文件地址"?>——>告诉处理引擎用css文件装饰此XML文档

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type="text/css" href="config.css"?>
<body>
	<head>
		<![CDATA[
			<a1>现充</a1>
			<a2>死宅</a2>
		]]>
	</head>
	
	<tbody>
		<b1>技术宅</b1>
		<b2>工业宅</b2>
	</tbody>
</body>

二. DTD

说明:DTD(文档类型定义 Document Type Definition)

意义:用来约束XML文档的书写规范,有时相当于XML的帮助文档

1.三种引用方式

(1)在xml文档内部   <!DOCTYPE  xml文档根节点  [DTD代码]>

(2)单独存在于本地系统   <!DOCTYPE   xml文档根节点   SYSTEM   ”文件位置“>

(3)存在于网络公共地址   <!DOCTYPE   xml文档根节点    PUBLIC    "DTD名称”     “DTD文件位置(url)">

按照指定DTD书写规范的xml文档(如代码所示)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE 书架 SYSTEM "book.dtd">
<书架>
	<书>
		<书名>OTAKU信息</书名>
		<作者>桂马</作者>
		<售价>1000</售价>
	</书>
	<书>
		<书名>达人</书名>
		<作者>doing</作者>
		<售价>10</售价>
	</书>
</书架>

DTD规范文档(如代码所示)

<!ELEMENT 书架 (书+)>
<!ELEMENT 书 (书名,作者,售价)>
<!ELEMENT 书名 (#PCDATA)>
<!ELEMENT 作者 (#PCDATA)>
<!ELEMENT 售价 (#PCDATA)>

2.DTD语法

2.1 元素定义

(1)DTD中使用ELEMENT声明一个xml元素

(2)语法格式: <!ELEMENT     元素名称      元素类型>——元素类型:可以是元素内容或元素类型

(3)缺点:DTD无法对数据进行更精细的操作,比如约束数据只能输入 数字 就不能用DTD实现

2.1.1 元素内容

<1>. 元素内容可用【,】逗号来分割,表示内容出现顺序必须与声明时一致

<2>. 元素内容可用【|】或的符号来分割,表示任选其一,即多个中只能出现一个

<3>. 元素内容中可以使用【+】【*】【?】来表示元素的出现次数

         【+】——>一次或多次      【?】——>零次或一次       【*】——>零次或多次   (可以使用【()】小括号形式进行次数批量设置

注意:书写时需用小括号括起来

<!ELEMENT MYFILE ((TITLE*, AUTHOR?, EMAIL)* | COMMENT)>
<!--COMMENT和前边只能有添加一个,前边中TITLE可出现0次或多次,
AUTHOR可出现1次货多次,EMAIL必须出现1次。不过这三个元素放在一起可出现0次或者多次-->

2.1.2 元素类型

<1>. EMPTY:用于定义空元素,指标签内不能添加内容——>   <书 />

<2>. ANY:表示元素内容为任意类型,指标签内容任意

注意:书写时不用小括号括起来,DTD定义的元素类型就这几种

2.2 属性定义

(1)DTD中通过ATTLIST约束XML文档属性

(2)语法格式:

<!ATTLIST 元素名
	属性名1		属性值类型		设置说明
	属性名2		属性值类型		设置说明
	......
>

2.2.1 属性值类型

<1>. CDATA:字符串

<2>. ENUMERATED:枚举——>(鸡肉 | 牛肉 | 猪肉 | 鱼肉)

<3>. ID:整个XML文档中属性值必须唯一(id值最好以字母开头,不要单单就写一个数字)

<4>. 参数实体:直接写实体名即可(实体中定义了属性名,ATTLIST中不要再写属性名)

<?xml version = "1.0" encoding="GB2312" standalone="yes"?>
<!DOCTYPE 购物篮 [
	<!ELEMENT 肉 EMPTY>
	<!ATTLIST 肉 品种 ( 鸡肉 | 牛肉 | 猪肉 | 鱼肉 ) "鸡肉">
	<!--肉标签中品种属性值类型为这个枚举类型,并且默认值为 鸡肉-->
]> 
<购物篮>
	<肉 品种="鱼肉"/><!--鱼肉是枚举值其中一个-->
	<肉 品种="牛肉"/><!--牛肉是枚举值其中一个-->
	<肉/>
</购物篮>

<!--===============================================================================================-->

<?xml version = "1.0" encoding="GB2312" ?>

<!DOCTYPE 联系人列表[
	<!ELEMENT 联系人列表 ANY><!--联系人列表标签中可添加任何元素-->
	<!ELEMENT 联系人(姓名,EMAIL)><!--联系人标签中只能是姓名和EMAIL标签-->
	<!ELEMENT 姓名(#PCDATA)>
	<!ELEMENT EMAIL(#PCDATA)>
	<!ATTLIST 联系人 编号 ID #REQUIRED><!--联系人标签中编号属性值为ID类型,并且是必须填写的属性-->
]>

<联系人列表>
	<联系人 编号="1"><!--添加了编号属性,不过属性最好为字母开头-->
		<姓名>张三</姓名>
		<EMAIL>zhang@it315.org</EMAIL>
     </联系人>
	<联系人 编号="2">
		<姓名>李四</姓名>
		<EMAIL>li@it315.org</EMAIL>
	</联系人>
</联系人列表>

2.2.2 设置说明

<1>. #REQUIRED:必须设置该属性

<2>. #IMPLIED:设置是否均可(可选的)

<3>. #FIXEED:该属性取值固定为一个值,在XML文档中不能为该属性设置其它值。但需要为该属性提供这个值。固定值跟在注释后边

<4>. 默认值:在XML文档中可以设置该值,也可以不设置,若没设置则使用默认值

<!ATTLIST 页面作者 
	姓名 CDATA #IMPLIED <!--可选的-->
	年龄 CDATA #IMPLIED 
	联系信息 CDATA #REQUIRED <!--必须的-->
	网站职务 CDATA #FIXED "页面作者" <!--固定值为"页面作者"-->
	个人爱好 CDATA "上网" <!--默认值-->
> 

2.3.实体

意义:实体用于为一段内容创建一个别名,以后在XML文档中就可以使用别名引用这段内容了

规则:DTD中通过ENTITY来定义一个实体

2.3.1 引用实体: 应用给XML文档

<1>. 语法格式:<!ENTITY     实体名称      “实体内容”>

<2>. 引用方式:&实体名称;

2.3.2 参数实体: 应用给DTD文档

<1>. 语法格式:<!ENTITY    %    实体名称     "实体内容" >

<2>. 引用方式:%实体名称

<!--引用实体,给XML文档引用-->
<!ENTITY copyright “I am a programmer"> 
	 ……
	 &copyright;

<!--参数实体,给DTD文档中-->
<!--举例1-->
<!ENTITY % TAG_NAMES "姓名 | EMAIL | 电话 | 地址">
<!ELEMENT 个人信息 (%TAG_NAMES; | 生日)>
<!ELEMENT 客户信息 (%TAG_NAMES; | 公司名)>


<!--举例2-->
<!ENTITY % common.attributes
	 " id ID #IMPLIED 
	account CDATA #REQUIRED "
>
...
<!ATTLIST purchaseOrder %common.attributes;>
<!ATTLIST item %common.attributes;>

3. DTD语法验证( 实例代码,看懂即可)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE CATALOG [

<!ENTITY AUTHOR "John Doe">
<!ENTITY COMPANY "JD Power Tools, Inc.">
<!ENTITY EMAIL "jd@jd-tools.com">

<!ELEMENT CATALOG (PRODUCT+)>

<!ELEMENT PRODUCT
(SPECIFICATIONS+,OPTIONS?,PRICE+,NOTES?)>
<!ATTLIST PRODUCT
NAME CDATA #IMPLIED
CATEGORY (HandTool|Table|Shop-Professional) "HandTool"
PARTNUM CDATA #IMPLIED
PLANT (Pittsburgh|Milwaukee|Chicago) "Chicago"
INVENTORY (InStock|Backordered|Discontinued) "InStock">

<!ELEMENT SPECIFICATIONS (#PCDATA)>
<!ATTLIST SPECIFICATIONS
WEIGHT CDATA #IMPLIED
POWER CDATA #IMPLIED>

<!ELEMENT OPTIONS (#PCDATA)>
<!ATTLIST OPTIONS
FINISH (Metal|Polished|Matte) "Matte" 
ADAPTER (Included|Optional|NotApplicable) "Included"
CASE (HardShell|Soft|NotApplicable) "HardShell">

<!ELEMENT PRICE (#PCDATA)>
<!ATTLIST PRICE
MSRP CDATA #IMPLIED
WHOLESALE CDATA #IMPLIED
STREET CDATA #IMPLIED
SHIPPING CDATA #IMPLIED>

<!ELEMENT NOTES (#PCDATA)>

]>

<CATALOG>
	<PRODUCT NAME="adaf" >
		<SPECIFICATIONS>SDFASD</SPECIFICATIONS>
		<OPTIONS>DFAF</OPTIONS>
		<PRICE>ASDFA</PRICE>
	</PRODUCT>
</CATALOG>

三. Schema

(1)Schema本身是一个Xml,Dom、Sax能够解析Schema

(2)Schema相比DTD更复杂,但它已是w3c组织的标准,正逐步取代DTD

(3)Schema文件扩展名为 .xsd

(4)Schema文档通称模式文档,按照这个文档写的xml称为实例文档

1.引用方式

<简称:根节点 xmlns:定义简称="Schema中定义的名称空间(uri)"
		    xmlns:xsi="http:www.w3.org/2001/XMLSchema-instance"
		    xsi:schemaLocation="名称空间(前面的) Schema文档地址位置">

	<简称:标签名>第一份实例文档</简称:标签名>
	<!--文档中需要约束的元素全部用定义的简称名修饰,不管是元素头还是尾-->
</简称:根节点>

xmlns:是系统识别的关键字,可以理解为一种变量类型

简称:就是名称空间的简写形式,一个引用,指向定义的名称空间

名称空间:通常名称空间是一个http地址,不过这个URI不指文件,可以看为一个值唯一的字符串标记

schemaLocation:其中定义了约束文档Schema的地址,这个关键字来自于xsi

xsi:定义的变量名,引用的是之后的名称空间,这个名称空间是个著名空间,会被Schema解析引擎所识别,会去找这个命名空间所对应的Schema文档


默认名称空间:(省略简称)

<根节点 xmlns="Schema中定义的名称空间(uri)"
	  xmlns:xsi="http:www.w3.org/2001/XMLSchema-instance"
	  xsi:schemaLocation="名称空间(前面的) Schema文档地址位置">

	<标签名>第一份实例文档</标签名>
	<!--全部元素都是必须符合Schema约束的-->
</根节点>

引用多个Schema约束文档:

<根节点 xmlns="Schema中定义的名称空间(uri)"
	  xmlns:demo="Schema中定义的名称空间(uri)"
	  xmlns:xsi="http:www.w3.org/2001/XMLSchema-instance"
	  xsi:schemaLocation="名称空间(前面的) Schema文档地址位置 名称空间(前面的) Schema文档地址位置">

	<标签名 demo:属性名="属性值">第一份实例文档</标签名>
	<!--全部元素都是必须符合Schema约束的,demo修饰的符合另一个Schema约束-->
</根节点>

2.Schema语法

2.1 根元素<schema>定义

(1)根标签必须为Schema

(2)根标签定义实例:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
			targetNamespace="自定义的名称空间"
			xmlns="http://www.w3school.com.cn"
			elementFormDefault="qualified">
<!--elementFormDefault的值可以为qualified和unqualified,前者为xsd中的全部元素绑定到名称空间中,-->
<!--后者只有根节点绑定到名称空间上-->
(3)完整的Xml与其绑定的Schema文档演示
<?xml version="1.0"?>  
<!--Schema文档-->  
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"  
targetNamespace="http://www.w3school.com.cn"  
xmlns="http://www.w3school.com.cn"  
elementFormDefault="qualified">  
<xs:element name="note">  
    <xs:complexType>  
      <xs:sequence>  
    <xs:element name="to" type="xs:string"/>  
    <xs:element name="from" type="xs:string"/>  
    <xs:element name="heading" type="xs:string"/>  
    <xs:element name="body" type="xs:string"/>  
      </xs:sequence>  
    </xs:complexType>  
</xs:element>  
</xs:schema>  
  
<!--===========================================================================-->
<?xml version="1.0"?>  
<!--对应Xml文档-->  
<note  
xmlns="http://www.w3school.com.cn"  
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
xsi:schemaLocation="http://www.w3school.com.cn note.xsd">  
<to>Tove</to>  
<from>Jani</from>  
<heading>Reminder</heading>  
<body>Don't forget me this weekend!</body>  
</note> 

2.2 简单元素与属性

(1)简单元素语法:<xs:element name="xxx" type="yyy">

(2)简单属性语法:<xs:attribute name="xxx" type="yyy">

(2)元素或属性类型:(Text的数据类型,属性值类型)

  • xs:string——字符串
  • xs:decimal——小数
  • xs:integer——整数
  • xs:boolean——布尔值
  • xs:date——日期
  • xs:time——时间

(3)默认值和固定值

<1>.默认值:<xs:element name="color" type="xs:string" default="red"/>

<2>.固定值:<xs:element name="color" type="xs:string" fixed="red"/>

2.3 限定类型

限定描述
enumeration定义可接受值的一个列表
fractionDigits定义所允许的最大的小数位数。必须大于等于0。
length定义所允许的字符或者列表项目的精确数目。必须大于或等于0。
maxExclusive定义数值的上限。所允许的值必须小于此值。
maxLength定义所允许的字符或者列表项目的最大数目。必须大于或等于0。
minExclusive定义数值的下限。所允许的值必需大于此值。
minInclusiv定义数值的下限。所允许的值必需大于或等于此值。
minLength定义所允许的字符或者列表项目的最小数目。必须大于或等于0。
pattern定义可接受的字符的精确序列
totalDigits定义所允许的阿拉伯数字的精确位数。必须大于0。
whiteSpace定义空白字符(换行、回车、空格以及制表符)的处理方式。

(1)用法实例:

<1>.下面的例子定义了带有一个限定的名为 "age" 的元素。age 的值不能低于 0 或者高于 120:

<xs:element name="age">
<xs:simpleType>
  <xs:restriction base="xs:integer">
    <xs:minInclusive value="0"/>
    <xs:maxInclusive value="120"/>
  </xs:restriction>
</xs:simpleType>
</xs:element> 

<2>.下面的例子定义了带有一个限定的名为 "car" 的元素。可接受的值只有:Audi, Golf, BMW:

<xs:element name="car">
<xs:simpleType>
  <xs:restriction base="xs:string">
    <xs:enumeration value="Audi"/>
    <xs:enumeration value="Golf"/>
    <xs:enumeration value="BMW"/>
  </xs:restriction>
</xs:simpleType>
</xs:element> 

<3>.类型可以定义名字,分配给多个使用者

<xs:element name="car" type="carType"/>
<xs:simpleType name="carType">
  <xs:restriction base="xs:string">
    <xs:enumeration value="Audi"/>
    <xs:enumeration value="Golf"/>
    <xs:enumeration value="BMW"/>
  </xs:restriction>
</xs:simpleType>

<4>.下一个例子定义了带有一个限定的名为 "initials" 的元素。可接受的值是大写字母 A - Z 其中的三个:

<xs:element name="initials">
<xs:simpleType>
  <xs:restriction base="xs:string">
    <xs:pattern value="[a-zA-Z][a-zA-Z][a-zA-Z]"/>
  </xs:restriction>
</xs:simpleType>
</xs:element> 

2.4 复杂类型与类型指示器

(1)复杂类型分为四种如下:(详细请查看文档)

  • 空元素
  • 包含其他元素的元素
  • 仅包含文本的元素
  • 包含元素和文本的元素

(2)类型指示器

<1>.Order指示器

  • All——随机出现,无所谓
  • Choice——要么有前一个,要么有后一个
  • Sequence——必须是按照Schema文档中的前后排列顺序

<2>.Occurrence指示器

  • maxOccurs——最多出现几次
  • minOccurs——最少出现几次

(3)实例演示

<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">

<xs:element name="persons">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="person" maxOccurs="unbounded"><!--表示出现次数没有上限-->
        <xs:complexType><!--复杂类型-->
          <xs:sequence>
            <xs:element name="full_name" type="xs:string"/>
            <xs:element name="child_name" type="xs:string"
            minOccurs="0" maxOccurs="5"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
  </xs:complexType>
</xs:element>

</xs:schema>

2.5 Schema检验 (通过Schema能够写出Xml文档)

<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="shiporder">
 <xs:complexType>
  <xs:sequence>
   <xs:element name="orderperson" type="xs:string"/>
   <xs:element name="shipto">
    <xs:complexType>
     <xs:sequence>
      <xs:element name="name" type="xs:string"/>
      <xs:element name="address" type="xs:string"/>
      <xs:element name="city" type="xs:string"/>
      <xs:element name="country" type="xs:string"/>
     </xs:sequence>
    </xs:complexType>
   </xs:element>
   <xs:element name="item" maxOccurs="unbounded">
    <xs:complexType>
     <xs:sequence>
      <xs:element name="title" type="xs:string"/>
      <xs:element name="note" type="xs:string" minOccurs="0"/>
      <xs:element name="quantity" type="xs:positiveInteger"/>
      <xs:element name="price" type="xs:decimal"/>
     </xs:sequence>
    </xs:complexType>
   </xs:element>
  </xs:sequence>
  <xs:attribute name="orderid" type="xs:string" use="required"/>
 </xs:complexType>
</xs:element>

</xs:schema>

xml文档如下:


四. XML编程(CRUD)

目的:因为XML有获取关系数据的作用,如果你想获取这些数据,你必然会对其进行解析

1.解析方式

1.1 DOM解析

(1)解释:dom解析(Document Object Model)文档对象模型

(2)原理:解析引擎会转载整个Xml文档,在内存中建立关于文档中节点对象,并按照节点关系建立对象间的关系,形成一颗对象树

(3)使用:程序员要得到代表文档的Document对象,就可以遍历出所有节点。并且通过调用节点对象的方法,可以方便的实现对Xml文档的CURD

(4)优点:增删改方便

(5)缺点:因为需装在整个Xml文档,对计算机内存消耗巨大,文档过大的话可能会内存溢出,不适合处理大文档

1.2 Sax解析

(1)特点:边解析边处理,占用内存少,解析速度快

(2)缺点:不能对Xml文档进行CUD的操作


2.解析器

理解:解析器就是指工具,对Xml进行解析的是已经编程好的工具,里边封装了Dom与Sax两种解析方式,我们用的API就是其给外边提供的能够访问的接口

2.1 Crimson

了解:sun公司开发,最垃圾,Jdk1.4以前Java自己用的就是这个解析器。此解析器现在属于Apache

2.2 Xerces

了解:IBM公司开发,性能不错,Jdk1.4以后Sun公司不用自己的解析器了,反而用这个解析器解析Xml。此解析器现在属于Apache

2.3 Aelfredz

了解:dom4j组织开发,性能不错


3.开发包

理解:解析器的能够访问的接口

3.1 JAXP

了解:sun公司开发,用的是Xerces解析器,性能最差,不过要会用

3.2 Jdom

了解:Jdom组织开发,用的是Aelfredz解析器,性能适中(几乎不用)。Jdom组织分裂后生成了dom4j

3.3 dom4j

了解:dom4j组织开发,用的是Aelfredz解析器,性能最好,dom4j基本代替了Jdom,所有要会用


4.Jasp工具包具体使用

位置:JAXP开发包是JavaSE的一部分,javax.xml包、orc.w3c.dom包、org.xml.sax包以及其子包组成

使用:JAXP在Javax.xml.parse包中定义了一些工厂类,你只需调用工厂类中的方法既可得到对Xml进行解析dom对象或者Sax对象

4.1 Dom解析实现

重要:Document对象树中所有节点对象都是Node的子类对象,文档的根节点、子节点与内容【空格换行与标签内容】都是Element的子类对象

DocumentBuilderFactory抽象类

位置:javax.xml.parsers包

方法摘要
static DocumentBuilderFactorynewInstance()
          获取 DocumentBuilderFactory 的新实例。建立解析器工厂
abstract  DocumentBuildernewDocumentBuilder()
          使用当前配置的参数创建一个新的 DocumentBuilder 实例。生产出一个Dom解析器
DocumentBuilder类

位置:javax.xml.parsers包

方法摘要
 Documentparse(File f)
          将给定文件的内容解析为一个 XML 文档,并且返回一个新的 DOM Document 对象。通过解析Xml文档返回对象树根节点Document对象,之后可用递归方法获取对象树中全部的节点
Node接口

方法摘要
 StringgetTextContent()
          此属性返回此节点及其后代的文本内容。
 voidsetTextContent(String textContent)
          此属性返回此节点及其后代的文本内容。
 NodeListgetChildNodes()
          包含此节点的所有子节点的 NodeList获取全部子节点并存入NodeList容器中
 NodegetFirstChild()
          此节点的第一个子节点。
 NodegetLastChild()
          此节点的最后一个节点。
 StringgetNodeName()
          此节点的名称,取决于其类型;参见上表。
 NodeappendChild(Node newChild)
          将节点 newChild 添加到此节点的子节点列表的末尾。通过父节点来插入节点到末尾
 NodeinsertBefore(Node newChild,Node refChild)
          在现有子节点 refChild 之前插入节点 newChild通过父节点来插入节点到指定位置
 NoderemoveChild(Node oldChild)
          从子节点列表中移除 oldChild 所指示的子节点,并将其返回。通过父节点来删除指定子节点,并返回
 NodereplaceChild(Node newChild,Node oldChild)
          将子节点列表中的子节点 oldChild 替换为 newChild,并返回 oldChild 节点。通过父节点来修改子节点为指定节点
 NodegetParentNode()
          此节点的父节点。

Document接口
方法摘要
 ElementgetElementById(String elementId)
          返回具有带给定值的 ID 属性的 Element
 NodeListgetElementsByTagName(String tagname)
          按文档顺序返回包含在文档中且具有给定标记名称的所有 ElementNodeList
 ElementcreateElement(String tagName)
          创建指定类型的元素。
Element接口
方法摘要
 StringgetAttribute(String name)
          通过名称获得属性值。
 voidsetAttribute(String name,String value)
          添加一个新属性。
 NodeListgetElementsByTagName(String name)
          以文档顺序返回具有给定标记名称的所有后代 ElementsNodeList
NodeList接口
方法摘要
 intgetLength()
          列表中的节点数。
 Nodeitem(int index)
          返回集合中的第 index 个项。
TransformerFactory抽象类

方法摘要
static TransformerFactorynewInstance()
          获取 TransformerFactory 的新实例。获取转换器工厂对象
abstract  TransformernewTransformer()
          创建执行从 SourceResult 的复制的新 Transformer获取解析器

Transformer类

重要:把内存中的对象树更新到Xml文档的功能可用该类实现。此类具有把某Document对象转换为某种格式进行输出。例如把Xml文件应用样式表转换为一个html文档

方法摘要
abstract  voidtransform(Source xmlSource,Result outputTarget)
          将 XML Source 转换为 Result把代表Source的内存对象更新到本地文件中
DomSource类

主要:此类是Source接口的子类

构造方法摘要
DOMSource(Node n)
          创建带有 DOM 节点的新输入源。(传入节点对象构造Source)
StreamResult类

主要:此类是Result接口的子类

构造方法摘要
StreamResult(File f)
          从 File 构造 StreamResult。
StreamResult(OutputStream outputStream)
          从字节流构造 StreamResult。传入输出流构造对象
代码实现
package cn.doing.xml;

import java.io.FileOutputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class ParseXml {

	private Document document;
	
	@Before
	public void before()throws Exception{
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		//得到dom解析器
		DocumentBuilder builder = factory.newDocumentBuilder();
		System.out.println(builder);
		
		document = builder.parse("src/03.ParseXml/01.ParseOTAKU.xml");
	}
	
	//遍历Xml结点信息打印在控制台上
	@Test
	public void parse_01() {
		list(document);
	}
	
	//遍历文档节点的具体实现
	public void list(Node n){
		System.out.println(n.getNodeName());
		NodeList list = n.getChildNodes();
		for(int x=0; x<list.getLength(); x++){
			Node child =  list.item(x);
			list(child);
		}
	}
	
	//获取xml文档中具体标签中的值 <a1>现充</a1>
	@Test
	public void parse_02(){
		Node node = document.getElementsByTagName("a1").item(0);
		System.out.println(node.getTextContent());
	}
	
	//获取xml文档标签中属性的值 <a1>现充</a1>
	@Test
	public void parse_03(){
		//结点包括很多,标签、文本、PI指令、属性这些,因为只有标签才具有属性值,如果需要获取属性值,只能强转为Element后才有这个功能。
		Element type = (Element) document.getElementsByTagName("a1").item(0);
		String value = type.getAttribute("type");
		System.out.println(value);
	}
	
	//插入结点在指令标签中
	@Test
	public void parse_04() throws Exception{
		//创建要挂的结点
		Element a3 = document.createElement("a1");
		a3.setTextContent("Java持续进步中!");
		a3.setAttribute("type", "程序员");
		//把创建的结点挂到head结点下
		Node node = document.getElementsByTagName("head").item(0);
		node.appendChild(a3);
		
		//使内存中更新的对象树加载到实体XML文件当中	
		TransformerFactory factory = TransformerFactory.newInstance();
		Transformer tran = factory.newTransformer();
		tran.transform(new DOMSource(document), new StreamResult(new FileOutputStream("src/03.ParseXml/01.ParseOTAKU.xml")));
		
	}
	
	//在指定位置插入结点
	@Test
	public void parse_05() throws Exception{
		//创建要挂的标签
		Element a4 = document.createElement("a4");
		a4.setTextContent("我的JAVA");
		a4.setAttribute("type", "我的");
		
		//获取要挂标签的节点与此节点中要挂子节点的位置
		Node head = document.getElementsByTagName("head").item(0);
		Node before = document.getElementsByTagName("a1").item(0);
		head.insertBefore(a4, before);
		
		//是内存中的更新的对象树加载到XML文件当中
		TransformerFactory factory = TransformerFactory.newInstance();
		Transformer tran = factory.newTransformer();
		tran.transform(new DOMSource(document), new StreamResult(new FileOutputStream("src/03.ParseXml/01.ParseOTAKU.xml")));
		
	}
	
	//删除指令结点
	@Test
	public void parse_06() throws Exception{
		//获取父节点与要删除的子节点
		Element father = (Element) document.getElementsByTagName("head").item(0);
		Node child=  document.getElementsByTagName("a4").item(0);
		
		//简单方法为:
		child.getParentNode().removeChild(child);
		
		//通过父节点方法删除子节点
		//father.removeChild(child);
		
		//把内存中更新的对象树加载到XML文件当中
		TransformerFactory factory = TransformerFactory.newInstance();
		Transformer tran = factory.newTransformer();
		tran.transform(new DOMSource(document), new StreamResult(new FileOutputStream("src/03.ParseXml/01.ParseOTAKU.xml")));		
	}
}

4.2 Sax解析实现


SAXParserFactory抽象类
方法摘要
static SAXParserFactorynewInstance()
          获取 SAXParserFactory 的一个新实例。建立一个SAX解析器工厂
abstract  SAXParsernewSAXParser()
          使用当前配置的工厂参数创建 SAXParser 的一个新实例。获取SAX解析器
SAXParser类
方法摘要
abstract  XMLReadergetXMLReader()
          返回由此类的实现封装的 XMLReader获取XML读取器
 voidparse(InputStream is,DefaultHandler dh)
          使用指定的 DefaultHandler 将给定的InputStream 实例的内容解析为 XML。方便的解析方法,内部封装了读取器
XMLReader类

位置:org.xml.sax包

方法摘要
 voidsetContentHandler(ContentHandler handler)
          允许应用程序注册内容事件处理程序。往解析器里面注册一个自定义的处理器
 voidparse(InputSource input)
          解析 XML 文档。
ContentHandler接口
方法摘要
 voidstartElement(String uri,String localName,String qName,Attributes atts)
          接收元素开始的通知。解析到一个开始标签时调用此方法,qName是指标签名,atts是存储标签中全部属性的集合
 voidendElement(String uri,String localName,String qName)
          接收元素结束的通知。解析到一个结束标签时调用此方法,qName是指标签名
voidcharacters(char[] ch, int start, int length)
          接收字符数据的通知。解析到内容时调用此方法,会把解析到的数据存储到ch字符数组中,start数存储数据的开始位置,length是数据长度
DefaultHandler类

注意:此类是ContentHandler的子类,是一个适配器类,通常写处理器会继承此类

Attributes接口
方法摘要
 intgetLength()
          返回此列表中的属性个数。
 StringgetQName(int index)
          通过索引查找属性的 XML 限定(前缀)名。
 StringgetValue(int index)
          通过索引查找属性的值。
代码实现

功能:遍历xml文档所有节点

package First.cn.doing.sax;

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.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

public class ListHandler {

	/**
	 * @param args
	 * @throws SAXException 
	 * @throws ParserConfigurationException 
	 * @throws IOException 
	 */
	public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
		//1.获取解析器的工厂
		SAXParserFactory factory = SAXParserFactory.newInstance();
		
		//2.获取解析器
		SAXParser parser = factory.newSAXParser();
		 
		//3.获取解析器的读取器
		XMLReader reader = parser.getXMLReader();
		
		//4.向读取器中传入处理器
		reader.setContentHandler(new DefaultHandler(){

			//读取到标签开始处调用
			@Override
			public void startElement(String uri, String localName,
					String qName, Attributes attributes) throws SAXException {
				System.out.print("<"+qName+">");
			}

			//读取到标签结束处调用
			@Override
			public void endElement(String uri, String localName, String qName)
					throws SAXException {
				System.out.println("<"+qName+">");
			}

			//读取到标签内的文本内容时调用
			@Override
			public void characters(char[] ch, int start, int length)
					throws SAXException {
				System.out.print(new String(ch,start,length));
			}
		});
		
		//5.读取器解析XML文档
		reader.parse("src/user.xml");
	}

}

功能:获取具体某个节点中的内容

package First.cn.doing.sax;

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.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

public class UserNameHandler {

	/**
	 * @param args
	 * @throws SAXException 
	 * @throws ParserConfigurationException 
	 * @throws IOException 
	 */
	public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
		//1.获取解析器工厂
		SAXParserFactory factory = SAXParserFactory.newInstance();
		
		//2.获取解析器
		SAXParser parser = factory.newSAXParser();
		 
		//3.获取XML读取器
		XMLReader reader = parser.getXMLReader();
		
		//4.向读取器中注册处理器
		reader.setContentHandler(new DefaultHandler(){

			private String currentTag;
			private int count;
			
			@Override
			public void startElement(String uri, String localName,
					String qName, Attributes attributes) throws SAXException {
				currentTag = qName;
				if("职业".equals(qName))
					count++;
			}

			@Override
			public void characters(char[] ch, int start, int length)
					throws SAXException {
				if("职业".equals(currentTag) && count == 2){
					System.out.print(new String(ch,start,length));
				}
			}
		});
		//解析XML文档
		reader.parse("src/user.xml");
	}
}

功能:把XML文件中的关系数据用对象形式封装,并且把对象存入到ArrayList集合中

package First.cn.doing.sax;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import First.cn.doing.domain.Person;


public class BeanListHandler {
	
	public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException{
		//1.创建Sax解析工厂
		SAXParserFactory factroy = SAXParserFactory.newInstance();
		
		//2.通过工厂方法建立解析器
		SAXParser parser = factroy.newSAXParser();
		 
		//3.建立Xml文件读取器
		XMLReader reader = parser.getXMLReader();
		 
		//向读取器中注册处理器
		List<Person> list = new ArrayList<Person>();
		MyListHandler handler = new MyListHandler();
		
		reader.setContentHandler(handler);
		
		//解析指定Xml文档
		reader.parse("src/user.xml");
		
		System.out.println(handler.getList().size());
	}
}

class MyListHandler extends DefaultHandler{
	private List<Person> list = new ArrayList<Person>();
	private String currentTag;
	private Person person;
	
	@Override
	public void startElement(String uri, String localName,
			String qName, Attributes attributes) throws SAXException {
		currentTag = qName;
		if("用户".equals(qName))
			person = new Person();
	}

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		currentTag = "";
		if("用户".equals(qName))
			list.add(person);
	}

	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		if("姓名".equals(currentTag))
			person.setName(new String(ch,start,length));
		if("年龄".equals(currentTag))
			person.setAge(new String(ch,start,length));
		if("职业".equals(currentTag))
			person.setJob(new String(ch,start,length));
		if("爱好".equals(currentTag))
			person.setHobby(new String(ch,start,length));
	}
	
	public List<Person> getList(){
		return list;
	}
}

5.dom4j工具包具体使用

注意:Node、Document、Element继承关系和JAXP中一样

SAXReader类

Constructor Summary
SAXReader()
构造解析器
           


Method Summary
 Documentread(File file)
           解析器读取文件File
 Documentread(URL url)
          通过Url读取
 Documentread(InputStream in)
           通过读取流读取
 Documentread(String systemId)
           通过路径名读取

Document类

Method Summary
 ElementgetRootElement()
         获取根节点


Element类

Method Summary
 Elementelement(String name)
          获取名称为name 的子标签(name是子标签才能获取)
 IteratorelementIterator(String name)
        获取名称为name的子标签的全部子标签迭代器
 Listelements()
           把全部子标签元素存入一个List集合中
IteratorelementIterator()
          获取子标签迭代器
 intnodeCount()
          获取子标签数,从父类Branch中继承的方法
 Nodenode(int index)
          通过索引获取节点对象,从父类Branch中继承
 ElementaddElement(String name)
          添加一个子标签,返回添加的子节点。不用自己重新创建
 ElementaddAttribute(String name,String value)
           添加一个属性,返回自己。不用自己重新创建
 ElementaddText(String text)
          添加内容,返回自己
 StringattributeValue(String name) 
           返回name属性的值的字符串形式

DocumentHelper类

Method Summary
static DocumentcreateDocument()
创建一个对象树
static ElementcreateElement(String name)
创建一个标签元素

XMLWriter类

Constructor Summary
XMLWriter(OutputStream out)
           通过制定字节输出流构造对象会把以utf-8编码的Document对象以utf-8编码写到本地文件中
XMLWriter(OutputStream out,OutputFormat format)
           传入输出流的基础上,指定一个标准输出格式
XMLWriter(Writer writer)
           通过制定字符输出流构造对象读取Document对象时会查询编码表,然后把数据按照自定义指定的码表写到一个文件当中
XMLWriter(Writer writer,OutputFormat format)
            传入输出流的基础上,指定一个标准输出格式

Method Summary
 voidwrite(Document doc)
           把对象树写入到文件中 
 voidclose()
          Closes the underlying Writer

OutputFormat类

Method Summary
static OutputFormatcreateCompactFormat()
         获取无空格换行的输出格式
static OutputFormatcreatePrettyPrint()
          获取有优美格式的输出格式
 voidsetEncoding(String encoding)
          能够指定输出流以哪种码表输出

代码实现

package Second.cn.doing.dom4j;

import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.junit.Test;

public class dom4j_01 {
	
	//遍历Xml文档标签
	@Test
	public void listFile() throws Exception{
		SAXReader reader = new SAXReader();
		Document document = reader.read("src/user.xml");
		Element root = document.getRootElement();
		System.out.println(root.getName());
		Element user = root.element("用户");
		Element name = user.element("姓名");
		System.out.println(name.getName());
		System.out.println(name.getText());
		list(root);
	}
	
	public void list(Element e){
		System.out.println(e.getName());
		List<Element> list = e.elements();
		for(Element child : list)
			list(child);
	}
	
	//获取	<职业>学生</职业> 节点内容
	@Test
	public void getContent() throws Exception{
		SAXReader reader = new SAXReader();
		Document document = reader.read("src/user.xml");
		Element job = document.getRootElement().element("用户").element("职业");
		String content = job.getTextTrim();
		System.out.println(content);
	}
	
	//获取	<职业 avc="啊啊啊">学生</职业> 节点属性值
	@Test
	public void getAttribute() throws Exception{
		SAXReader reader = new SAXReader();
		Document document = reader.read("src/user.xml");
		Element job = document.getRootElement().element("用户").element("职业");
		String content = job.attributeValue("avc");
		System.out.println(content);
	}
		
	//向xml文档中添加一个<杰出程度>节点
	@Test
	public void addElement() throws Exception{
		SAXReader reader = new SAXReader();
		Document document = reader.read("src/user.xml");
		
		//创建要添加的结点内容属性并添加到指定位置
		Element newChild = document.getRootElement().element("用户").addElement("杰出程度")
				.addAttribute("boolean", "ture").addText("垃圾");
		
		//运用格式化输出器修改编码方式
		OutputFormat format = OutputFormat.createPrettyPrint();
		format.setEncoding("utf-8");
		
		//把更新好的对象document回写到xml文档中
		XMLWriter writer = new XMLWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream("src/user.xml"), "utf-8")),format);
		writer.write(document);
		writer.close();
		
		//注:如果让XMLWriter写数据到xml文档中,只会按着utf-8码表。如果xml文档是GB2312格式的,会把文档强转为utf-8的
		//为了防止乱码,应该用Format指定码表输出
		//add方法返回值为什么一般是添加的元素?因为这样便于在这个添加的节点上继续添加元素
	}
	
	//向xml文档指定位置添加 <杰出程度> 节点。
	@Test
	public void addElementOfSpecificLocation() throws Exception{
		SAXReader reader = new SAXReader();
		Document document = reader.read("src/user.xml");
		
		Element child = DocumentHelper.createElement("杰出程度");
		child.setText("哈哈");
		
		//在list集合指定位置添加元素 
		List<Element> list = document.getRootElement().element("用户").elements();
		list.add(2, child);//通过List集合添加元素在指定角标的方法
		
		//格式化回写的数据
		OutputFormat format = OutputFormat.createPrettyPrint();
		format.setEncoding("utf-8");
		
		//回写数据
		XMLWriter writer = new XMLWriter(new BufferedOutputStream(new FileOutputStream("src/user.xml")),format);
		writer.write(document);
		writer.close();
	}
	
	//删除和修改代码和dom类似就不再写了!
	
}

XPath

dom4j中一种便捷取出指定节点的一种表达式语法。语法请看XPath文档很简单的

位置:jaxen-1.1 bata包中,所以在导入dom4j包的基础上还要导入这个开发包

Node接口

Method Summary
 ListselectNodes(String xpathExpression)
           返回按照XPath表达式查询到的所有标签对象的集合
 NodeselectSingleNode(String xpathExpression)
           返回按照XPath表达式查询到的所有标签对象的第一个节点
StringvalueOf(String xpathExpression)
           获取XPath表达式对应节点的字符串值

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值