【Program With Soul】XML文件与DOM4J初步认识

前端之家收集整理的这篇文章主要介绍了【Program With Soul】XML文件与DOM4J初步认识前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

XML与DOM4J

1.XML —— Extensible Markup Language ( 可扩展标记语言 )

在实际开发中,每种语言都有自己的用途,好比如:

①:HTML 在网页中合理地编排数据,使数据更有条理地展现

②:CSS 添加更多视觉效果,使得网页的显示效果更佳丰富

③:JS用作网页的逻辑处理,使得程序能与用户产生交互

而XML纯粹用于存储或传输数据,而不是用来显示数据的,它不做任何逻辑行为

2.XML基本语法规则

我们可以发现XML和HTML很像,都是使用标签,但有一点不同:

HTML的标签是固定好的,只能使用该语言自带标签属性,而XML可以自定义标签属性

XML的基本内容— — 文档声明、标签元素、属性、注释、文本内容

格式注意事项:

①:每对标签都要成对出现

②:标签属性名都区分大小写

③:标签之间的嵌套关系要正确

④:键值对之间用 "=" 隔开,而且两边不能有空格,属性值用双或单引号括住

⑤:文档声明必须要有,并且要写在XML文件第一行

⑥:根元素<根标签> 有且仅有一个,其他子元素都要嵌套在里面

基本内容示例:

文档声明 <?xml version="1.0" encoding="utf-8"?>

注释<!-- 注释 -->

属性 <person id="10004"></person> id就是属性

标签 <person></person>

3.DOM4J -- Document Object Model ( 文档对象模型 )

XML文件在内存中表示就是一棵树,简称DOM树,我们可以通过 DOM4J这个API来读写XML文件

说到树,就不得不提数据结构,学过数据结构都知道内存中的树模型,是由一个个节点组成的。正好,DOM树也是由节点组成的,而每个节点都代表着一个标签

比如以下的XML文件

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

<person-list>

	<!-- 联系人的信息 -->
	<person id="10004">
		<name>狂人</name>
		<gender>男</gender>
		<phone>1364499123</phone>
		<qq>1238645</qq>
		<email>1238645@qq.com</email>
	</person>

	<!-- 联系人的信息 -->
	<person id="10005">
		<name>张三</name>
		<gender>男</gender>
		<phone>1378574765</phone>
		<qq>64593435</qq>
		<email>64593435@qq.com</email>
	</person>

</person-list>

DOM4J中的 Node类 与以下几个类存在着 is-a 的关系

Node ( 节点 )

-- Document 文档声明

-- Element 标签元素 <person-list></person-list> <person></person> <name></name>等

-- Attribute属性 person标签中的id

-- Text 文本 XML中的空格或者换行、标签对之前的文本

-- Comment 注释 <!-- -->之前的内容

-- ......

因此,只要我们得DOM树中的节点,就能得到XML文件所有的信息。

每个Element对象包含着元素名、附带属性、父元素、子元素、兄弟元素等信息,而它又能获得其所有子节点的信息,所以,我们也可以首先得到根元素,然后得到其子节点的迭代器,遍历所有子节点。

我们可以使用 dom4j.jar 中所包含的各种工具来解析XML文件,得到DOM树后并对它进行各种操作。

其中,我们经常要使用到的类有:

①:SAXReader -- Simple API for XML XML解析器

②:Document

③:Element

④:Text

⑤:Attribute

⑥:Comment

SAXReader saxReader = new saxReader();
Document document = saxReader.read("XML文件路径");
Element element = document.getRootElement();

通常,都是以这种方式得到XML文件的整个文档与根元素的,接着我们就能很好地操作内部的数据了。

下面是读取XML并递归遍历所有元素和打印XML文件的例子:

package mdk.dom4j_tree;

import java.net.URL;
import java.util.Iterator;

import org.dom4j.Attribute;
import org.dom4j.Comment;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.Text;
import org.dom4j.io.SAXReader;

public class Print_XmlInfo {

	
	public static void main(String[] args) throws Exception
	{
		// 创建xml解析器
		SAXReader saxReader = new SAXReader();
		// 从该字节码所在的包中查找my_data.xml这个 文件
		URL resource = Print_XmlInfo.class.getResource("my_data.xml");
		// 获得某个xml文件的document对象
		Document document = saxReader.read( resource );
		// 获得文档中的根元素
		Element rootElement = document.getRootElement();
		
		System.out.println("------------xml文件元素内容-------------");
		showElements(rootElement);
		
		System.out.println("------------xml文件文本内容-------------");
		StringBuilder sb = new StringBuilder();
		showElements2( rootElement,sb );
		System.out.println( sb.toString() );	
	}
	
	// 递归显示xml文件整个文档的所有标签元素
	public static void showElements( Element element )
	{
		// 显示当前元素
		System.out.println( element );
		
		for ( Iterator<Element> elementIterator = 
				element.elementIterator(); elementIterator.hasNext(); )
			showElements( elementIterator.next() );	
	}
	
	// 递归遍历根元素中的所有节点并将所有信息打印出来 
	public static void showElements2( Element element,StringBuilder sb )
	{
		// 拼接元素标签信息
		sb.append("<").append( element.getName() );
		for ( int i = 0; i != element.attributeCount(); i++ ){
			Attribute attribute = element.attribute( i );
			sb.append(" " + attribute.getName() + "=\"" + attribute.getValue() + "\"" );
		}
		sb.append(">");
		
		// 遍历该元素的子节点
		for ( Iterator<Node> nodeIterator = element.nodeIterator(); nodeIterator.hasNext(); )
		{
			Node node = nodeIterator.next();
			if ( node instanceof Text ){
				Text text = (Text) node;
				sb.append( text.getText() );
			}
			else if ( node instanceof Comment ){
				Comment comment = (Comment)node;
				sb.append("<!--").append( comment.getText() ).append("-->");
			}else if ( node instanceof Element ){
				showElements2( (Element)node,sb );
			}
		}
		
		sb.append("</" + element.getName() + ">");	
	}
}


打印的是之前用作示例的XML

output:

------------xml文件元素内容-------------
org.dom4j.tree.DefaultElement@871e65 [Element: <person-list attributes: []/>]
org.dom4j.tree.DefaultElement@ea7549 [Element: <person attributes: [org.dom4j.tree.DefaultAttribute@ba175f [Attribute: name id value "10004"]]/>]
org.dom4j.tree.DefaultElement@1549ceb [Element: <name attributes: []/>]
org.dom4j.tree.DefaultElement@a30fd [Element: <gender attributes: []/>]
org.dom4j.tree.DefaultElement@11650d6 [Element: <phone attributes: []/>]
org.dom4j.tree.DefaultElement@1532fc [Element: <qq attributes: []/>]
org.dom4j.tree.DefaultElement@1c64ed8 [Element: <email attributes: []/>]
org.dom4j.tree.DefaultElement@626fd2 [Element: <person attributes: [org.dom4j.tree.DefaultAttribute@9b777a [Attribute: name id value "10005"]]/>]
org.dom4j.tree.DefaultElement@c12978 [Element: <name attributes: []/>]
org.dom4j.tree.DefaultElement@189c12a [Element: <gender attributes: []/>]
org.dom4j.tree.DefaultElement@e8c7db [Element: <phone attributes: []/>]
org.dom4j.tree.DefaultElement@992fa5 [Element: <qq attributes: []/>]
org.dom4j.tree.DefaultElement@10718b7 [Element: <email attributes: []/>]
------------xml文件文本内容-------------
<person-list>

	<!-- 联系人的信息 -->
	<person id="10004">
		<name>狂人</name>
		<gender>男</gender>
		<phone>1364499123</phone>
		<qq>1238645</qq>
		<email>1238645@qq.com</email>
	</person>

	<!-- 联系人的信息 -->
	<person id="10005">
		<name>张三</name>
		<gender>男</gender>
		<phone>1378574765</phone>
		<qq>64593435</qq>
		<email>64593435@qq.com</email>
	</person>

</person-list>

4.DOM树节点的增删改,并将改变后的树写入到XML文件

改变DOM树,就是改变其内部的节点。

若要改变树的节点,以及要将改变后的内容重新写入到XML文件,我们需要用到以下工具:

①:DocumentHelper

用于增加各种节点元素,比如Document、Element、Attribute都可以用它来创建

②:XmlWriter

创建其对象,通常都调用它的writer方法将新的document对象写到XML文件

③:OutputFormat

用它的对象来限定以什么格式来将DOM树写入到XML文件中,只有紧凑和漂亮两种格式

.createCompactFormat() -- 以紧凑格式写到文件,通常用于网络传输数据,节省空间

.createPrettyPrint() -- 以带缩进换行的格式写到文件,这样自己查看XML文件内容会更方便

①:直接从无构建一棵DOM树

package mdk.dom4j_tree;

import java.io.FileOutputStream;

import org.dom4j.Attribute;
import org.dom4j.Comment;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;

public class CreateXml {

	public static void main(String[] args) throws Exception {
		
		// 创建document对象
		Document document = DocumentHelper.createDocument();
		// 创建根元素
		Element rootElement = DocumentHelper.createElement("person-list");
		// 将根元素添加到文档上
		document.add( rootElement );
		
		// 创建根元素附带的子元素 person
		Element personEle = DocumentHelper.createElement("person");
		Attribute personAttr = DocumentHelper.createAttribute(personEle,"id","12345");
		personEle.add( personAttr );
		
		//添加注释
		Comment comment = DocumentHelper.createComment("这是个人信息");
		rootElement.add( comment );
		
		// 创建person附带的子元素 name gender age
		personEle.addElement("name").setText("张三");
		personEle.addElement("gender").setText("男");
		personEle.addElement("age").setText("18");
		
		rootElement.add( personEle );
		
		writeTo("d:/my_data.xml",document);
		
	}
	
	public static void writeTo( String xmlFileName,Document document ) throws Exception
	{
		FileOutputStream out = new FileOutputStream( xmlFileName );
		OutputFormat format = OutputFormat.createPrettyPrint();
		OutputFormat.createCompactFormat();
		XMLWriter xmlWriter = new XMLWriter(out,format);
		xmlWriter.write( document );
		xmlWriter.close();
	}

}

②:节点的增删改,继续使用上面的XML代码作为例子 -- 一信息表的增删改查

package mdk.exec02;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import mdk.exec02.Person.InfoTable;

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

public class OutputToHtml {

	private static String str_info[];
	private static InfoTable info[] = InfoTable.values();
	static{	
		str_info = new String[ info.length ];
		for ( int i = 0; i != str_info.length; i++ )
			str_info[ i ] = info[ i ].toString();
	}
	
	public static void main(String[] args) throws Exception {
		System.out.println();
		System.out.println("************************");
		System.out.println("(1)添加联系人");
		System.out.println("(2)删除联系人");
		System.out.println("(3)修改联系人");
		System.out.println("(4)在网页中显示联系人");
		System.out.println("(5)退出");
		System.out.println("************************");
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in,"utf-8"));
		String command = null;
		System.out.print("请选择:");
		while ( !(( command = br.readLine() ).equals("5")) )
		{
			if ( "1".equals(command) )
				addPersonInfo();
			else if ( "2".equals(command) )
				deletePersonInfo();
			else if ( "3".equals(command) )
				modifyPersonInfo();
			else if ( "4".equals(command) )
				showAllInfo();
			else
				System.out.print("无效选项,请重新选择:");
			System.out.print("请选择:");
		}
		System.out.println("程序退出...");
		
	}
	
	private static void modifyPersonInfo() throws Exception{
		SAXReader saxReader = new SAXReader();
		Document document = saxReader.read(new File("d:/my_data.xml"));
		Element rootElement = document.getRootElement();
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in,"gbk"));
		
		System.out.print("请输入你要修改的联系人的id号:");
		String id = br.readLine();
		
		Node targetNode = rootElement.selectSingleNode("//person[@id='"+id+"']");
		if ( targetNode == null ){
			System.out.println("通讯录没有此联系人");
			return;
		}
		
		System.out.println("(1)姓名  (2)性别  (3)电话 (4)QQ (5)E-Mail");
		String select = br.readLine();
		
		Element elt = (Element)targetNode;
		Element element = elt.element( str_info[ Integer.parseInt(select) ] );
		
		System.out.print("输入修改内容:");
		String content = br.readLine();
		element.setText(content);
			
		writeTo(document,"d:/my_data.xml");
	}

	private static void deletePersonInfo() throws Exception{
		SAXReader saxReader = new SAXReader();
		Document document = saxReader.read(new File("d:/my_data.xml"));
		Element rootElement = document.getRootElement();
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in,"gbk"));

		System.out.print("请输入你要删除的联系人的id号:");
		String id = br.readLine();
		Node targetNode = rootElement.selectSingleNode("//person[@id='"+id+"']");
		if ( targetNode == null ){
			System.out.println("通讯录没有此联系人");
			return;
		}
		targetNode.getParent().remove(targetNode);

		writeTo(document,"d:/my_data.xml");
		
	}

	public static void showAllInfo()throws Exception{	
		// 装载Person信息的列表
		List<Person> personList = new ArrayList<Person>();
		
		//创建 SAXReader对象
		SAXReader saxReader = new SAXReader();
		Document document = saxReader.read(new File("d:/my_data.xml"));
		// 获取根元素
		Element rootElement = document.getRootElement();
		// 获取 XML 的信息,将得到的信息放入List中
		List<Element> personElements = rootElement.elements("person");
		for (Element personEle : personElements){
			personList.add(new Person(
					personEle.attributeValue("id"),personEle.elementText("name"),personEle.elementText("gender"),personEle.elementText("phone"),personEle.elementText("qq"),personEle.elementText("email")));
		}
		
		String html = "";
		html += "<html>\n";
		html += "	<head>\n";
		html += "		<Meta http-equiv='content-type' content='text/html;charset=gbk'>\n";
		html += "		<title>联系人列表</title>\n";
		html += "		<style type='text/css'> th,td{ padding: 8px; } </style>\n";
		html += "	</head>\n";
		html += "	<body>\n";
		html += "		<h1 align='center'>8.21班通讯录</h1>\n";
		html += "		<table align='center' border='1' style='border-collapse: collapse;'> \n";
		html += "			<tr> <th>姓名</th> <th>性别</th> <th>电话</th> <th>QQ</th> <th>邮箱</th> </tr>\n";
		// 循环生成tr(每一个联系人对应一个<tr>)
		for (Person p : personList) {
			html += "			<tr>\n";
			html += "				<td>" + p.getName() + "</td>\n";
			html += "				<td>" + p.getGender() + "</td>\n";
			html += "				<td>" + p.getPhone() + "</td>\n";
			html += "				<td>" + p.getQq() + "</td>\n";
			html += "				<td>" + p.getEmail() + "</td>\n";
			html += "			</tr>\n";
		}
		html += "		</table>\n";
		html += "	<body>\n";
		html += "</html>\n";
		
		// 将上面的HTML代码写入到一个html文件中
		FileWriter fw = new FileWriter("d:/person-list.html");
		fw.write(html);
		fw.close();
		
		// 使用 Runtime类中的的getRuntime()得到一个Runtime对象,然后调用exec()方法执行某些程序功能
		Runtime.getRuntime().exec("\"C:\\Program Files\\Internet Explorer\\iexplore.exe\" d:/person-list.html");
	}
	
	public static void addPersonInfo() throws Exception{
		BufferedReader br = new BufferedReader(
				new InputStreamReader(System.in,"gbk"));
		
		System.out.println("----增加通讯录名单----");
		
		String inputInfo[] = new String[ str_info.length ];
		for ( int i = 1; i != str_info.length; i++ ){
			System.out.print("请输入"+ info[ i ].getInfo() + ":");
			inputInfo[ i ] = br.readLine();
		}
		System.out.print("请输入id:");
		String id = br.readLine();
		
		SAXReader saxReader = new SAXReader();
		Document document = saxReader.read(new File("d:/my_data.xml"));
		Element rootElement = document.getRootElement();
		
		while ( true )
		{
			//使用XPath查找
			Node targetNode = rootElement.selectSingleNode
						("//person[@id='"+id+"']");
			if ( targetNode == null )
				break;
			System.out.print("id与其它联系人的id重复了,请重新输入:");
			id = br.readLine();
		}
		inputInfo[ 0 ] = id;
		
		Element personEle = DocumentHelper.createElement("person");
		personEle.addAttribute(str_info[ 0 ],inputInfo[ 0 ]);
		for ( int i = 1; i != str_info.length; i++ )
			personEle.addElement(str_info[ i ]).setText(inputInfo[ i ]);
			
		rootElement.add(personEle);
		writeTo(document,"d:/my_data.xml");
		System.out.println("添加成功...");
	}
	
	public static void writeTo( Document document,String fileName ) {
		FileOutputStream out = null;
		XMLWriter xmlWriter  = null;
		
		try {
			 out = new FileOutputStream(fileName);
		} catch (FileNotFoundException e) {
			System.out.println("找不到文件!");
		}
		OutputFormat format = OutputFormat.createPrettyPrint();
		format.setEncoding("gbk");
		try {
			xmlWriter = new XMLWriter(out,format);
		} catch (UnsupportedEncodingException e) {
			System.out.println("不支持该编码格式!");
		}
		try {
			xmlWriter.write(document);
			xmlWriter.close();
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
}



里面所用到的Person类:

package mdk.exec02;

/**
 * 模型/实体:联系人信息
 * 
 * @author tyg
 * 
 */
public class Person {

	private String id; // 唯一标识符
	private String name; // 姓名
	private String gender; // 性别
	private String phone; // 电话
	private String qq; // QQ
	private String email; // 邮箱

	public enum InfoTable{
		
		id("id"),name("姓名"),gender("性别"),phone("电话"),qq("QQ"),email("E-mail");
		private String info; 
		private InfoTable( String value ) { info = value; }
		public String getInfo(){
			return info;
		}
	}
	
	public Person(String id,String name,String gender,String phone,String qq,String email) {
		this.id = id;
		this.name = name;
		this.gender = gender;
		this.phone = phone;
		this.qq = qq;
		this.email = email;
	}
	
	public Person(){}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	public String getQq() {
		return qq;
	}

	public void setQq(String qq) {
		this.qq = qq;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

}

猜你在找的XML相关文章