up:: Dom4j读取XML文档


一:需求:加入现在来了个新员工,如果利用Dom4j将新员工的信息,写入到XML文档中?

1.XML文档:这个可以不看,只是贴这儿了;

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- 人力资源管理系统 --><!--xmlns:xsi的意思是告诉XML文档,我们的约束是使用Schema;xsi:noNamespaceSchemaLocation:指向xsd文件 -->
    <hr xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:noNamespaceSchemaLocation="hr-schema.xsd">
    	<employee no="3306">   <!-- 标签和属性尽量起的有意义,做到见名知意 -->
    		<name>张三</name>
    		<age>31</age>
    		<salary>4000</salary>
    		<department>    <!-- 标签可以嵌套 -->
    			<dName>会计</dName>
    			<dAddress>4楼103室</dAddress>
    		</department>
    	</employee>
    	<employee no="3377">
    		<name>李四</name>
    		<age>29</age>
    		<salary>5000</salary>
    		<department>
    			<dName>工程部门</dName>
    			<dAddress>4楼105室</dAddress>
    		</department>
    	</employee>
    	<employee no="3346">
    		<name>李铁柱</name>
    		<age>35</age>
    		<salary>4300</salary>
    		<department>
    			<dName>行政部门</dName>
    			<dAddress>3楼301室</dAddress>
    		</department>
    	</employee>
    </hr>

2.XML Shema约束,xsd文件:这个可以不看,只是贴这儿了

 
    <?xml version="1.0" encoding="UTF-8"?>
    <schema xmlns="http://www.w3.org/2001/XMLSchema">
 
    	<element name="hr">    <!-- 声明根节点 -->
    		<complexType>       <!-- complexType标签的意思是复杂节点,包含子节点时,必须使用这个标签 -->
    			<sequence>     <!-- sequence是序列的意思,代表里面的子节点必须按照顺序书写 -->
    			 <!-- minOccurs="1":employee节点最少出现一次;maxOccurs="9999":employee节点最多出现9999次-->
    				<element name="employee" minOccurs="1" maxOccurs="9999">
    					<complexType>
    						<sequence>
    							<element name="name" type="string"></element> <!-- type="string":name节点的值只能是字符串; -->
    							<element name="age">
    								<simpleType><!-- 如年龄,要求在18-60之间; <simpleType>标签可以设置数值范围-->
    									<restriction base="integer"><!-- 这儿的base="integer"表示我们要限定范围的数据是整数-->
    										<minInclusive value="18"></minInclusive>
    										<maxInclusive value="60"></maxInclusive>
    									</restriction>
    								</simpleType>
    							</element> <!-- Schema高级的地方就是有了数据类型 -->
    							<element name="salary" type="integer"></element>
    							<element name="department">
    								<complexType>
    									<sequence>
    										<element name="dName" type="string"></element>
    										<element name="dAddress" type="string"></element>
    									</sequence>
    								</complexType>
    							</element>
    						</sequence>
    						 <!--在employee标签中有一个no属性,那么就在employee标签的那个 </complexType>标签位置上面设置attribute标签-->
    						  <!-- “required”代表必须的,即任何employee标签如果不写no属性,会报错 -->
    						<attribute name="no" type="string" use="required"></attribute>
    					</complexType>
    				</element>
 
    			</sequence>
    		</complexType>
    	</element>
 
    </schema>

3.追加的方法:(核心,这篇博客可以只看这儿)

(1)代码:本篇博客的核心,最重要的部分

利用Dom4j追加XML文档:以后记不清了,可以作为一个查阅、参考的备忘;熟能生巧,熟练了就好了;

 
    public class HrWriter {
 
    	public void writeXml() {
    		String file = "e:/eclipse-workspace/xml/src/hr-schema.xml";
    		//(1) SAXReader是读取XML文件的核心类,用于将XML解析后以“树”的形式保存在内存中。
    		SAXReader reader = new SAXReader();
    		try {
    			// (2) SAXReader类的主要方法时read()方法,该方法返回一个Document对象;
    			Document document = reader.read(file);
    			// (3) 获取XML文档的根节点;Dom4j中所有的标签都是用Element类型来进行的包装;
    			Element root = document.getRootElement();
    			// (4) 在根节点下,利用addElement()方法,创建一个新的“employee”子节点;这个方法返回这个新创节点的Element对象,以后续操作;
    			// 此后,在内存中,就有了一个新的空的“employee”节点(即一个空的Element对象)
    			Element employee = root.addElement("employee");
    			// (5) 给新创的employee节点,设置属性
    			employee.addAttribute("no", "3346");
    			// (6) 给新创的employee节点,添加“name”子节点
    			Element name = employee.addElement("name");
    			// (7) 给“name”子节点,设置文本;
    			name.setText("李铁柱");
    			employee.addElement("age").setText("35");
    			employee.addElement("salary").setText("4300");
    			// (7.1) 添加嵌套的子节点
    			Element department = employee.addElement("department");
    			department.addElement("dName").setText("行政部门");
    			department.addElement("dAddress").setText("3楼301室");
    			// (8) 上面设置完成后,代码一运行,就在内存中,构建出“李铁柱”这个员工节点,并追加到Document文档的最后;
    			// 但是,只在内存中是不行的,还要写到XML文件中去!
    			Writer writer = new OutputStreamWriter(new FileOutputStream(file),"UTF-8");  // 这个会抛FileNotFoundException异常
    			document.write(writer);  // 这个会抛 IOException;可以增加几个catch,也可以只抛一个Exception
    			writer.close();
 
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
 
    	public static void main(String[] args) {
    		new HrWriter().writeXml();
    	}
    }

(2)简单归纳:新的主要的东西有:

● Element employee = root.addElement(“employee”); 在根节点下,新加一个“employee”节点;

● employee.addAttribute(“no”, “3346”); 给新加的“employee”节点设置属性

● Element name = employee.addElement(“name”); 给“employee”节点,添加“name”子节点

● name.setText(“李铁柱”); 设置“name”子节点的值;

● Element department = employee.addElement(“department”); department.addElement(“dName”).setText(“行政部门”); 给“employee”节点添加“department”子节点;因为“department”还有子节点,所以,继续向“department”添加“dName”子节点;;;;

节点都是Element对象,这种标签的一级一级的嵌套, 可以给每个Element对象再设置Element对象(有点一个根节点,多条发散的树状链表的赶脚) ;而且这种一个套一个,套娃。。。。

● Writer writer = new OutputStreamWriter(new FileOutputStream(file),“UTF-8”); 建立输出流,utf-8保证中文;

document.write(writer); 内存中Document的内容,写到XML文件中去;然后发现,document的write()方法只有一个输出流参数的时候,默认是追加模式哎


效果:

(3)Eclipse格式化代码的方法:source→format:


(4)Dom4j并不负责XML的校验工作

(1)上述,代码,如果写的时候,有违反XML约束的地方,也会照写,Dom4j并不负责XML的校验工作(DTD || Schema);所以聪明做法是,每次写完后,在IDE中,打开XML文档,看是否有问题:

如果在IDE中发现了错误,提醒及时检查书写代码;或者核验约束规则;