Java操作XML详解

Java操作XML文件
一.下载Dom4j.jar包,复制至exjar文件夹中,并通过eclipse的building Path选项,配置class路径。
1.创建一个xml文件
假如我们需要创建如下的xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<website>
	<!--about my blog-->
	<domain type="blog">
		<url>hrmzone.cn</url>
		<catalog>computer</catalog>
	</domain>
	<author>hrmzone</author>
	<createdate>2009</createdate>
</website>

创建一个java源文件,命名为CreateXML.java,内容如下:

package cn.hrmzone.xml;
 
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
 
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.junit.Test;
 
/**
 * <p>2010-9-19</p>
 * @author <b>hrmzone.cn</b>
 *
 */
public class CreateXML {
 
	/**
	 * 
	 * @return 测试方法,无返回值
	 * 
	 */
	@Test
	public void testCreate() {
		// TODO Auto-generated method stub
		Document document=DocumentHelper.createDocument();
		Element siteElement=document.addElement("website");
		siteElement.addComment("about my blog");
		Element domainElement=siteElement.addElement("domain");
		domainElement.addAttribute("type", "blog");
		Element urlElement=domainElement.addElement("url");
		urlElement.setText("hrmzone.cn");
		Element catalogElement=domainElement.addElement("catalog");
		catalogElement.setText("computer");
		Element authorElement=siteElement.addElement("author");
		authorElement.setText("hrmzone");
		Element dateElement=siteElement.addElement("date");
		dateElement.setText("2009");
		OutputFormat format=OutputFormat.createPrettyPrint();
		try {
			XMLWriter output=new XMLWriter(new FileWriter(new File("output\\test.xml")),format);
			output.write(document);
			output.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
 
}


这里用到junit类进行测试,运行后,会在项目下的output文件夹中产生一个test.xml文件,打开之后会发现和之前需要创建的文件一致。现在对xml文件的创建进行说明:
创建一个xml文档的实例,DomcutmentHelper是生成xml文档节点的工厂类:

Document document=DocumentHelper.createDocument();

createDocument():是一个静态方法。
为创建的文档添加元素:

Element siteElement=document.addElement("website");

addElement:添加元素,其对象如果Document就是添加根元素,其对象如果是Element,那么就是添加子元素;
为根元素添加一个注释“about my blog”:

siteElement.addComment("about my blog");

同时为根元素添加子元素:domain、author、date

Element domainElement=siteElement.addElement("domain");Element authorElement=siteElement.addElement("author");Element dateElement=siteElement.addElement("date");

现在我想为domain元素添加一个属性:type,表面我网站的类型是blog:

domainElement.addAttribute("type", "blog");

Element.addAttribute():此方法为元素添加属性,内有两个参数,分别表示属性名称和值;
添加子元素的方法是一致,不论层次有多少,都是在上层元素上使用AddElement方法。
如果我需要为元素添加CDATA元素,就是字符元素,为computer、author、date三个元素添加文本:

catalogElement.setText("computer");authorElement.setText("hrmzone");dateElement.setText("2009");

Element.setText():为元素增加文本
至此为止,已经将xml的元素和内容建立,接下来需要将其保存到test.xml文件中。创建一个XMLWriter对象,其参数FileWriter类型,如果这样直接保存的话,产生的xml文件是一种紧凑型,就是说所有的元素、内容均在一行,如果需要产生层次分明的文档,需要创建一个OutputFormat对象,并作为参数加入到XMLWriter中:
OutputFormat format=OutputFormat.createPrettyPrint();
try {
XMLWriter output=new XMLWriter(new FileWriter(new File(“output\\test.xml”)),format);
output.write(document);
output.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

注意:在结束时应关闭XMLWriter。
二.读取xml文档
1.读取xml文档
xml文档的也是一个文件,所以读取一个xml文件和读取一个其他的普通文件是一样的,需要先创建一个File,指定将被读取的文件。在创建一个xml文件时,是使用DocumentHelper类,注意,读取则不一样,是使用SAXReader类。如:

/**
 * 
 */
package cn.hrmzone.xml;
 
import java.io.File;
import java.util.Iterator;
import java.util.List;
 
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
 
/**
 * @author hrmzone.cn
 *2010-9-19
 */
public class ReaderXML {
 
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		File file=new File("output\\test.xml");
		SAXReader reader=new SAXReader();
		try {
			Document doc=reader.read(file);
			Element root=doc.getRootElement();
			for(Iterator iter=root.elementIterator();iter.hasNext();) {
				Element element=(Element) iter.next();
				System.out.println(element.getName()+"\t:"+element.getStringValue());
			}
 
 
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			System.out.println("有异常抛出");
			e.printStackTrace();
		}
	}
 
}

解释过程:
根据文件名创建一个File

File file=new File("output\\test.xml");

创建一个SAXReader实例,他可以用来读取文件

SAXReader reader=new SAXReader();

通过SAXReader的reader方法读取文件:

Document doc=reader.read(file);

载入文件之后,就可以对xml的元素、属性等进行读取了,for循环语句即为获取所有元素节点的元素名称和属性值

for(Iterator iter=root.elementIterator();iter.hasNext();) {
				Element element=(Element) iter.next();
				System.out.println(element.getName()+"\t:"+element.getStringValue());
			}

2.读取xml文档中的元素、属性
以上的循环只能从根节点通过迭代的方式,逐渐来访问其子节点和属性,那么,如果需要直接访问某个节点或者某个已知名称的属性呢,有没有快捷的方法呢。毫无疑问,当然有这种便捷方式来,就是通过XPath来访问指定的元素、属性,如下代码:

/**
 * 
 */
package cn.hrmzone.xml;
 
import java.io.File;
import java.util.Iterator;
import java.util.List;
 
import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.junit.Before;
import org.junit.Test;
 
/**
 * @author hrmzone.cn
 *2010-9-26
 */
public class XMLTest {
	File file;
	Document doc;
	OutputFormat format;
	Logger logger;
 
	@Before
	public void init() {
		file=new File("output\\test.xml");
		format=OutputFormat.createPrettyPrint();
		logger=Logger.getLogger(XMLTest.class);
		DOMConfigurator.configure("bin\\cn\\hrmzone\\xml\\Log4J.xml");
	}
 
	@Test
	public void testRead() {
		logger.debug("test starting");
		try {
			doc=new SAXReader().read(file);
			Element root=doc.getRootElement();
//			选取所有匹配domain的元素,而不考虑domain的位置所在
			List<Element> l1=doc.selectNodes("//domain/url");
			for(Iterator<Element> iter=l1.iterator();iter.hasNext();) {
				Element e=iter.next();
				System.out.println(e.getName());
			}
 
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			System.out.println("无法加载文件");
			e.printStackTrace();
		}
	}
}

输出结果为url,即输出匹配的domain的子元素url的元素名。(这个测试类中使用了Log4j的相关知识,如果不了解Log4j,可以删除相关的内容,可以正常执行。
//:表示从当前元素节点开始搜索,知道匹配

List<Element> l1=doc.selectNodes("//domain/url");

XPath另有很多表达式,介绍几个可以常用的:
@:表示选取元素的属性,如“//domain/@type”,即需找名为domain,属性为type的属性。
/:从根节点开始选取,如:“/weisite/author”,从根节点开始需找。
仅为元素名:选取所有此元素名的子节点,如“domain”,选取了url,catalog节点。
XPath还有很多强大的表达式,这里就不一一介绍。
强调一点,XPath需要导入另外一个jar包,而不仅仅在class path中导入dom4j就行了。这个jar包在下载的dom4j的lib目录下,包名为:jaxen-1.1-beta-6,如果没有导入此包,使用XPath是会报异常,如下:

Exception in thread "main" java.lang.NoClassDefFoundError: org/jaxen/JaxenException

ok,读取、创建xml文档就是这么简单。
XML基础知识
一.XML文档的组成
1.XML声明

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

encoding为文档编码类型
2.文档类型声明
在XML中引入DTD定义
DTD:Document Type Definition,解释器会根据DTD检验文档结构是否正确。
3.元素
XML中元素由开始标签、元素内容和结束标签构成;对于空元素,由空元素标签构成。
元素有4中类型:空元素、带有属性的元素、带有内容的元素和带有内容和属性的元素
注意:元素和标签的区别:
元素是指开始标签、结束标签以及两者之间的内容,包括文本、属性、注释及子元素
标签是一对尖括号(<>)和两者之间的内容,包括元素名和所有属性
元素的构成:子元素、字符数据、字符引用、实体引 用和CDATA段
元素内容不可以有和号(&)和小于号(<),也不能有字符串"]]>"。
如果需要使用这些字符,需要使用其预定义实体引用:

<    &lt; 
>    &gt; 
"    &quot; 
'     &apos; 
&    &amp;

(注:都是带分号的)
元素 CDATA段,包含的都是纯字符数据。不被XML解析 ,相当是引用。

 <?xml version="1.0" encoding="utf-8"?>        
 <java>    
   <![CDATA[   
     if(a>b) && c<d){   
       max=a;   
     }   
   ]]>    
 </java> <

上面代码中的java代码段不会被xml解析,以原始代码的形式呈现。但是,CDATA的内容可以有不包括"]]>"的任意字符串,如下代码:

 <?xml version="1.0" encoding="utf-8"?>    
 
 <java>    
   <![CDATA[   
     if(array[num[i]]>1){     
       func();     
     }     
   ]]>    
 </java>

因为Java代码中有这样的字符串"]]>"提前的结束了CDATA。可以再其后加一个空格,也可以分开到两个CDATA段中来写。
4.注释
在XML文档中,注释可以出现在标记之外的还有文档声明语法允许的任意位置。
注释标记 ,注释内部的数据会被XML解析器忽略。
要点:
a:注释不能出现在XML声明之前;
b:不能出现在标记中;>>hello world,这时不允许的;
c:注释要保证注释外的XML文档是结构完整的;
d:注释内容中间不能出现双联字符--;
e:注释不能以三联字符---结尾;
5.处理指令
处理指令(Processing Instructions)允许文档中包含由应用程序来处理的指令。在XML文档中,有可能会包含一些非XML格式的数据,这些数据XML处理器无法处 理,我们就可以通过处理指令通知其他应用程序来处理这些数据
结束。如:

<?xml-stylesheet href="hello.css" type="text/css"?>

xml-stylesheet叫做处理指令目标,他必须表示要用到的应用程序,对于非W3C定义的处理指令不能以XML开头。其余的部分是是传递给应用程 序的字符数据。
6.总结
XML与HTML在标记语言中处于不同的层次;
XML将数据和显示分开;
开始标签必须要有一个结束标签;
   空元素标签必须被关闭;
   所有标签必须区分大小写;
   所有标签必须成对出现、合理嵌套;
   所有标签的属性必须用双引号""或单引号''括起来;
   XML中有且只有一个根元素。
在 XML规范中,空白包括空格,制表符和空行

二.DTD内容
文档 类型声明必须位于XML声明之后,且在根元素(文档元素)之前。不过在XML声明和文档类型之间可以插入注释和处理指令。
外部引用DTD文档:

<!-- 外部 文件中引用XML -->  
<!DOCTYPE greeting SYSTEM "hello.dtd">  

引用外部DTD文档,在文档类型声明时,用关键字SYSTEM或PUBLC来指出外部DTD文件的位置 。可以通过SYSTEM、PUBLIC来引入外部文档。

<!DOCTYPE 根元素的名字 SYSTEM "外部DTD文件的URI">
<!DOCTYPE 根元素的名字 PUBLC "DTD的名称" "外部DTD文件的URI">

直接在xml文档中给出DTD

<!-- 直接 在XML文档中给出DTD -->  
<?xml version="1.0" encoding="utf-8"?>  
<!DOCTYPE greeting[  
<!ELEMENT greeting(#PCDATA)>  
]>  

DTD文档的结构
1.元素类型声明
元素类型声明说明了每个文档可能存在的元素,给出了元素的名称,而且给出了元素的具体类型

<!ELEMENT 元素名称 元素内容说明>

元素内容说明:#PCDATA、子元素、混合内容、EMPTY和ANY
#PCDATA 说明元素包含字符数据

	<?xml version="1.0" encoding="utf-8"?>  
<!DOCTYPE hr[  
<!ELEMENT hr(#PCDATA)>  
]>  
<hr>人力资源标准</hr>  

子元素:当一个元素只包含子元素,而没有字符数据时,称此元素类型具有元素型内容(element content)
在该类型的元素声明时,通过内容模型来制定在其内容上的约束。内容模型是决定子元素类型和子元素出现顺序的一种简单语法

 <?xml version="1.0" encoding="utf-8"?>  
 <!DOCTYPE company [ 
 <!ELEMENT company (employee)> 
 <!ELEMENT employee (name,age,sex,salary,interest+,spouse?)> 
 <!ELEMENT name (PCDATA)> 
 <!ELEMENT age (PCDATA)> 
 <!ELEMENT sex (PCDATA)> 
 <!ELEMENT salary (cash | credit_card)> 
 <!ELEMENT cash (PCDATA)> 
 <!ELEMENT credit_card (PCDATA)> 
 <!ELEMENT interest (PCDATA)> 
 <!ELEMENT spouse (PCDATA)> 
 ]> 
 <company> 
 <employee> 
 <name>魁魁</name> 
 <age>22</age> 
 <sex></sex> 
 <salary> 
 <cash>6000.00</cash> 
 </salary> 
 <interest>武术</interest> 
 <interest>健美</interest> 
 <spouse>飞雪</spouse> 
 </employee> 
 </company>

上面的interest+,spouse?分别代表interest至少有一 个,spouse有零个或者一个。还有一个*号,代表零个或多个,不限定个数
在使用混合内容模型时,#PCDATA必须作为第一个选项,并且只能使用竖线。

employee (#PCDATA | name)*

说明了employee有零个或多个#PCDATA或name。
EMPTY:表明该元素既不包含字符数据,也不包含子元素,是一个空元素。
如果在文档中元素本身已经表示了明确的含义,就可以在DTD中用关键字 EMPTY来表明空元素。例如:

<!ELEMENT br EMPTY>

表明br是一个没有内容的空元素。
ANY:表明该元素可以包含任意的字符数据和子元素,只要规范即可。例如:

<!ELEMENT br ANY>

表明employee可以包含任何形式的内容。
实体声明
有时候在多个文档中调用同样的内容,我们可以声明一个实体来表示这个内容,在文档中引用这个实体。
两种内容的实体:一般实体和参数实体。都用ENTITY声明。
一般实体是在文档内容中使用的的实体;
参数实体是在DTD中使用的已分析实体
一般实体:声明语法: 引用方式:"&实体名"。
如下:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE website [
<!ELEMENT website (name,copyright)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT copyright (#PCDATA)>
<!ENTITY name "程序员之家">
<!ENTITY copyright "&#169;, 2005, 程序员之家, All Rights Reserved">
]>
<website>
	<name>&name;</name>
	<copyright>&copyright;</copyright>
</website>

参数实体:只能在DTD中使用,语法如下:

<!ENTITY %  实体名 "实体内容">

注意声明时ENTITY和%之间有空格,引用实体的方式为:%实体名;。
例子如下:

<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT website (name,copyright)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT copyright (#PCDATA)>
<!ENTITY % name "程序员之家">
<!ENTITY copyright "&#169;2005 %name; All Right Reserved">

因为参数实体只能在DTD中引用,所以要单独创建DTD文件。
在内部DTD子集中,参数实体引用不能在标记声明内部出现,可以在标记声明允许出现的地方出现。对于外部DTD子集,没这个限制。在DTD中,所有参数实体必须在引用之前进行声明。这意味着内部DTD子集不能引用在外部DTD中声明的参数实体,这是因为XML处理器将首先读取内部子集,也就是说,内部子集中的实体和属性表明的优先级要高于外部子集。

内部实体在XML文档内部定义,实体的内容在声明中输出。内部实体都是已分析的实体,他们没有单独的物理存储对象。
外部实体在单独的(外部)文件中定义,外部实体可以使已分析的实体,也可以是未分析的实体。外部一般实体声明形式如下:

<!ENTITY copyright SYSTEM "http://www.ghk.com/copyright.xml">

关键字SYSTEM表明这是一个私有的外部一般实体,后面的URI称为该实体的系统标识符,用于给出外部文件的位置。
属性表声明
属性用于将名字-值对与元素进行关联。属性说明只能在开始标签和空元素标签中出现。属性表声明详细说明了与给定元素类型相关联的每一个属性的名字,数据类型和缺省值(如果有的话)。
声明格式如下:

<!ATTLIST 元素名 属性名 属性类型 缺省声明>

元素名是属性所属的元素的名字,属性名是属性的命名,属性类型则用来制定该属性是属于哪种类型,共有十种类型,缺省声明用于说明在元素中该属性是否必须出现,如果不是必须出现,那么当该属性没有出现时,XML处理器该如何处理
缺省声明有四种缺省设置:#REQUIRED、#IMPLIED、#FIXED和缺省值、只有缺省值。
REQUIRED:必须为元素提供该属性。
如下:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE bbs [
<!ELEMENT bbs (article)*>
<!ELEMENT article (title,author)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ATTLIST author ip CDATA #REQUIRED>
]>
<bbs>
	<article>
		<title>关于属性表声明的问题</title>
		<author ip="192.168.0.1">张三</author>
	</article>
	<article>
		<title>关于XML应用的问题</title>
		<author ip="192.168.0.11">李四</author>
	</article>
</bbs>

如果我把其中的一个ip去掉不加,就会报错,因为#REQUIRED是必须有的意思。另外 CDATA代表字符串。
#IMPLIED:可以包含,也可以不包含。
#FIXED和缺省值:说明一个固定的属性缺省值,文档的编写者不能修改该属性的值。如果元素中不包含这个属性,XML处理器将以声明的缺省值向应用程序报告该属性。
例子如下:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE bbs [
<!ELEMENT bbs (article)*>
<!ELEMENT article (title,author)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ATTLIST author ip CDATA #IMPLIED>
<!ATTLIST article copyright CDATA #FIXED "版权论坛所有">
]>
 
<bbs>
	<article>
		<title>关于属性表声明的问题</title>
		<author>张三</author>
	</article>
	<article>
		<title>关于XML应用的问题</title>
		<author ip="192.168.0.11">李四</author>
	</article>
</bbs>

只有缺省值:和上面的那个类似,只不过属性值可以改变的。
例子

<?xml version="1.0" encoding="utf-8"?>
 
<!DOCTYPE bbs [
<!ELEMENT bbs (article)*>
<!ELEMENT article (title,author)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ATTLIST author ip CDATA #IMPLIED>
<!ATTLIST article copyright CDATA #FIXED "版权论坛所有">
<!ATTLIST article style CDATA "txt">
]>
 
<bbs>
	<article>
		<title>关于属性表声明的问题</title>
		<author>张三</author>
	</article>
	<article style="html">
		<title>关于XML应用的问题</title>
		<author ip="192.168.0.11">李四</author>
	</article>
</bbs>

另外,可以把这两行

<!ATTLIST article copyright CDATA #FIXED "版权论坛所有">
<!ATTLIST article style CDATA "txt">

合并为一行

<!ATTLIST article copyright CDATA #FIXED "版权论坛所有" style CDATA "txt">

效果是一样的。
属性类型:属性表声明类型时,一共有十种类型可以选择:
CDATA、Enumerated、ID、IDREF、IDREFS、ENTITY、ENTITIES、NMTOKEN、 NMTOKENS、NOTATION。
CDATA:最常用的一种属性类型,表明属性值为字符类型数据,与元素内容说明中的#PCDATA一样。特殊字符要与定义实体引用或字符引用。
Enumerated:枚举类型,在声明属性时,可以限定属性的取值范围,举例如下:

<!ATTLIST person sex (male | female) #REQUIRED>

枚举元素用竖线隔开。
ID、IDREF、IDREFS:
一个ID类型的属性唯一标识XML文档中的一个元素;
一个ID 类型的属性值必须遵守XML名称定义的规则;
一个元素只能有一个ID类型的属性,ID类型的属性必须设置为#IMPLIED或者#REQUIRED。
例子:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE company [
<!ELEMENT company (employee*)>
<!ELEMENT employee (name)>
<!ELEMENT name (#PCDATA)>
<!ATTLIST employee sn ID #REQUIRED>
]>
 
<company>
	<employee sn="E-20020511601">
		<name>张三</name>
	</employee>
 
	<employee sn="E-20020511602">
		<name>李四</name>
	</employee>
</company>

IDREF类型的属性值必须是统一文档中另一个元素的ID类型的属性值,而这另一个元素的ID类型的属性值必须是已经存在的。
利用 ID和IDREF这两种类型的属性,我们可以在两个对象之间建立一种关联关系。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE company [
<!ELEMENT company (employee | manager)*>
<!ELEMENT employee (name)>
<!ELEMENT manager EMPTY>
<!ELEMENT name (#PCDATA)>
<!ATTLIST employee sn ID #REQUIRED>
<!ATTLIST manager mgrid IDREF #REQUIRED>
]>
<company>
	<employee sn="E-20020511601">
		<name>张三</name>
	</employee>
 
	<employee sn="E-20020511602">
		<name>李四</name>
	</employee>
	<manager mgrid="E-20020511601"/>
</company>

张三实际上是这个公司的经理。
也可以这样修改:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE company [
<!ELEMENT company (employee*)>
<!ELEMENT employee (name)>
<!ELEMENT manager EMPTY>
<!ELEMENT name (#PCDATA)>
<!ATTLIST employee sn ID #REQUIRED>
<!ATTLIST employee manager IDREF #IMPLIED>
]>
<company>
	<employee sn="E-20020511601">
		<name>张三</name>
	</employee>
 
	<employee sn="E-20020511602" manager="E-20020511601">
		<name>李四</name>
	</employee>
 
	<employee sn="E-20020511603" manager="E-20020511601">
		<name>王五</name>
	</employee>
</company>

如果一个属性需要引用文档中多个ID类型的属性值,那么可以把它声明为具有IDREFS 类型:
IDREFS类型的属性值是一系列以空格分隔的ID类型的属性值,而且必须与文档中已有的ID类型属性值相匹配。

 <?xml version="1.0" encoding="utf-8"?>  
<!DOCTYPE library [  
 <!ELEMENT library (books,records)>  
 <!ELEMENT books (book+)>  
<!ELEMENT book (#PCDATA)>  
<!ELEMENT records (item*)>  
 <!ELEMENT item (data,person)>  
<!ELEMENT data (#PCDATA)>  
<!ELEMENT person EMPTY>  
 <!ATTLIST book bookid ID #REQUIRED>  
<!ATTLIST person name CDATA #REQUIRED>  
<!ATTLIST person borrowed IDREFS #REQUIRED>  
 ]>  
   <library>  
     <books>  
        <book bookid="b-1-1">XML详解</book>  
         <book bookid="b-1-2">Servlet从入门到精通</book>  
        <book bookid="b-1-3">JSP实例编程</book>  
    </books>  
     <records>  
        <item>  
             <data>2009-05-05</data>  
             <person name="张三" borrowed="b-1-1 b-1-2"></person>  
         </item>  
         <item>  
             <data>2009-05-12</data>  
            <person name="李四" borrowed="b-1-1 b-1-2 b-1-3"></person>  
         </item>  
     </records>  
 </library>

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">

Go back to top