黑马程序员 方立勋JavaWEB视频 第2、3天 xml笔记

01-xml语言和作用

XML:Extensible Markup Language,可扩展标记语言。
XML技术是W3C组织发布的,目前推荐遵循的是W3C组织于2000年发布的XML1.0规范。
XML语言出现的根本目标在于描述上图那种,在现实生活中经常出现的有关系的数据。
在XML语言中,它允许用户自定义标签。一个标签用于描述一段数据;一个标签可分为开始标签和结束标签,在开始标签和结束标签之间,又可以使用其他标签描述其他数据,以此来实现数据关系的描述。

<?xml version="1.0" encoding="UTF-8"?>

<中国>
      <北京>
            <海淀></海淀>
	    <丰台></丰台>	
      </北京>
      <湖南>
            <长沙></长沙>
	    <岳阳></岳阳>
      </湖南>
      <湖北>
            <武汉></武汉>
	    <荆州></荆州>
      </湖北>
</中国>


XML技术除用于保存有关系的数据之外,它还经常用作软件配置文件,以描述程序模块之间的关系。
在一个软件系统中,为提高系统的灵活性,它所启动的模块通常由其配置文件决定。
--例如一个软件在启动时,它需要启动A、B两个模块,而A、B这两个模块在启动时,又分别需要A1、A2和B1、B2模块的支持,为了准确描述这种关系,此时使用XML文件最为合适不过。

02-xml语法详解
一个XML文件分为如下几部分内容:
--文档声明
--元素
--属性
--注释
--CDATA区、特殊字符
--处理指令(processing instruction)

-文档声明
在编写XML文档时,需要先使用文档声明,声明XML文档的类型。
最简单的声明语法:
<?xml version="1.0" ?>
用encoding属性说明文档的字符编码:
<?xml version="1.0" encoding="GB2312" ?>
用standalone属性说明文档是否独立:
<?xml version="1.0" encoding="GB2312" standalone="yes" ?>
没有文档声明的文档成为格式不良好的XML文档
常见错误:
在记事本中以<?xml version="1.0" encoding="UTF-8" ?>来声明的xml文档,默认用ANSI编码保存在硬盘上,而用浏览器打开的时候是用文档声明中的UTF-8编码来解码的,所以出现乱码。可以在保存文档的时候以UTF-8编码来保存,那样在用浏览器打开的时候就不是乱码了。
而用eclipse和myeclipse来编写xml文档时,修改encoding时,这些IDE都会随之改变成对应的编码方式。
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>,standalone如果为"no",表示这个xml文件不是独立的,需要其他文档关联实现,但是很多浏览器都没有对应的解释器,无法识别。

-标签
xml元素指xml文件中出现的标签,一个标签分为开始标签和结束标签,一个标签有如下几种书写形式,例如:
    包含标签体:<a>www.itcast.cn</a>
    不含标签体的:<a></a>,简写为:<a/>
一个标签中也可以嵌套若干子标签。但所有标签必须合理的嵌套,却对不允许交叉嵌套,例如:
    <a>welcome to <b>www.it315.org</a></b>
格式良好的xml文档必须有且仅有一个根标签,其他标签都是这个根标签的子孙标签。

对于xml标签中出现的所有空格和换行,xml解析程序都会当做标签内容进行处理。例如:下面两段内容的意义是不一样的。
第一段:
<网址>www.itcast.cn</网址>

第二段:
<网址>
   www.itcast.cn
</网址>
由于在xml中,空格和换行都作为原始内容被处理,所以,在编写xml文件时,使用换行和缩进等方式来让原文件中的内容清晰可读的“良好”书写习惯可能要被迫改变。

命名规范:
一个xml元素可以包含字母、数字以及其他一些可见字符,但必须遵守下面的一些规范:
区分大小写,例如,<P>和<p>是两个不同的标记。
不能以数字或"_"(下划线)开头。
不能以xml(或XML、或Xml等)开头。
不能包含空格。
名称中间不能包含冒号(:).

-属性
一个标签可以有多个属性,每个属性都有它自己的名称和取值,例如:
<input name="text">
属性值一定要用双引号(")或单引号(')引起来
定义属性必须遵循与标签相同的命名规范
多学一招:在xml技术中,标签属性所代表的信息,也可以被改成用子元素的形式来描述,例如:
<input>
 <name>text</name>
</input>

-注释
xml文件中的注释采用:"<!--注释-->"格式。
注意:
    xml声明之前不能有注释
    注释不能嵌套,例如:
    <!--大段注释
    ……
      <!---局部注释->
    ……
    -->

CDATA区
在编写XML文件时,有些内容可能不想让解析引擎解析执行,而是当做原始内容处理。
遇到此种情况,可以把这些内容放在CDATA区里,对于CDATA区域内的内容,XML解析程序不会处理,而是直接原封不动的输出。
语法:<![CDATA[内容]]>
<![CDATA[
    <itcast>
           <br/>
    </itcast>
]]>

转义字符
对于一些单个字符,若想显示其原始样式,也可以使用转义的形式予以处理。
特殊字符 替代符号
    &       &amp;
    <       &lt;
    >       &gt;
    "       &quot;
    .       &apos;

CDATA和转义的区别:
给人看原始样式用转义,给程序原始样式用CDATA区。

处理指令
简称PI(processing instruction)。处理指令用来指挥解析引擎如何解析XML文档内容。
例如,在XML文档中可以使用xml-stylesheet指令,通知XML解析引擎,应用css文件显示xml文档内容。
<?xml-stylesheet type="text/css" href="1.css"?>
处理指令必须以"<?"作为开头,以"?>"作为结尾,XML声明语句就是最常见的一种处理指令。

放在同一目录下的xml和css文件,可以通过浏览器显示文字样式。
xml文档:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type="text/css" href="config1.css"?>
<soft>
      <a>
         <a1 id="a1">中国</a1>
	     <a2 id="a2">美国</a2>
      </a>
      <b>
         <b1 id="b1">日本</b1>
	     <b2 id="b2">英国</b2>
      </b>
</soft>


css文档:

#a1{
	font-size:300px;
	color:red;
}
#a2{
	font-size:100px;
	color:green;
}
#b1{
	font-size:20px;
}
#b2{
	font-size:200px;
	color:blue;
}


 

03-XmlDTD约束和DTD校验
XML约束概述
什么是XML约束
在XML技术里,可以编写一个文档来约束一个XML文档的书写规范,这称之为XML约束。
为什么需要XML约束
常用的约束技术:
XML DTD
XML Schema

DTD约束快速入门
DTD(Document Type Definition),全称为文档类型定义。
文件清单:

book.xml

<?xml version="1.0" ?>
<!DOCTYPE 书架 SYSTEM "book.dtd">
<书架>
    <书>
          <书名>Java就业培训教程</书名>
	  <作者>张孝祥</作者>
	  <售价>39.00</售价>
    </书>
    <书>
          <书名>JavaScript网页开发</书名>
	  <作者>张孝祥</作者>
	  <售价>28.00</售价>
    </书>
</书架>


book.dtd

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


 

DTD文件应使用UTF-8或Unicode

PCDATA(parse character data)可解析的字符数据

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE 书架 SYSTEM "book.dtd">
<书架>
    <书>
          <书名>Java就业培训教程</书名>
	  <作者>张孝祥</作者>
	  <售价>39.00</售价>
    </书>
    <书>
          <书名>JavaScript网页开发</书名>
	  <作者>张孝祥</作者>
	  <售价>28.00</售价>
    </书>
    <阿猫></阿猫>
</书架>


 

以上在ie中可以正确显示

Tip:编程校验XML文档正确性
IE5以上浏览器内置了XML解析工具:Microsort.XMLDOM,开发人员可以编写javascript代码,利用这个解析工具装载xml文件,并对xml文件进行dtd验证。
创建xml文档解析器对象
var xmldoc = new ActiveXObject("Microsoft.XMLDOM");
开启xml校验
xmldoc.validateOnParse="true";
装载文档
xmldoc.load("book.xml");
获取错误信息
xmldoc.parseError.reason;
xmldoc.parseError.line
但是如今开发不适用以上方法,使用myeclipse来校验
实际开发的时候不需要写dtd,而写框架人员需要写dtd,要求不高,要会读。

04-XMLDTD语法详解和分析struts的DTD约束文档
编写DTD约束的两种方式
DTD约束即可以作为一个单独的文件编写,也可以在XML文件内编写。
在XML文件内编写DTD

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE 书架 [
    <!ELEMENT 书架(书+)>
    <!ELEMENT 书 (书,作者,售价)>
    <!ELEMENT 书名 (#PCDATA)>
    <!ELEMENT 作者 (#PCDATA)>
    <!ELEMENT 售价 (#PCDATA)>
]>
<书架>
    <书>
          <书名>Java就业培训教程</书名>
	  <作者>张孝祥</作者>
	  <售价>39.00</售价>
    </书>
    <书>
          <书名>JavaScript网页开发</书名>
	  <作者>张孝祥</作者>
	  <售价>28.00</售价>
    </书>
</书架>


 

引用DTD约束
XML文件使用DOCTYPE声明来指明它所遵循的DTD文件,DOCTYPE声明语句有两种形式;
--当引用的文件在本地时,采用如下方式:
<!DOCTYPE 文件根结点 SYSTEM "DTD文件的URL">
例如:<!DOCTYPE 书架 SYSTEM "book.dtd">。

--当引用的文件是一个公共的文件时,采用如下方式:
<!DOCTYPE 文档根结点 PUBLIC "DTD名称" "DTD文件的URL">
例如:<!DOCTYPE web-app PUBLIC "-//Sun Microsystems.lnc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2.3.dtd">

DTD约束语法细节
元素定义
属性定义
实体定义

--元素定义1:
在DTD文档中使用ELEMENT声明一个XML元素,语法格式如下所示:
<!ELEMENT 元素名称 元素类型>
元素类型可以是元素内容、或类型
    如为元素内容:则需要使用()括起来,如
        <!ELEMENT 书架(书名,作者,售价)>
 <!ELEMENT 书名(#PCDATA)>
    如为元素类型,则直接书写,DTD规范定义了如下几种类型:
        EMPTY:用于定义空元素,例如<br/> <hr/>
 ANY:表示元素内容为任意类型。
  元素定义2:
元素内容中可以使用如下方式,描述内容的组成关系
    用逗号分隔,表示内容的出现顺序必须与声明时一致。
    <!ELEMENT MYFILE(TITLE,AUTHOR,EMAIL)>
    用|分隔,表示任选其一,即多个只能出现一个
    <!ELEMENT MYFILE(TITLE|AUTHOR|EMAIL)>
在元素内容中也可以使用+、*、?等符号表示元素出现的次数:
    +:一次或多次(书+)
    ?:0次或一次(书?)
    *:0次或多次(书*)
    (书)这样写必须出现一次
也可以使用圆括号()批量设置,例如
<!ELEMENT MYFILE((TITLE*,AUTHOR?,EMAIL)*|COMMENT)>

属性定义:
xml文档中的标签属性需要通过ATTLIST为其设置属性
语法格式:
<!ATTLIST 元素名
    属性名1 属性值类型 设置说明
    属性名2 属性值类型 设置说明
    ……
>
属性声明举例:
<ATTLIST 商品
  类别 CDATA #REQUIRED
  颜色 CDATA #IMPLIED
>
对应XML文件:
<商品 类别="服装" 颜色="黄色">...</商品>
<商品 类别="服装">...</商品>

设置说明:
  #REQUIRED:必须设置该属性
  #IMPLIED:可以设置也可以不设置
  #FIXED:说明该属性的取值固定为一个值,在XML文件中不能为该属性设置其他值,但需要为该属性提供这个值。
  直接使用默认值:在XML中可以设置该值也可以不设置该属性值。若没设置则使用默认值。

举例:
<!ATTLIST 页面作者
  姓名 CDATA #IMPLIED
  年龄 CDATA #IMPLIED
  联系信息 CDATA #REQUIRED
  网站职务 CDATA #FIXED "页面作者"
  个人爱好 CDATA "上网"
>

<页面作者 联系信息="aaaa">
其中有三个属性,联系信息为一个,还有一个FIXED固定属性和一个默认属性。

常用属性值类型
CDATA:表示属性值为普通文本字符串。
ENUMERATED
ID
ENTITY(实体)

ENUMERATED
属性的类型可以是一组取值的列表,在XML文件中设置的属性值只能是这个列表中的某个值(枚举)

<?xml version="1.0" encoding="GB2312" standalone="yes" ?>
<!DOCTYPE 购物篮 [
    <!ELEMENT 肉 EMPTY>
    <!ATTLIST 肉 品种(鸡肉|牛肉|猪肉|鱼肉)"鸡肉">
]>
<购物篮>
    <肉 品种="鱼肉"/>
    <肉 品种="牛肉"/>
    <肉/>
</购物篮>


ID
表示属性的设置值为一个唯一值,同一个xml文档中不能重复出现,id最好不要用数字开头。
ID属性的值只能由字符,下划线开始,不能出现空白字符。

<?xml version="1.0" encoding="GB2312" ?>
<!DOCTYPE 联系人列表 [
    <!ELEMENT 联系人列表 ANY>
    <!ELEMENT 联系人(姓名,EMAIL)>
    <!ELEMENT 姓名(#PCDATA)>
    <!ELEMENT EMAIL(#PCDATA)>
    <!ATTLIST 联系人 编号 ID #REQUIRED>
]>

<联系人列表>
    <联系人 编号="1">
        <姓名>张三</姓名>
	<EMAIL>zhang@it315.org</EMAIL>
    </联系人>
    <联系人 编号="2">
        <姓名>李四</姓名>
	<EMAIL>li@it315.org</EMAIL>
    </联系人>
</联系人列表>


 

实体定义
使用用于为一段内容创建一个别名,以后在XML文档中就可以使用别名引用这段内容了。
在DTD定义中,一条<!ENTITY...>语句用于定义一个实体。
实体可分为两种类型:引用实体和参数实体。

引用实体
引用实体主要在XML文档中被应用
语法格式:
    <!ENTITY 实体名称 "实体内容">:直接转变成实体内容
引用方式:
  &实体名称:
举例:
  <!ENTITY copyright "I am a programmer">
  ......
  &copyright;

参数实体
参数实体被DTD文件自身使用
语法格式:
<!ENTITY % 实体名称 "实体内容" >
引用方式:
%实体名称;
举例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>

struts里action标签里面什么属性是必须设置的:path(查看源文档)

05-DTD案例
DTD代码是W3C SCHOOL中的案例。

<?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>
		<SPECIFICATIONS>aaaa</SPECIFICATIONS>
		<OPTIONS>aaaa</OPTIONS>
		<PRICE>aaaa</PRICE><!-- DTD中price不能精确地限定为数字,所以正在被schema取代 -->
		<NOTES>aaaa</NOTES>
	</PRODUCT>
</CATALOG>


 

06-xml解析概述和DOM&SAX解析原理
XML编程(CRUD)
create read update delete

XML解析方式分为两种:dom和sax
dom:(Document Object Model,即文档对象模型)是W3C组织推荐的解析XML的一种方式。
sax:(Simple API for XML)不是官方标准,但它是XML社区事实上的标准,几乎所有的XML解析器都支持它。

XML解析开发包
Jaxp(sun)、Jdom、dom4j

dom方式:
优点:增删改查容易;
缺点:容易导致内存溢出,不能用于大文件。

sax方式:
从上往下读,读一行处理一行。
优点:内存消耗小。
缺点:不适合做增删改查。

Dom和sax解析方法的区别:
1.dom解析的优点是对文档crud比较方便,缺点是占用内存比较大。
2.sax解析的优点是占用内存少,解析速度快,缺点是只适合做文档的读取,不适合做文档的crud。

07-调整JVM内存大小
假设拿到的xml文档100兆
-Xmx200m

08-xml解析技术概述和使用Jaxp对xml文档进行dom解析
Jaxp(sun)、Jdom、dom4j
效率依次提高
JAXP
JAXP开发包是J2SE的一部分,它由javax.xml、org.w3c.dom、org.xml.sax包及其子包组成.
在javax.xml.parsers包中,定义了几个工厂类,程序员调用这些工厂类,可以得到xml文档的DOM或SAX的解析器,从而实现对xml文档的解析。
javax.xml.parsers包中的DocumentBuilderFactory用于创建DOM模式的解析器对象,DocumentBuilderFactory是一个抽象工厂类,它不能直接实例化,但该类提供一个newInstance方法,这个方法会根据本地平台默认安装的解析器,自动创建一个工厂的对象并返回。

package cn.itcast.xml;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

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 Demo3 {
	@Test
	public void read1() throws Exception{
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse("src/book.xml");
		
		//读取xml文档
		NodeList list = document.getElementsByTagName("书名");
		Node node = list.item(1);
		
		String content = node.getTextContent();
		System.out.println(content);
	}
	
	//得到xml文档中的所有标签
	@Test
	public void read2() throws Exception{
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse("src/book.xml");
		
		//得到根结点
		Node root = document.getElementsByTagName("书架").item(0);
		list(root);
	}
	
	//得到xml文档中的标签属性的值
		@Test
		public void read3() throws Exception{
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document document = builder.parse("src/book.xml");
			
			Element bookname = (Element) document.getElementsByTagName("书名").item(0);
			String value = bookname.getAttribute("name");
			System.out.println(value);
		}
		
	private void list(Node node){
		if(node instanceof Element){
			System.out.println(node.getNodeName());
		}
		NodeList list = node.getChildNodes();
		for(int i=0;i<list.getLength();i++){
			Node child = list.item(i);
			list(child);
		}
	}

}
<?xml version="1.0" encoding="UTF-8" ?>
<书架>
    <书>
      <书名 name="xxxx">Java就业培训教程</书名>
	  <作者>张孝祥</作者>
	  <售价>39.00</售价>
    </书>
    <书>
      <书名>JavaScript网页开发</书名>
	  <作者>张孝祥</作者>
	  <售价>28.00</售价>
    </书>
</书架>


09-使用JAXP对XML文档进行DOM解析
更新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获得。

package cn.itcast.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.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class Demo3 {
	@Test
	public void read1() throws Exception{
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse("src/book.xml");
		
		//读取xml文档
		NodeList list = document.getElementsByTagName("书名");
		Node node = list.item(1);
		
		String content = node.getTextContent();
		System.out.println(content);
	}
	
	//得到xml文档中的所有标签
	@Test
	public void read2() throws Exception{
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse("src/book.xml");
		
		//得到根结点
		Node root = document.getElementsByTagName("书架").item(0);
		list(root);
	}
	
	//得到xml文档中的标签属性的值
	@Test
	public void read3() throws Exception{
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse("src/book.xml");
		
		Element bookname = (Element) document.getElementsByTagName("书名").item(0);
		String value = bookname.getAttribute("name");
		System.out.println(value);
	}
	
	//向xml文档中添加节点:<售价>59.00</售价>
	@Test
	public void add() throws Exception{
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse("src/book.xml");
		
		Element price = document.createElement("售价");
		price.setTextContent("59.00元");
		
		//把创建的节点挂到第一本书上
		Element book = (Element) document.getElementsByTagName("书").item(0);
		book.appendChild(price);
		
		//把更新后的内存写回到xml文档
		TransformerFactory tffactory = TransformerFactory.newInstance();
		Transformer tf = tffactory.newTransformer();
		tf.transform(new DOMSource(document), new StreamResult(new FileOutputStream("src/book.xml")));

	}	
	
	//向xml文档中指定位置上添加节点:<售价>59.00</售价>
	@Test
	public void add2() throws Exception{
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse("src/book.xml");
		
		Element price = document.createElement("售价");
		price.setTextContent("59.00元");
		
		//得到参考节点
		Element refNode = (Element) document.getElementsByTagName("售价").item(0);
		
		Element book = (Element) document.getElementsByTagName("书").item(0);
		
		book.insertBefore(price, refNode);
		
		//把更新后的内存写回到xml文档
		TransformerFactory tffactory = TransformerFactory.newInstance();
		Transformer tf = tffactory.newTransformer();
		tf.transform(new DOMSource(document), new StreamResult(new FileOutputStream("src/book.xml")));

	}	
	
	//向xml文档节点上添加属性: <书名 name="xxxx">Java就业培训教程</书名>上添加name="xxx"属性
	@Test
	public void addAttr() throws Exception{
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse("src/book.xml");
		
		Element bookname = (Element) document.getElementsByTagName("书名").item(0);
		bookname.setAttribute("name", "xxxxx");
		
		//把更新后的内存写回到xml文档
		TransformerFactory tffactory = TransformerFactory.newInstance();
		Transformer tf = tffactory.newTransformer();
		tf.transform(new DOMSource(document), new StreamResult(new FileOutputStream("src/book.xml")));
		
	}	
	
	@Test
	public void delete1() throws Exception{
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse("src/book.xml");
		
		//得到要删除的节点
		Element e = (Element) document.getElementsByTagName("售价").item(0);
		
		//得到要删除的结点的爸爸
		Element book = (Element) document.getElementsByTagName("书").item(0);
		
		//爸爸再删崽
		book.removeChild(e);
		
		//把更新后的内存写回到xml文档
		TransformerFactory tffactory = TransformerFactory.newInstance();
		Transformer tf = tffactory.newTransformer();
		tf.transform(new DOMSource(document), new StreamResult(new FileOutputStream("src/book.xml")));
	}
	
	//删除整个xml文档
	@Test
	public void delete2() throws Exception{
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse("src/book.xml");
		
		//得到要删除的节点
		Element e = (Element) document.getElementsByTagName("售价").item(0);
		e.getParentNode().getParentNode().getParentNode().removeChild(e.getParentNode().getParentNode());
		
		//把更新后的内存写回到xml文档
		TransformerFactory tffactory = TransformerFactory.newInstance();
		Transformer tf = tffactory.newTransformer();
		tf.transform(new DOMSource(document), new StreamResult(new FileOutputStream("src/book.xml")));
	}
	
	@Test
	public void update() throws Exception{
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse("src/book.xml");
		
		Element e = (Element) document.getElementsByTagName("售价").item(0);
		e.setTextContent("109元");
		
		//把更新后的内存写回到xml文档
		TransformerFactory tffactory = TransformerFactory.newInstance();
		Transformer tf = tffactory.newTransformer();
		tf.transform(new DOMSource(document), new StreamResult(new FileOutputStream("src/book.xml")));
	}
	
	private void list(Node node){
		if(node instanceof Element){
			System.out.println(node.getNodeName());
		}
		NodeList list = node.getChildNodes();
		for(int i=0;i<list.getLength();i++){
			Node child = list.item(i);
			list(child);
		}
	}

}


 

<?xml version="1.0" encoding="UTF-8" standalone="no"?><书架>
    <书>
      <书名 name="xxxxx">Java就业培训教程</书名>
	  <作者>张孝祥</作者>
	  
	  <售价>109元</售价>
    </书>
    <书>
      <书名>JavaScript网页开发</书名>
	  <作者>张孝祥</作者>
	  <售价>28.00</售价>
    </书>
</书架>


 

10-用xml作为持久化设备实现考生成绩管理系统
DOM方式解析XML文件
DOM解析编程
-遍历所有节点
-查找某一个节点
-删除结点
-更新结点
-添加节点
DOM编程练习

11-xml案例(考生成绩管理系统)


当要把异常当作一个返回值的时候,使用编译时异常,而其他情况使用运行时异常。

exam.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?><exam>
	<student examid="222" idcard="111">
		<name>张三</name>
		<location>沈阳</location>
		<grade>89</grade>
	</student>

	<student examid="444" idcard="333">
		<name>李四</name>
		<location>大连</location>
		<grade>97</grade>
	</student>
</exam>


Student.java

package cn.itcast.domain;

public class Student {
	public String getIdcard() {
		return idcard;
	}
	public void setIdcard(String idcard) {
		this.idcard = idcard;
	}
	public String getExamid() {
		return examid;
	}
	public void setExamid(String examid) {
		this.examid = examid;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getLocation() {
		return location;
	}
	public void setLocation(String location) {
		this.location = location;
	}
	public double getGrade() {
		return grade;
	}
	public void setGrade(double grade) {
		this.grade = grade;
	}
	private String idcard;
	private String examid;
	private String name;
	private String location;
	private double grade;
}


StudentDao.java

package cn.itcast.dao;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import cn.itcast.domain.Student;
import cn.itcast.exception.StudentNotExistException;
import cn.itcast.utils.XmlUtils;

public class StudentDao {
	public void add(Student s){
		try {
			Document document = XmlUtils.getDocument();
			
			//创建出封装学生信息的标签
			Element student_tag = document.createElement("student");
			student_tag.setAttribute("idcard", s.getIdcard());
			student_tag.setAttribute("examid", s.getExamid());
			
			//创建用于封装学生姓名,所在地和成绩的标签
			Element name = document.createElement("name");
			Element location = document.createElement("location");
			Element grade = document.createElement("grade");
			
			name.setTextContent(s.getName());
			location.setTextContent(s.getLocation());
			grade.setTextContent(s.getGrade()+"");
			
			student_tag.appendChild(name);
			student_tag.appendChild(location);
			student_tag.appendChild(grade);
			
			//把封装了信息学生标签,挂到文档上
			document.getElementsByTagName("exam").item(0).appendChild(student_tag);
			
			//更新内容
			XmlUtils.write2Xml(document);
		} catch (Exception e) {
			throw new RuntimeException(e);
			//unchecked exception(运行时异常)
		}  //checked exception(编译时异常)
	}
	public Student find(String examid){
		
		try {
			Document document = XmlUtils.getDocument();
			NodeList list = document.getElementsByTagName("student");
			for(int i=0;i<list.getLength();i++){
				Element student_tag = (Element) list.item(i);
				if(student_tag.getAttribute("examid").equals(examid)){
					//找到与examid相匹配的学生,new出一个student对象封装这个学生的信息返回
					Student s = new Student();
					s.setExamid(examid);
					s.setIdcard(student_tag.getAttribute("idcard"));
					s.setName(student_tag.getElementsByTagName("name").item(0).getTextContent());
					s.setLocation(student_tag.getElementsByTagName("grade").item(0).getTextContent());
					s.setGrade(Double.parseDouble(student_tag.getElementsByTagName("grade").item(0).getTextContent()));
					return s;
				}
			}
			return null;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	public void delete(String name) throws StudentNotExistException{
		try {
			Document document = XmlUtils.getDocument();
			
			NodeList list = document.getElementsByTagName("name");
			for(int i=0;i<list.getLength();i++){
				if(list.item(i).getTextContent().equals(name)){
					list.item(i).getParentNode().getParentNode().removeChild(list.item(i).getParentNode());
					XmlUtils.write2Xml(document);
					return;
				}
			}
			throw new StudentNotExistException(name + "不存在");
		}catch(StudentNotExistException e){
			throw e;
		} catch (Exception e) {
			throw new RuntimeException();
		}
		
	}
}


XmlUtils.java

package cn.itcast.utils;

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.w3c.dom.Document;

/*
 * 工具类方法要用static
 */
public class XmlUtils {
	
	private static String filename = "src/exam.xml";
	
	public static Document getDocument() throws Exception{
		
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		return builder.parse(filename);
	}
	public static void write2Xml(Document document) throws Exception{
		
		TransformerFactory factory = TransformerFactory.newInstance();
		Transformer tf = factory.newTransformer();
		tf.transform(new DOMSource(document), new StreamResult(new FileOutputStream(filename)));
	}
}


StudentNotExistException.java

package cn.itcast.exception;

public class StudentNotExistException extends Exception {

	public StudentNotExistException() {
		// TODO Auto-generated constructor stub
	}

	public StudentNotExistException(String message) {
		super(message);
		// TODO Auto-generated constructor stub
	}

	public StudentNotExistException(Throwable cause) {
		super(cause);
		// TODO Auto-generated constructor stub
	}

	public StudentNotExistException(String message, Throwable cause) {
		super(message, cause);
		// TODO Auto-generated constructor stub
	}

	public StudentNotExistException(String message, Throwable cause,
			boolean enableSuppression, boolean writableStackTrace) {
		super(message, cause, enableSuppression, writableStackTrace);
		// TODO Auto-generated constructor stub
	}

}


StudentDaoTest.java

package junit.test;

import org.junit.Test;

import cn.itcast.dao.StudentDao;
import cn.itcast.domain.Student;
import cn.itcast.exception.StudentNotExistException;

public class StudentDaoTest {
	@Test
	public void testAdd(){
		StudentDao dao = new StudentDao();
		Student s = new Student();
		s.setExamid("121");
		s.setGrade(89);
		s.setIdcard("121");
		s.setLocation("北京");
		s.setName("aa");
		dao.add(s);
	}
	
	@Test
	public void testFind(){
		StudentDao dao = new StudentDao();
		dao.find("121");
	}
	
	@Test
	public void testDelete() throws StudentNotExistException{
		StudentDao dao = new StudentDao();
		dao.delete("aa");
	}
}


Main.java

package cn.itcast.UI;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import cn.itcast.dao.StudentDao;
import cn.itcast.domain.Student;
import cn.itcast.exception.StudentNotExistException;

public class Main {
	public static void main(String[] args){
		try {
			System.out.println("添加学生(a) 删除学生(b) 查找学生(c)");
			System.out.println("请输入操作类型:");
			
			BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
			String type = br.readLine();
			
			if("a".equals(type)){
				System.out.println("请输入学生姓名:");
				String name = br.readLine();
				
				System.out.println("请输入学生准考证号:");
				String examid = br.readLine();
				
				System.out.println("请输入学生身份证号:");
				String idcard = br.readLine();
				
				System.out.println("请输入学生所在地:");
				String location = br.readLine();
				
				System.out.println("请输入学生成绩:");
				String grade = br.readLine();
				
				Student s = new Student();
				s.setExamid(examid);
				s.setGrade(Double.parseDouble(grade));
				s.setIdcard(idcard);
				s.setLocation(location);
				s.setName(name);
				
				StudentDao dao = new StudentDao();
				dao.add(s);
				
				System.out.println("添加成功");
			}else if ("b".equals(type)) {
				System.out.println("请输入要删除的学生姓名:");
				String name = br.readLine();
				
				try {
					StudentDao dao = new StudentDao();
					dao.delete(name);
					System.out.println("删除成功");
				} catch (StudentNotExistException e) {
					System.out.println("您要删除的用户不存在!!!");
				}
				
			}else if ("c".equals(type)) {
				
			}else{
				System.out.println("不支持您的操作!!");
			}
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("对不起,我出错了");
		}
	}

}


 

12-sax解析原理与案例
SAX解析 jaxp dom
在使用DOM解析XML文档时,需要读取整个XML文档,在内存中构架代表整个DOM树的Document对象,从而再对XML文档进行操作。此种情况下,如果XML文档特别大,就会消耗计算机的大量内存,并且容易导致内存溢出。

SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会对文档进行操作。

SAX解析
SAX解析采用事件处理的方式解析XML文件,利用SAX解析XML文档,涉及两个部分:解析器和事件处理器:
    解析器可以使用JAXP的API创建,创建出SAX解析器后,就可以指定解析器去解析某个XML文档。

    解析器采用SAX方式在解析某个XML文档时,它只要解析到XML文档的一个组成部分,都会去调用事件处理器的一个方法,解析器在迪欧诺个用事件处理器的方法时,会把当前解析到的xml文件内容作为方法的参数传递给事件处理器。

    事件处理器由程序员编写,程序员通过事件处理器中方法的参数,就可以很轻松地得到sax解析器解析到的数据,从而可以决定如何对数据进行处理。
阅读ContentHandler API文档,常用方法:startElement、endElement、characters

book.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?><书架>
    <书>
      <书名 name="xxxxx">Java就业培训教程</书名>
	  <作者>张孝祥</作者>
	  
	  <售价>109元</售价>
    </书>
    <书>
      <书名>JavaScript网页开发</书名>
	  <作者>张孝祥</作者>
	  <售价>28.00</售价>
    </书>
</书架>


Demo2.java

package cn.itcast.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.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

public class Demo2 {
	/**
	 *sax 解析 xml文档 
	 * @throws SAXException 
	 * @throws ParserConfigurationException 
	 * @throws IOException 
	 */
	public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException{
		//1.创建解析工厂
		SAXParserFactory factory = SAXParserFactory.newInstance();
		
		//2.得到解析器
		SAXParser sp = factory.newSAXParser();
		//3.得到读取器
		XMLReader reader = sp.getXMLReader();
		
		//4.设置内容处理器
		reader.setContentHandler(new TagValueHandler());
		//5.读取xml文档内容
		reader.parse("src/book.xml");
	}
}

//获取指定标签的值
class TagValueHandler extends DefaultHandler{
	
	private String currentTag; //记住当前解析到的是什么标签
	private int needNumber = 2;//记住想获取第几个作者标签的值
	private int currentNumber;//当前解析到的是第几个
	
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		currentTag = qName;
		if(currentTag.equals("作者")){
			currentNumber++;
		}
	}

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		currentTag = null;
	}

	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		if("作者".equals(currentTag) && currentNumber==needNumber){
			System.out.println(new String(ch,start,length));
		}
	}
}


13-sax解析案例(javabean封装xml文档数据)
book.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?><书架>
    <书>
      <书名 name="xxxxx">Java就业培训教程</书名>
	  <作者>张孝祥</作者>
	  
	  <售价>109元</售价>
    </书>
    <书>
      <书名>JavaScript网页开发</书名>
	  <作者>张孝祥</作者>
	  <售价>28.00</售价>
    </书>
</书架>


Demo3.java

package cn.itcast.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;

public class Demo3 {
	/**
	 *sax 解析 xml文档 
	 * @throws SAXException 
	 * @throws ParserConfigurationException 
	 * @throws IOException 
	 */
	@SuppressWarnings("unchecked")
	public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException{
		//1.创建解析工厂
		SAXParserFactory factory = SAXParserFactory.newInstance();
		
		//2.得到解析器
		SAXParser sp = factory.newSAXParser();
		//3.得到读取器
		XMLReader reader = sp.getXMLReader();
		
		//4.设置内容处理器
		BeanListHandler handle = new BeanListHandler();
		reader.setContentHandler(handle);
		//5.读取xml文档内容
		reader.parse("src/book.xml");
		
		List<Book> list = handle.getBooks();
		System.out.println(list);
	}
}

//把xml文档中的每一本数封装到一个book对象,并把多个book对象放在一个list集合中返回
class BeanListHandler extends DefaultHandler{
	
	private List list = new ArrayList();
	private String currentTag;
	private Book book;
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		currentTag = qName;
		if("书".equals(currentTag)){
			book = new Book();
		}
	}

	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		if("书名".equals(currentTag)){
			String name = new String(ch,start,length);
			book.setName(name);
		}
		if("作者".equals(currentTag)){
			String author = new String(ch,start,length);
			book.setAuthor(author);
		}
		if("售价".equals(currentTag)){
			String price = new String(ch,start,length);
			book.setPrice(price);
		}
	}
	
	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		if(qName.equals("书")){
			list.add(book);
			book = null;
		}
		currentTag = null;
	}

	public List getBooks() {
		return list;
	}
	

	
}


 

14-断点跟踪sax解析案例,分析程序问题

15-dom4j解析xml文档
Dom4j是一个简单、灵活的开放源代码的库。Dom4j是由早期开发JDOM的人分离出来而后独立开发的。与JDOM不同的是,dom4j使用接口和抽象基类,虽然Dom4j的API相对要复杂一些,但它提供了比JDOM更好地灵活性。

Dom4j是一个非常优秀的Java XML API,具有性能优异、功能强大和极易使用的特点。现在很多软件采用了Dom4j,例如Hibernate,包括sun公司自己的JAXM也用了Dom4j。

使用Dom4j开发,需下载dom4j相应的jar文件。
book.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?><书架>
    <书>
      <书名 name="xxxxx">Java就业培训教程</书名>
	  <作者>张孝祥</作者>
	  <售价>109元</售价>
    </书>
    <书>
      <书名 name="xxxxx">JavaScript网页开发</书名>
	  <作者>张孝祥</作者>
	  <售价>28.00</售价>
    </书>
</书架>


demo1.java

package cn.itcast.dom4j;

import java.io.File;
import java.io.FileWriter;

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

public class Demo1 {
	// 读取xml文档第二本书的:<书名>JavaScript网页开发</书名>
	@Test
	public void read() throws Exception {
		SAXReader reader = new SAXReader();
		Document document = reader.read(new File("src/book.xml"));

		Element root = document.getRootElement();
		Element book = (Element) root.elements("书").get(1);
		String value = book.element("书名").getText();
		System.out.println(value);
	}

	// 读取xml文档第二本书的:<书名 name="xxxxx">JavaScript网页开发</书名>
	@Test
	public void readAttr() throws Exception {
		SAXReader reader = new SAXReader();
		Document document = reader.read(new File("src/book.xml"));

		Element root = document.getRootElement();
		Element book = (Element) root.elements("书").get(1);
		String value = book.element("书名").attributeValue("name");
		System.out.println(value);
	}

	// 在第一本上添加一个新的售价: <售价>209元</售价>
	@Test
	public void add() throws Exception {
		SAXReader reader = new SAXReader();
		Document document = reader.read(new File("src/book.xml"));

		Element book = document.getRootElement().element("书");
		book.addElement("售价").setText("$209");

		// lets write to a file
		XMLWriter writer = new XMLWriter(new FileWriter("src/book.xml"));
		writer.write(document);
		writer.close();
	}
}


运行完出现乱码问题

<?xml version="1.0" encoding="UTF-8"?>
<���>
    <��>
      <���� name="xxxxx">Java��ҵ��ѵ�̳�</����>
	  <����>����</����>
	  <�ۼ�>109Ԫ</�ۼ�>
    <�ۼ�>209Ԫ</�ۼ�></��>
    <��>
      <���� name="xxxxx">JavaScript��ҳ����</����>
	  <����>����</����>
	  <�ۼ�>28.00</�ۼ�>
    </��>
</���>


16-dom4j保存数据的乱码问题
乱码不是dom4j的问题,而是sun公司io流的问题
FileWriter写的时候用的GB2312码表,不是UTF-8,但是FileWriter中没有可以指定编码方式的构造方法,所以不能使用。
book.xml

<?xml version="1.0" encoding="UTF-8"?>

<书架> 
  <书> 
    <书名 name="xxxxx">Java就业培训教程</书名>  
    <作者>张孝祥</作者>  
    <售价>109元</售价>  
  </书>  
  <书> 
    <书名 name="xxxxx">JavaScript网页开发</书名>  
    <作者>张孝祥</作者>  
    <售价>28.00</售价> 
  </书> 
</书架>


Deom1.java

package cn.itcast.dom4j;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;

import org.dom4j.Document;
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 Demo1 {
	// 读取xml文档第二本书的:<书名>JavaScript网页开发</书名>
	@Test
	public void read() throws Exception {
		SAXReader reader = new SAXReader();
		Document document = reader.read(new File("src/book.xml"));

		Element root = document.getRootElement();
		Element book = (Element) root.elements("书").get(1);
		String value = book.element("书名").getText();
		System.out.println(value);
	}

	// 读取xml文档第二本书的:<书名 name="xxxxx">JavaScript网页开发</书名>
	@Test
	public void readAttr() throws Exception {
		SAXReader reader = new SAXReader();
		Document document = reader.read(new File("src/book.xml"));

		Element root = document.getRootElement();
		Element book = (Element) root.elements("书").get(1);
		String value = book.element("书名").attributeValue("name");
		System.out.println(value);
	}

	// 在第一本上添加一个新的售价: <售价>209元</售价>
	@Test
	public void add() throws Exception {
		SAXReader reader = new SAXReader();
		Document document = reader.read(new File("src/book.xml"));

		Element book = document.getRootElement().element("书");
		book.addElement("售价").setText("209元");
		
		//格式化输入器
		OutputFormat format = OutputFormat.createPrettyPrint();
//		OutputFormat format = OutputFormat.createCompactFormat();
		format.setEncoding("UTF-8");

		// lets write to a file
		//使用字节流,不要使用字符流
		XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format);
//		XMLWriter writer = new XMLWriter(new FileWriter("src/book.xml"),format);
		writer.write(document);//UTF-8
		writer.close();
	}
}


17-dom4j解析xml文档(增删改查)
book.xml

<?xml version="1.0" encoding="UTF-8"?>

<书架> 
  <书> 
    <书名 name="xxxxx">Java就业培训教程</书名>  
    <作者>张孝祥</作者>  
    <售价>209元</售价> 
  </书>  
  <书> 
    <书名 name="xxxxx">JavaScript网页开发</书名>  
    <作者>活黎明</作者>  
    <售价>28.00</售价> 
  </书> 
</书架>


Demo1.java

package cn.itcast.dom4j;

import java.io.File;
import java.io.FileOutputStream;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
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;
import org.xml.sax.DocumentHandler;

public class Demo1 {
	// 读取xml文档第二本书的:<书名>JavaScript网页开发</书名>
	@Test
	public void read() throws Exception {
		SAXReader reader = new SAXReader();
		Document document = reader.read(new File("src/book.xml"));

		Element root = document.getRootElement();
		Element book = (Element) root.elements("书").get(1);
		String value = book.element("书名").getText();
		System.out.println(value);
	}

	// 读取xml文档第二本书的:<书名 name="xxxxx">JavaScript网页开发</书名>
	@Test
	public void readAttr() throws Exception {
		SAXReader reader = new SAXReader();
		Document document = reader.read(new File("src/book.xml"));

		Element root = document.getRootElement();
		Element book = (Element) root.elements("书").get(1);
		String value = book.element("书名").attributeValue("name");
		System.out.println(value);
	}

	// 在第一本上添加一个新的售价: <售价>209元</售价>
	@Test
	public void add() throws Exception {
		SAXReader reader = new SAXReader();
		Document document = reader.read(new File("src/book.xml"));

		Element book = document.getRootElement().element("书");
		book.addElement("售价").setText("209元");
		
		//格式化输入器
		OutputFormat format = OutputFormat.createPrettyPrint();
//		OutputFormat format = OutputFormat.createCompactFormat();
		format.setEncoding("UTF-8");

		// lets write to a file
		//使用字节流,不要使用字符流
		XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format);
//		XMLWriter writer = new XMLWriter(new FileWriter("src/book.xml"),format);
		writer.write(document);//UTF-8
		writer.close();
	}
	
	// 在第一本指定位置上添加一个新的售价: <售价>209元</售价> 更改list集合的顺序
	@Test
	public void add2() throws Exception {
		SAXReader reader = new SAXReader();
		Document document = reader.read(new File("src/book.xml"));

		Element book = document.getRootElement().element("书");
		List list = book.elements();//[书名,作者,售价]
		
		Element price = DocumentHelper.createElement("售价");
		price.setText("309");
		
		list.add(2, price);
		
		//格式化输入器
		OutputFormat format = OutputFormat.createPrettyPrint();
		format.setEncoding("UTF-8");

		XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format);
		writer.write(document);
		writer.close();
	}
	
	//删除上面添加的售价节点
	@Test
	public void delete() throws Exception{
		SAXReader reader = new SAXReader();
		Document document = reader.read(new File("src/book.xml"));
		
		Element price = document.getRootElement().element("书").element("售价");
		price.getParent().remove(price);
		
		OutputFormat format = OutputFormat.createPrettyPrint();
		format.setEncoding("UTF-8");

		XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format);
		writer.write(document);
		writer.close();
	}
	
	@Test
	public void update() throws Exception{
		SAXReader reader = new SAXReader();
		Document document = reader.read(new File("src/book.xml"));
		
		Element book = (Element) document.getRootElement().elements("书").get(1);
		book.element("作者").setText("活黎明");
		
		OutputFormat format = OutputFormat.createPrettyPrint();
		format.setEncoding("UTF-8");

		XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format);
		writer.write(document);
		writer.close();
	}
}


18-XPath提取xml文档数据
users.xml

<?xml version="1.0" encoding="UTF-8"?>
<users>
	<user id="1" username="aaa" password="123" email="aa@sina.com"/>
	<user id="2" username="bbb" password="123" email="aa@sina.com"/>
</users>


Deom5.java

package cn.itcast.sax;

import java.io.File;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

public class Demo5 {

	/**
	 * 查找users.xml文档是否有和用户相匹配的用户名和密码
	 * @throws DocumentException 
	 */
	public static void main(String[] args) throws DocumentException {
		String username = "aaa";
		String password = "123";
		
		//检测xml文档是否有匹配的用户名和密码
		SAXReader reader = new SAXReader();
		Document document = reader.read(new File("src/users.xml"));
		
		Node node = document.selectSingleNode("//user[@username='"+username+"' and @password='"+password+"']");
		if(node==null){
			System.out.println("用户名或密码错误!");
		}else{
			System.out.println("登陆成功");
		}
	}

}


 

19-schema技术详解
XML Schema
XML Schema也是一种用于定义和描述XML文档结构与内容的模式语言,其出现是为了克服DTD的局限性
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。

Schema约束快速入门
XML Schema文件自身就是一个XML文件,但它的扩展名通常为.xsd。
一个XML Schema文档通常称之为模式文档(约束文档),遵循这个文档书写的xml文件称之为实例文档。
和XML文件一样,一个XML Schema文档也必须有一个根结点,但这个根结点的名称为Schema。
编写了一个XML Schema约束文档后,通常需要把这个文件中声明的元素绑定到一个URI地址上,在XML Schema技术中有一个专业术语来描述这个过程,即把XML Schema文档声明的元素绑定到一个名称空间上,以后XML文件就可以通过这个URI(即名称空间)来告诉解析引擎,xml文档中编写的元素来自哪里,被谁约束。

book.xsd

<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.itcast.cn" elementFormDefault="qualified">//unqualified只是绑定根结点,而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>


book.xml

<?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:书架>


 

名称空间的概念
在XML Schema中,每个约束模式文档都可以被赋以一个唯一的名称空间,名称空间用一个唯一的URI(Uniform Resource Identifier,统一资源标识符)表示。在Xml文件中书写标签时,可以通过名称空间声明(xmlns),来声明当前编写的标签来自哪个Schema约束文档。如:
<itcast:书架 xmlns:itcast="http://www.itcast.cn">
 <itcast:书>......</itcast:书>
<itcast:书架>
此处使用itcast来指向声明的名称,以便后面对名称空间的引用。
注意:名称空间的名字语法容易让人混淆,尽管以http://开始,那个URI并不指向一个包含模式定义的文件。事实上,这个URL:http://www.itcast.cn根本没有指向任何文件,只是一个分配的名字。

使用名称空间引入Schema
为了在一个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的位置,两者之间用空格分隔。
注意,在使用schemaLocation属性时,也需要指定该属性来自哪里。

使用默认名称空间
基本格式:
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网页开发</书名>
		<作者>张孝祥</作者>
		<售价 demo:币种="人民币">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网页开发</书名>
		<作者>张孝祥</作者>
		<售价 demo:币种="人民币">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所指定的名称空间。

20-schema语法详解和案例
shiporder.xml

<?xml version="1.0" encoding="UTF-8"?>
	
<shiporder xmlns="http://www.itcast.cn" 
		   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
		   xsi:schemaLocation="http://www.itcast.cn shiporder.xsd"
		   orderid="111">
	<orderperson>xxx</orderperson>
	<shipto>
		<name>xxx</name>
		<address>xxx</address>
		<city>xxx</city>
		<country>xxx</country>
	</shipto>
	<item>
		<title>xxxx</title>
		<note>xxxx</note>
		<quantity>12</quantity>
		<price>0.1</price>
	</item>
</shiporder>


shiporder.xsd

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

	<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>


21一道打印M的面试题

package it.cast.demo;

public class Demo1 {
		/*
		   3    7
		  2 4  6 8
		 1    5   9
		 平面图形(二维数组)
		 */
	public static void main(String[] args) {
		int num = 13;
		
		int height = num/4+1;
		int width = num;
		
		int[][] arr = new int[height][width];
		
		int x = height-1;
		int y = 0;
		
		boolean order = false;
		for(int i=1;i<=num;i++){
			arr[x][y] = i;
			y++;
			
			if(order==false){
				x--;
			}
			if(order==true){
				x++;
			}
			
			if(x<0){
				order = true;
				x = x + 2;
			}
			if(x>height-1){
				order = false;
				x = x - 2;
			}
		}
		for(int i=0;i<arr.length;i++){
			for(int j=0;j<arr[i].length;j++){
				if(arr[i][j]==0){
					System.out.print("  ");
				}else{
					System.out.print(arr[i][j]);
				}
			}
			System.out.println();
		}
	}
}




 


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值