XML 的 DOM 解析范例:将XML用作数据库

1,建立 domain 类

Student.java

public class Student {
	public Student() {
		super();
	}

	public Student(String number,String name,String age,String sex) {
		super();
		this.number = number;
		this.name = name;
		this.age = age;
		this.sex = sex;
	}

	@Override
	public String toString() {
		return "Student [number=" + number + ",name=" + name + ",age=" + age
				+ ",sex=" + sex + "]";
	}

	public String getNumber() {
		return number;
	}

	public void setNumber(String number) {
		this.number = number;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	private String number;
	private String name;
	private String age;
	private String sex;
}
2,因为要将数据存储保存到XML文件中,而解析XML文件,或者将内存中的数据写入XML 文件都需要一些固定的解析格式,这时需要一个工具类,这就是简单的DomUtils.java

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.source;
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;

public class DomUtils {
	
	/**
	 * JAXP保存Document
	 * @param doc
	 * @param xmlName
	 */
	public static void saveDocument(Document doc,String xmlName){
		TransformerFactory factory = TransformerFactory.newInstance();
		try {
			Transformer transform = factory.newTransformer();
			
			//设置保存格式
			/**
			 * public abstract void setoutputProperty(String name,String value)
                                throws IllegalArgumentException设置转换中实际的输出属性。 
				以两部分字符串形式传递限定属性名称,即用花括号括起来的名称空间 URI,后跟本地名称。如果名称中有 null URL,则 String 只包含本地名称。应用程序可以通过测试安全地检查非 null URI,以查看名称的首字符是否为 '{' 字符。
				例如,如果 URI 和本地名称是从通过 <xyz:foo xmlns:xyz="http://xyz.foo.com/yada/baz.html"/> 定义的元素获取的,则限定名称将为 "{http://xyz.foo.com/yada/baz.html}foo"。注意,不使用前缀。
				传递给 setoutputProperties(java.util.Properties) 的 Properties 对象不会受到调用方法的影响。

				参数:
				name - 指定了输出属性名称的非 null String,它可以是名称空间限定的。
				value - 输出属性的非 null 字符串值。 
				抛出: 
				IllegalArgumentException - 如果不支持属性,且该属性没有限定于某一名称空间。
				另请参见:
				OutputKeys
				
			INDENT 
	          indent = "yes" | "no". indent 指定了当输出结果树时,Transformer 是否可以添加额外的空白;其值必须为 yes 或 no。
			 */
			transform.setoutputProperty(OutputKeys.INDENT,"yes");
			
			//Source实现此接口的对象包含充当源输入(XML 源或转换指令)所需的信息 
			Source source = new DOMSource(doc);
			//Result实现此接口的对象包含构建转换结果树所需的信息。
			Result outputTarget = new StreamResult(xmlName);
			transform.transform(source,outputTarget);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 获取Document对象
	 * @param xmlName
	 */
	public static Document getDocument(String xmlName){
		DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
		Document doc = null ;
		try {
			DocumentBuilder builder = builderFactory.newDocumentBuilder();
			doc = builder.parse(xmlName);
		} catch (Exception e) {
			throw new RuntimeException();
		}
		return doc;
	}
	
	/**
	 * 创建Document对象
	 * @return
	 */
	public static Document newDocument(){
		DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = null;
		try {
			builder = builderFactory.newDocumentBuilder();
			Document doc = builder.newDocument();
			doc.setXmlVersion("1.0");
			doc.setXmlStandalone(true);
			return doc;
		} catch (Exception e) {
			throw new RuntimeException();
		}
	}
}


3,如下是具体的dom规范解析xml过程

import java.util.LinkedList;
import java.util.List;

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

public class DomaAalyzeXml {
	/**
	 * 遍历Students.xml
	 */
	@Test
	public void traversalStudentXmltest() {
		// 获取Document对象
		Document doc = DomUtils.getDocument("src/students.xml");
		// 获取根元素
		Element root = doc.getDocumentElement();
		
		NodeList list = root.getElementsByTagName("student");
		for (int i = 0; i < list.getLength(); i++) {
//			Node node = list.item(i);
//			Element element = (Element) node;
			Element ele = (Element) list.item(i);
			//打印
			printElement(ele);
		}
		
		// 获取所有
//		NodeList list = root.getChildNodes();
//		/**
//		 * int getLength() 列表中的节点数。 
//		 * Node item(int index) 返回集合中的第 index 个项。
//		 */
//		for (int i = 0; i < list.getLength(); i++) {
//			Node node = list.item(i);
//			if (node.getNodeType() == node.ELEMENT_NODE) {
//				System.out.println(node.getNodeName() + ","
//						+ node.getNodeValue());
//			}
//		}
	}
	
	/**
	 * 给name为lisi元素添加<score>子元素
	 */
	@Test public void addChildNodetest(){
		Document doc =  DomUtils.getDocument("src/students.xml");
		Element root = doc.getDocumentElement();
		NodeList list = root.getElementsByTagName("student");
		for (int i = 0; i < list.getLength(); i++) {
			Element ele = (Element)list.item(i);
			String name = ele.getElementsByTagName("name").item(0).getTextContent();
			if(name.equals("lisi")){
				/**
				 * 1,创建<score>
				 * 2,给它添加文本元素
				 * 3,将<score>添加到ele中
				 * /
				Element scoreEle = doc.createElement("score");
				scoreEle.setTextContent("59.5");
				ele.appendChild(scoreEle);
				break;
			}
		}
		DomUtils.saveDocument(doc,"src/addChildNode.xml");
	}

	/**
	 * 为张三添加friend属性,指定为李四学号
	 * @param ele
	 */
	@Test public void addAttributetest(){
		Document doc = DomUtils.getDocument("src/students.xml");
		NodeList list = doc.getDocumentElement().getElementsByTagName("student");
		Element ls = null;
		Element zs = null;
		for (int i = 0; i < list.getLength(); i++) {
			Element ele = (Element)list.item(i);
			String name = ele.getElementsByTagName("name").item(0).getTextContent();
			if("zhangsan".equals(name)){
				zs = ele;
			}else if ("lisi".equals(name)) {
				ls = ele;
			}
			
			if(ls != null && zs != null){
				break;
			}
		}
		
		if(ls == null || zs == null){
			return;
		}
		
		//获取lisi的number属性
		String number = ls.getAttribute("number");
		//创建<friend>
		zs.setAttribute("friend",number);
		//保存
		DomUtils.saveDocument(doc,"src/addAttribute.xml");
	}
	
	/**
	 * 删除number为ID_1003的学生元素
	 */
	@Test public void deleteElementtest(){
		Document doc = DomUtils.getDocument("src/students.xml");
		Element root = doc.getDocumentElement();
		NodeList list = root.getElementsByTagName("student");
		for(int i = 0 ; i < list.getLength();i++){
			Element ele = (Element)list.item(i);
			String number = ele.getAttribute("number");
			if("N_1003".equals(number)){
				//获取其父节点,再通过父节点来删除当前节点
				ele.getParentNode().removeChild(ele);
			}
		}
		//保存
		DomUtils.saveDocument(doc,"src/deleteNode.xml");
	}
	
	/**
	 * 通过List<Student>生成Document并保存
	 */
	@Test public void testList2Document(){
		//得到Student的集合对象
		List<Student> stuList = getList();
		//创建Document
		Document doc = DomUtils.newDocument();
		//给当前文档添加根元素
		Element root = doc.createElement("students");
		
		//为root元素添加子元素及其属性
		/**
		 * 1,遍历Student集合对象,得到Student对象
		 * 2,将Student转换为Element
		 * 3,将元素添加到root中
		 */
		for (Student student : stuList) {
			Element ele = toElement(doc,student);
			root.appendChild(ele);
		}
		//将根元素添加到当前文档中
		doc.appendChild(root);
		DomUtils.saveDocument(doc,"src/student.xml");
	}

	/**
	 * 将Student转换为Element
	 * @param doc
	 * @param student
	 * @return
	 */
	private Element toElement(Document doc,Student stu) {
		Element student_tag = doc.createElement("student");//学生节点
		
		Element name = doc.createElement("name");
		Element age = doc.createElement("age");
		Element sex = doc.createElement("sex");
		
		 // 对Element各个属性赋值 
		student_tag.setAttribute("number",stu.getNumber());
		name.setTextContent(stu.getName());
		age.setTextContent(stu.getAge());
		sex.setTextContent(stu.getSex());
		
		 // 将各个属性添加到 student 对象 
		student_tag.appendChild(name);
		student_tag.appendChild(age);
		student_tag.appendChild(sex);
		return student_tag;
	}
		
	private List<Student> getList() {
		List<Student> list = new LinkedList<Student>();
		list.add(new Student("N_001","zhangSan","20","male"));
		list.add(new Student("N_002","liSi","21","female"));
		list.add(new Student("N_003","wangWu","22","male"));
		list.add(new Student("N_004","zhaoLiu","23","female"));
		list.add(new Student("N_005","chenQi","24","male"));
		return list;
		
	}
	private void printElement(Element ele) {
		String number = ele.getAttribute("number");
		String name = ele.getElementsByTagName("name").item(0).getTextContent();
		String age = ele.getElementsByTagName("age").item(0).getTextContent();
		String sex = ele.getElementsByTagName("sex").item(0).getTextContent();
		System.out.println(number + "--" + name + "-" + age + "-" + sex);
	}
}


4,下面是testList2Document()方法运行结果:

<?xml version="1.0" encoding="UTF-8"?><students>
<student number="N_001">
<name>zhangSan</name>
<age>20</age>
<sex>male</sex>
</student>
<student number="N_002">
<name>liSi</name>
<age>21</age>
<sex>female</sex>
</student>
<student number="N_003">
<name>wangWu</name>
<age>22</age>
<sex>male</sex>
</student>
<student number="N_004">
<name>zhaoLiu</name>
<age>23</age>
<sex>female</sex>
</student>
<student number="N_005">
<name>chenQi</name>
<age>24</age>
<sex>male</sex>
</student>
</students>



这里用的工具类只是简单的处理了,如果需要查看更加详细的dom4j的工具类方法,读者可以参考 Do4j,希望朋友多提宝贵意见。

相关文章

php输出xml格式字符串
J2ME Mobile 3D入门教程系列文章之一
XML轻松学习手册
XML入门的常见问题(一)
XML入门的常见问题(三)
XML轻松学习手册(2)XML概念