一、java操作xml简介

 java里面操作xml的方法无非就是读与写,读出来才能谈后续的替换、查找等操作,java里面操作xml的方法也是五花八门的,我这里总结几种常用的方法,见下图:

JAVA xml 配置 xml在java中怎么用_System

xml读:sax,dom,jdom,dom4j

xml写:dom,jdom,dom4j

下面先大致介绍一下这几种方法,后续再贴出具体代码。

sax:即Simple API for XML,它是java本身自带的类库,使用它不需要你引入任何其他的jar包,在xml的解析方面性能特别快,特别针对比较大的xml文档,处理起来很有优势。

dom:即jdk针对w3c dom结构标准的实现,虽然可以用来xml的解析与写入,不过在实际使用的状况来看,还是在写入方面使用的比较多,解析建议使用sax。

jdom:是一个第三方类库,我们使用的使用引入jdom.jar就可以使用了

dom4j:"4j"这个词不读做“四j”,而是读作“for  j”,意思是dom  for  java,也是一个第三方类库,我们使用时也需要引入它的jar包。

二、使用java本身针对w3c dom的实现(dom)读取xml

 java本身针对w3c dom结构标准的实现就叫做dom,它在操作写入xml的时候用的比较多,xml解析一般用sax,但是dom也可以用来做xml的解析,下面是代码。

要解析的xml叫做msg.xml,内容如下:


<?xml version="1.0" encoding="UTF-8"?>
<message>
	<creator>zhao</creator>
	<noticeId>20141213</noticeId>
	<time>2014-12-13 19:10:30</time>
	<dept>59000</dept>
	<content>
		<optionId effect="true">1001000</optionId>
		<optionName>请列举你的至少3项意见</optionName>
	</content>
</message>


现有需求如下,我想取到optionName标签的内容该怎么用dom来实现呢?下面就是实现该功能的java代码:


package zhao;
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
 * 使用java本身针对w3c dom的实现之dom读取xml。读取不方便
 * @author zhao
 */
public class XmlReader1 {
	public static void main(String[] args) throws Exception {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		Document document = db.parse(new File(System.getProperty("user.dir")+File.separator+"msg.xml"));
		//得到根节点
		NodeList rootElement = document.getElementsByTagName("message");
		for (int i = 0; i < rootElement.getLength(); i++) {
			   NodeList contentElList = document.getElementsByTagName("content");
			   Element contentEl = (Element)contentElList.item(0);
			   String textContent = contentEl.getElementsByTagName("optionName").item(0).
			   getFirstChild().getNodeValue();
			   System.out.println(textContent);
		}
	}
}


执行结果如下:

JAVA xml 配置 xml在java中怎么用_xml_02

三、使用jdk自带的sax解析xml

 sax(Simple API for XML)就是用来做xml解析用的,使用很简单,它是基于事件模型的,这样说你可能有点看不懂,什么意思呢。我们自己想一想读xml能有什么事件?无非就是说读到了一个xml,刚读到的时候是个事件吧,读到一个xml标签开始的时候也是一个事件吧,读到一个xml标签结束的时候也可以是一个事件,读到文本标签的时候也是一个事件,无非就是这些嘛,sax是怎么分这些事件的呢,也跟我们上边自己分的思路是一样的,只不过它可能考虑的更周密,那我们就来看看使用sax是怎么解析xml的。

要解析的xml,依然是msg.xml:

<?xml version="1.0" encoding="UTF-8"?>
<message>
<creator>zhao</creator>
<noticeId>20141213</noticeId>
<time>2014-12-13 19:10:30</time>
<dept>59000</dept>
<content>
<optionId effect="true">1001000</optionId>
<optionName>请列举你的至少3项意见</optionName>
</content>
</message>

        我现在的需求不让你找到optionName标签内的文本内容了,直接让你读出来整个文档,使用sax怎么做呢?看下面的代码:


package zhao;
import java.io.File;
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.helpers.DefaultHandler;
public class XmlReader2 {
	public static void main(String[] args) throws Exception {
		SAXParserFactory saxParserFactory=SAXParserFactory.newInstance();
		SAXParser saxParser = saxParserFactory.newSAXParser();
		saxParser.parse(new File(System.getProperty("user.dir")+File.separator+"msg.xml"), new XmlHandler());
	}
}
class XmlHandler extends DefaultHandler{

	@Override
	public void startDocument() throws SAXException {
    	System.out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
	}

	@Override
	public void endDocument() throws SAXException {
		System.out.print("解析完毕");
	}

	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
	       System.out.print("<");
	       System.out.print(qName);
	       if (attributes!=null) {
			for (int i = 0; i < attributes.getLength(); i++) {
			  System.out.print(" "+attributes.getQName(i)+"=\""+attributes.getValue(i)+"\"");	 
			}
		  }
	       System.out.print(">");
	}

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		 System.out.print("</");
	       System.out.print(qName);
	    if (qName.equals("message")) {
			System.out.println(">");
		}else {
			System.out.print(">");
		}
	}
	@Override
	public void characters(char[] ch, int start, int length) throws SAXException {
		System.out.print(new String(ch,start,length));
	}
}


执行结果如下图:

JAVA xml 配置 xml在java中怎么用_System_03

总结:

        可以看到,sax定义了startDocument,endDocument,startElement,endElement,characters这些事件,针对上面的例子来说,startDocument,endDocument只会调用一次,因为只有一个文档嘛,自然就只有一次文档的开始与文档的结束。startElement,endElement,characters事件都会调用多次,其中characters用于获取元素内的文本内容。

四、使用jdom解析xml文件

 jdom是java里面一个操作xml的第三方库,这里我依然使用msg.xml来演示jdom解析xml的功能,msg.xml的内容如下:


<?xml version="1.0" encoding="UTF-8"?>
<message>
	<creator>zhao</creator>
	<noticeId>20141213</noticeId>
	<time>2014-12-13 19:10:30</time>
	<dept>59000</dept>
	<content>
		<optionId effect="true">1001000</optionId>
		<optionName>请列举你的至少3项意见</optionName>
	</content>
</message>


需求跟前面使用sax解析是一样的,就是使用jdom读取msg.xml的全部内容,以下是使用jdom解析xml的代码:


package zhao;
import java.io.File;
import java.util.Iterator;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;

import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
public class XmlReader3 {
	public static void main(String[] args) throws Exception {
		SAXBuilder saxBuilder=new SAXBuilder();
		Document document = saxBuilder.build(new File(System.getProperty("user.dir")+File.separator+"msg.xml"));
		Element rootElement = document.getRootElement();
		if (rootElement!=null) {
			System.out.print("<");
			System.out.print(rootElement.getName());
			System.out.println(">");
			//只得到儿子
			List<Element> children = rootElement.getChildren();
			readXmlByJdom(children);
			System.out.print("</");
			System.out.print(rootElement.getName());
			System.out.println(">");
		}
	}
	
	private static void readXmlByJdom(List<Element> children){
		for (Iterator<Element> iterator = children.iterator(); iterator.hasNext();) {
			//现在每个element是creator级别的
			Element element =  iterator.next();
			String name = element.getName();
			//element.getChildren()!=null 这里每个元素的孩子可能会为空:文本节点不算在孩子之内,其实w3c里是算的
			//System.out.println(element.getChildren());
			if (element.getChildren().size()!=0) {
				System.out.println("<"+name+">");
				//递归读取
				 readXmlByJdom((List<Element>)element.getChildren());
				 System.out.println("</"+name+">");
			}else {
				if (!element.getAttributes().isEmpty()) {
					System.out.print("<"+name);
					for (int i = 0; i < element.getAttributes().size(); i++) {
						Attribute attribute=(Attribute) element.getAttributes().get(i);
						System.out.print(" "+attribute.getName()+"=\""+attribute.getValue()+"\"");
					}
					System.out.print(">");
				}else {
					System.out.print("<"+name+">");
					
				}
				
				//element.getText()没有text的话自然输出空
				System.out.print(element.getText());
				System.out.println("</"+name+">");
			}
			//得到名字为"creator"的的element 的child
			//Element child = element.getChild("creator");
			//System.out.println(child.getText());
		}
	}
}


结果:

JAVA xml 配置 xml在java中怎么用_JAVA xml 配置_04

可以看出这里使用jdom实现与前边sax同样功能的话,就需要一点功力了,需要自己写递归实现xml的读取,单独针对msg.xml,其实没有必要使用递归,因为结构你是知道的,也是固定的,我这里用了递归,是因为,因为什么呢,这是很早之前我的代码了,2014年的吧,可能就是为了求代码的通用性而写的递归吧。

五、使用dom4j解析xml文件

 要被解析的msg.xml:

JAVA xml 配置 xml在java中怎么用_System_05

下面代码实现的功能是使用dom4j解析上面的msg.xml:


package zhao;
import java.io.File;
import java.util.Iterator;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class XmlReader4 {
	public static void main(String[] args) throws Exception {
		SAXReader saxReader=new SAXReader();
		Document document = saxReader.read(new File(System.getProperty("user.dir")+File.separator+"msg.xml"));
		Element root = document.getRootElement();
		System.out.println("<"+root.getName()+">");
		//当然了,同jdom的getChildren一样,也是只包含儿子元素
		Iterator childrenOfRoot = root.elementIterator();
		readByDom4j(childrenOfRoot);
		System.out.println("</"+root.getName()+">");
		
	}
	private static void readByDom4j(Iterator iterator){
		while(iterator.hasNext()){
			Element element = (Element) iterator.next();
			Iterator children = element.elementIterator();
			//这里同jdom一样,文本节点也不算在子元素集合的迭代器之内
			//System.out.println(children.hasNext());
			if(children.hasNext()){
				System.out.println("<"+element.getName()+">");
				readByDom4j(children);
				System.out.println("</"+element.getName()+">");
			}else {
				List attributes = element.attributes();
				if (!attributes.isEmpty()) {
					System.out.print("<"+element.getName());
					for(Object o:attributes){
						Attribute attribute=(Attribute) o;
						System.out.print(" "+attribute.getName()+"=\""+attribute.getValue()+"\"");
					}
					System.out.print(">");
				}else {
					System.out.print("<"+element.getName()+">");
				}
				System.out.print(element.getText());
				System.out.println("</"+element.getName()+">");
			}
		}
	}
}


执行结果:

JAVA xml 配置 xml在java中怎么用_dom_06

六、使用jdom解析xml字符串

  有时候,我们的xml可能不是一个xml文件,比如在webservice里面,xml可能是调用webservice方法的返回值,我们收到的返回值就是一个字符串了,使用jdom当然也可以解析了,因为这里的xml字符串本质上也是一个xml文件嘛,你读了一个xml文件,读进来之后不就是一个字符串了嘛,都是一样的道理,没什么区别。唯一的区别就是得到org.jdom.Document对象的方法不同了,解析xml文件的时候是通过

Document document = saxBuilder.build(new File(System.getProperty("user.dir")+File.separator+"msg.xml"))的方式,而这里因为是xml字符串而不是xml文件,就换了一下,改为了

StringReader sr=new StringReader(str);

InputSource is=new InputSource(sr);

Document document = saxBuilder.build(is);

的方式,其他没什么区别,还是再写个简单的例子吧:


package zhao;

import java.io.File;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;

import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;
import org.xml.sax.InputSource;
public class XmlReader5 {

	public static void main(String[] args) throws Exception {
		//ws传来的字符串
		String str="<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+
"<message><creator>zhao</creator><noticeId>20141213</noticeId><time>2014-12-13 19:10:30</time><dept>59000</dept><content>"+
			"<optionId effect=\"true\">1001000</optionId>"+
				"<optionName>请列举你的至少3项意见</optionName></content></message>";
		SAXBuilder saxBuilder=new SAXBuilder();
		StringReader sr=new StringReader(str);
		InputSource is=new InputSource(sr);
		Document document = saxBuilder.build(is);
		Map<String, String> map=new HashMap<String, String>();
		Element rootElement = document.getRootElement();
		Element child = rootElement.getChild("creator");
		System.out.println(child.getName());
		System.out.println(child.getText());
		
		//xpath测试
		System.out.println("---xpath测试---");
		XPath xPath=XPath.newInstance("//optionName");
		@SuppressWarnings("unchecked")
		List<Element> selectNodes = xPath.selectNodes(child);
		for (int i = 0; i < selectNodes.size(); i++) {
			System.out.println(selectNodes.get(i).getName());
		}
	}
}


注意:jdom里面还可以使用xpath来进行元素的选取,记得要导入相关jar包就行了。

七、使用dom4j解析xml字符串

如题所示,这篇java教程再来看一下如何使用dom4j解析xml字符串,跟前边那篇jdom类似,dom4j既然可以解析xml文件,自然也就可以解析xml字符串了,没什么大的区别,可以当做一个巩固的例子来学习。


package zhao;
import java.util.Iterator;
import javax.xml.parsers.ParserConfigurationException;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
public class XmlReader6 {
	public static void main(String[] args) throws Exception {
		String str="<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+
		"<messages><message><creator>zhao</creator><noticeId>20141213</noticeId>" +
		"<noticeId>20141214</noticeId><time>2014-12-13 19:10:30</time>" +
		"<dept>59000</dept><content>"+
				"<optionId effect=\"true\">1001000</optionId>"+
				"<optionName>请列举你的至少3项意见</optionName></content></message>"+
				"<message><creator>zhao</creator><noticeId>111</noticeId>" +
				"<noticeId>2222</noticeId><time>2014-12-13 19:10:30</time><dept>59000</dept>" +
				"<content>"+
				"<optionId effect=\"true\">1001000</optionId>"+
				"<optionName>请列举你的至少3项意见</optionName></content></message></messages>";
		Document document = DocumentHelper.parseText(str);
		Element root = document.getRootElement();
		//相当于jdom的getchild("noticeId")
		Iterator elementIterator = root.elementIterator("message");
		while(elementIterator.hasNext()){
			Element element = (Element) elementIterator.next();
			Iterator elementIterator2 = element.elementIterator("noticeId");
			while(elementIterator2.hasNext()){
				Element element2 = (Element) elementIterator2.next();
				System.out.println(element2.getName());
				System.out.println(element2.getText());
			}
		}
	}
}


上面程序的功能是找出所有的message标签下面的noticeId标签,并打印出来找到的标签名字和标签里面的内容,执行结果如下图:

JAVA xml 配置 xml在java中怎么用_xml_07

八、使用jdk自带的dom生成xml

使用java本身自带的实现了w3c dom的dom可以生成xml,先看下代码:


package zhao;

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
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;
import org.w3c.dom.Element;
public class XmlWrite1 {
	public static void main(String[] args) throws Exception {
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		Document document = db.newDocument();
		//创建元素
		Element list = document.createElement("list");
		Element option = document.createElement("option");
		Element name = document.createElement("name");
		Element email = document.createElement("email");
		//设置值
		name.setTextContent("abc");
		name.setAttribute("effect", "true");
		email.setTextContent("123@163.com");
		//设置关系
		option.appendChild(name);
		option.appendChild(email);
		list.appendChild(option);
		document.appendChild(list);
		
		TransformerFactory tff=TransformerFactory.newInstance();
		Transformer tf = tff.newTransformer();
		DOMSource xmlSource=new DOMSource(document);
		StreamResult sr=new StreamResult(new File(System.getProperty("user.dir")+File.separator+"javaDomWriter.xml"));
		//输出前的格式化
		tf.setOutputProperty(OutputKeys.ENCODING, "utf-8");
				tf.setOutputProperty(OutputKeys.INDENT, "yes");
		tf.transform(xmlSource, sr);
	}
}


生成的javaDomWriter.xml如下,:

JAVA xml 配置 xml在java中怎么用_System_08

注意:tf.setOutputProperty(OutputKeys.INDENT, "yes");的作用时要xml换行,如果不加入这句的话,那么生成的xml都是放在一行里面,虽然说内容都是一样的,但是放在一行里面很不容易阅读,加不加这一句视具体情况而定,如果你只是用于数据传输,可以不加这一句,这样起到了压缩传输内容大小的作用,如果你要生成xml自己看,那就加上吧。

九、使用jdom生成xml

这篇教程演示如何通过jdom来生成xml文件:


package zhao;
import java.io.File;
import java.io.FileOutputStream;
import javax.xml.parsers.ParserConfigurationException;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.XMLOutputter;
public class XmlWrite3 {
	public static void main(String[] args) throws Exception {
		//创建元素
		Element list=new Element("list");
		Element option=new Element("option");
		Element name=new Element("name");
		Element email=new Element("email");
		
		//设置内容
		name.setText("abc");
		name.setAttribute("effect", "false");
		email.setText("123@163.com");
		//设置关系
		option.addContent(name);
		option.addContent(email);
		list.addContent(option);
		//新建document
		Document document=new Document(list);
		XMLOutputter xmlOutputter=new XMLOutputter();
		xmlOutputter.setEncoding("gbk");
		xmlOutputter.output(document, new FileOutputStream(new File(System.getProperty("user.dir")+
		File.separator+"writenByJdom.xml")));
	}
}


生成的文件writenByJdom.xml内容如下:


<?xml version="1.0" encoding="gbk"?>
<list><option><name effect="false">abc</name><email>123@163.com</email></option></list>


十、使用dom4j生成xml文件

在java中,使用dom4j这个类库可以生成xml文件,dom4j与jdom都综合了sax的读取和dom的写操作的优点,实现的功能都是类似的,即都可以用来解析xml和生成xml等操作,我个人比较喜欢用dom4j,没有什么原因,也没有针对dom4j和jdom做过性能比较,总感觉没那个必要吧,都是成熟的类库,在不是对性能要求至一分一毫的系统里面,何必做那些无用功。至于为甚么喜欢用dom4j,可能是先入为主的原因。下面的代码演示了如何使用dom4j来生成一个xml文件。


package zhao;

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

import javax.xml.parsers.ParserConfigurationException;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
public class XmlWrite4 {
	public static void main(String[] args) throws Exception {
		//dom4j创建元素的同时就设置了关系
		Document document = DocumentHelper.createDocument();
		Element root = document.addElement("list");
		Element option = root.addElement("option");
		Element name = option.addElement("name");
		Element email = option.addElement("email");
		//设置内容
		name.addAttribute("effect", "false");
		name.addText("abc");
		email.addText("123@qq.ccom");
		
		//输出
		OutputFormat outputFormat=OutputFormat.createPrettyPrint();
		outputFormat.setEncoding("gbk");
		XMLWriter xmlWriter=new XMLWriter(new FileOutputStream(new File
				(System.getProperty("user.dir")+File.separator+"wirtenByDom4j.xml")), outputFormat);
		xmlWriter.write(document);
		//document.write(xmlWriter);
		xmlWriter.close();
	}
}


生成的wirtenByDom4j.xml如下:

JAVA xml 配置 xml在java中怎么用_System_09