关于XML解析的几种方式,可以去看看别人家的博客,这里主要展示DOM,SAX,DOM4J三种方式生成xml和解析xml的示例!
四种生成和解析XML文档的方法详解(介绍+优缺点比较+示例)
public static void DomCreateXml() throws Exception {
// 1、创建一个DocumentBuilderFactory的对象
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// 2、创建一个DocumentBuilder对象
DocumentBuilder db = dbf.newDocumentBuilder();
// 3、创建一个新的Document
Document document = db.newDocument();
// 创建元素
Element songs = document.createElement("songs");
// 创建子元素(使用一个循环来创建子元素)
for (int i = 0; i < 5; i++) {
// 创建元素
Element song = document.createElement("song");
Element name = document.createElement("name");
// 向name中添加数据
// 如果改变数据可以直接定义三个数组 或者创建一个实体类 吧他们放入集合中再来赋值
name.setTextContent("春天里");
Element time = document.createElement("time");
time.setTextContent("5:20");
Element size = document.createElement("size");
size.setTextContent("30m");
//添加到上一级的元素
song.appendChild(name);
song.appendChild(time);
song.appendChild(size);
songs.appendChild(song);
}
// 添加元素到文档
document.appendChild(songs);
// 保存到项目的 demo/目录下
// 首先创建一个TransformerFactory对象
TransformerFactory tff = TransformerFactory.newInstance();
// 再利用tff创建一个Transformer
Transformer tf = tff.newTransformer();
// xml 换行
tf.setOutputProperty(OutputKeys.INDENT, "yes");
// 关联文档 和 创建xml文件
tf.transform(new DOMSource(document), new StreamResult("demo/dom.xml"));
}
使用DOM创建xml的时候需要注意DOM数的层级关系,因为DOM是w3c的标准,所以DOM具有一定的通用性,在JavaScript中操作html和上面的代码类似,这里就不赘述。下面我们再来看一下如何
这里写代码片public static void DomParseXml() throws Exception {
// 1、创建一个DocumentBuilderFactory的对象
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
// 2、创建一个DocumentBuilder对象
DocumentBuilder db = dbf.newDocumentBuilder();
// 3、通过调用db的parse的方法加载xml文件
Document parse = db.parse(new FileInputStream("demo/dom.xml"));
// 获取到了parse对象之后 就可以进行节点的解析,开始解析song节点
NodeList songs = parse.getElementsByTagName("song");
for (int i = 0; i < songs.getLength(); i++) {
// 通过item定位每一首歌的集合
Node song = songs.item(i);
// 通过song获取当前song节点里面的属性集合
NamedNodeMap attributes = song.getAttributes();
// 输出一下里面的属性
System.out.println(attributes.getLength());
// 遍历属性
for (int j = 0; j < attributes.getLength(); j++) {
// 那一个song节点里某一个属性
Node item = attributes.item(j);
// 打印属性值
System.out.println(item.getNodeName() + " = " + item.getNodeValue() + "");
}
// 遍历子节点
NodeList childNodes = song.getChildNodes();
// 输出一下子节点的长度
System.out.println(childNodes.getLength());
// 遍历子节点并且输出
for (int k = 0; k < childNodes.getLength(); k++) {
// 判断一下是否是空格
if (childNodes.item(k).getNodeType() == Node.ELEMENT_NODE) {
System.out.println(childNodes.item(k).getNodeName() + " = " + childNodes.item(k).getTextContent());
}
}
}
}
在获取子节点的值的时候需要注意并不是getNodeVaue()方法,而是getTextContent()方法,当然还可以使用 childNodes.item(k).getFirstChild().getNodeValue()方法获取节点值。
public static void SAXCreateXml() throws Exception {
// 创建一个xml文件
StreamResult streamResult = new StreamResult(new FileOutputStream("demo/sax.xml"));
// 创建好了xml文件之后需要进行设置 包括设置xml的内容
// 创建SAXTransformerFactory对象
SAXTransformerFactory tff = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
// 通过tff创建TransformerHandler对象
TransformerHandler handler = tff.newTransformerHandler();
// 格式化xml文档
handler.getTransformer().setOutputProperty(OutputKeys.INDENT, "yes");
// 设置handler和xml文档关联
handler.setResult(streamResult);
// 关联了之后我们需要向xml文件中添加元素
// 首先打开document文档
handler.startDocument();
// 方便添加属性
AttributesImpl attr = new AttributesImpl();
// 打开
handler.startElement("", "", "songs", attr);
for (int i = 0; i < 5; i++) {
//这里直接定义字符串 也可自行定义数组或者集合(定义集合需要判断是否为空)
String s1 = "童话镇",s2="4:30 秒",s3="4 M";
// 先清空一下属性
attr.clear();
attr.addAttribute("", "", "id", "", "1");
handler.startElement("", "", "song", attr);
attr.clear();
handler.startElement("", "", "name", attr);
handler.characters(s1.toCharArray(), 0, s1.length());
handler.endElement("", "", "name");
attr.clear();
handler.startElement("", "", "time", attr);
handler.characters(s2.toCharArray(), 0, s2.length());
handler.endElement("", "", "time");
attr.clear();
handler.startElement("", "", "size", attr);
handler.characters(s3.toCharArray(), 0, s3.length());
handler.endElement("", "", "size");
handler.endElement("", "", "song");
}
// 关闭
handler.endElement("", "", "songs");
handler.endDocument();
}
这里我使用的是自己定义的字符串,当然也可自行定义数组或者集合,定义集合的时候需要判断一下是否为空,不要报了空指针。
public static ArrayList SAXParseXml() throws Exception {
// 1、获取一个SAXParserFactory对象
SAXParserFactory factory = SAXParserFactory.newInstance();
// 2、通过factory 创建SAXParser对象
SAXParser parser = factory.newSAXParser();
// 3、parse的对象的parse方法加载xml文件
// 创建一个工具类继承DefaultHandler
SAXHandler saxHandler = new SAXHandler();
parser.parse(new FileInputStream("demo/songs.xml"), saxHandler);
// 输出一下list的长度
System.out.println(saxHandler.getList().size());
List list = saxHandler.getList();
for (Song s : list) {
System.out.println(s.getId());
System.out.println(s.getName());
System.out.println(s.getTime());
System.out.println(s.getSize());
}
return (ArrayList) saxHandler.getList();
}
public class SAXHandler extends DefaultHandler {
private List list ;
private Song song = null;
private String string = null;
// 生成getList方法 输出
public List getList() {
return list;
}
public SAXHandler() {
this.list =new ArrayList();
}
@Override
public void startDocument() throws SAXException {
super.startDocument();
System.out.println("开始解析");
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
super.startElement(uri, localName, qName, attributes);
if (qName.equals("song")) {
// 创建实体类song的对象
song = new Song();
// 遍历song
for (int i = 0; i < attributes.getLength(); i++) {
System.out.println(attributes.getQName(i) + " = " + attributes.getValue(i));
System.out.println("\n==========================");
// 把id保存到实体类中
if (attributes.getQName(i).equals("id")) {
song.setId(attributes.getValue(i));
}
}
} else if (!qName.equals("song") && !qName.equals("songs")) {
System.out.println("节点名:" + qName);
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
// TODO Auto-generated method stub
super.characters(ch, start, length);
// 必须把节点值定义成全局的变量 否则endElement就很难获取到值
string = new String(ch, start, length);
// 去掉换行
if (!string.trim().equals("")) {
System.out.println("节点值:" + string + "\n");
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
// TODO Auto-generated method stub
super.endElement(uri, localName, qName);
if (qName.equals("song")) {
System.out.println("=============结束===============");
// 添加到集合中去
list.add(song);
// 添加到了集合中之后清空一下song
song = null;
} else if (qName.equals("name")) {
song.setName(string);
} else if (qName.equals("time")) {
song.setTime(string);
} else if (qName.equals("size")) {
song.setSize(string);
}
}
@Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
super.endDocument();
System.out.println("结束解析");
}
}
package com.entity;
public class Song {
private String id;
private String name;
private String time;
private String size;
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 getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
}
上面操作:解析xml文档 —->保存到集合中—->输出
当然你不保存到集合直接输出也是可以的,直接把关于实体类和集合的代码删除可以,只是我们一般都要保存值,然后再取出来,因为我感觉有一定的普遍性,所以就贴出了保存到集合的例子。
SAX方法其实是这四种方式中解析速度是最快的,没错在中小型的xml数据中比dom4j还要快,大型的数据中dom4j是最好的,Hibernate使用dom4j就是个例子。看过开头的那篇博客都知道,SAX也有一些缺点,这里不再赘述。
public static void DOM4JCreateXML() throws Exception {
//1、创建document对象
Document document = DocumentHelper.createDocument();
//2、创建根节点
Element rootElement = document.addElement("songs");
//3、创建子元素节点
Element song = rootElement.addElement("song");
Element name = song.addElement("name");
name.setText("今天你要嫁给我");
Element time = song.addElement("time");
time.setText("5:20");
Element size = song.addElement("size");
size.setText("10M");
//4、生成xml文件
XMLWriter xmlWriter = new XMLWriter(
new FileOutputStream("demo/dom4j.xml"),
//格式化
OutputFormat.createPrettyPrint()
);
//写入到文档
xmlWriter.write(document);
//关闭xmlWriter
xmlWriter.close();
}
如果没有什么特别要求的话,我觉得大家还是使用DOM4J比较好,代码量少,生成的xml文档也美观。另外,DOM4J还可以支持很多复杂的xml文档,本人还没有使用过,如果你知道也可以和我说说,非常欢迎!
// 创建SAXReader对象
SAXReader saxReader = new SAXReader();
// 加载books.xml文件并且获取document对象
Document document = saxReader.read(new InputStreamReader(new FileInputStream("demo/dom4j.xml"), "utf-8"));
//通过document获取根节点
Element rootElement = document.getRootElement();
//通过根节点获取迭代器
Iterator elementIterator = rootElement.elementIterator();
while (elementIterator.hasNext()) {
Element song = (Element) elementIterator.next();
//获取book的属性名及属性值
List attributes = song.attributes();
for (Attribute attr : attributes) {
System.out.println(attr.getName()+" = "+attr.getValue());
}
//对song的子节点名和子节点值进行遍历
Iterator elementIterator2 = song.elementIterator();
while (elementIterator2.hasNext()) {
Element songChild = (Element) elementIterator2.next();
System.out.println("节点名:"+songChild.getName()+" "+songChild.getStringValue());
}
}
}
这里介绍了三种方式解析XML文档,JDOM的话,本人觉得没有使用的必要,完全可以使用DOM4J方式替代,另外DOM这种方式遇到大文件的时候也处理不好,所以我推荐使用SAX方式和DOM4J方式解析和生成XML文档。最最重要的一点,差点忽略了,DOM方式和SAX是JAVA中自带的,不需要导入额外的JAR包,而JDOM和DOM4都需要导入额外的JAR包。