XML四种解析方式
- DOM
- SAX
- JDOM
- DOM4J
前两种是官方自带的解析方式
后两种是第三方开源工具
XML文件示例
<?xml version="1.0" encoding="utf-8"?>
<!--开头必须写的一段代码-->
<bookstore>
<book id="1">
<name>百年孤独</name>
<author>马尔克斯</author>
<year>1900</year>
<price>50</price>
</book>
<book id="2">
<name>哈利波特</name>
<author>罗琳</author>
<year>2000</year>
<price>60</price>
<language>English</language>
</book>
</bookstore>
XML常用的节点类型
节点类型 | NodeType | NamedConstant | nodeName返回值 | nodeValue返回值 |
---|---|---|---|---|
Element | 1 | ELEMENT_NODE | element name | null |
Attr | 2 | ATTRIBUTR_NODE | 属性名 | 属性值 |
Text | 3 | TEXT_NODE | text | 节点内容 |
DOM
读
顺序:
1. 创建DocumentBuilderFactory对象
``` DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();```
2. 创建DocumentBuilder对象
```DocumentBuilder db = dbf.newDocumentBuilder();```
3. 使用parse()方法传入需要解析的xml文件的地址,返回document对象
```Document document = db.parse("books.xml");```
//1--创建DocumentBuilderFactory对象
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try{
//2--创建DocumentBuilder对象
DocumentBuilder db = dbf.newDocumentBuilder();
//3--使用parse()方法传入需要解析的xml文件的地址,返回document对象
Document document = db.parse("books.xml");
/* ----------------开始解析xml文件----------------- */
//输出所有book节点的集合
NodeList BookLists = document.getElementsByTagName("book");
//输出总共几本书
System.out.println("一总有"+BookLists.getLength()+"本书");
System.out.println("----------------------------");
for(int i=0;i<BookLists.getLength();i++){
System.out.println("=============================");
System.out.println("开始遍历第"+(i+1)+"本书"); Node bookNode = BookLists.item(i);
//获得book节点的属性集合
NamedNodeMap attr = bookNode.getAttributes();
System.out.println("第"+(i+1)+"本书共有"+attr.getLength()+"属性"); //遍历book节点的属性
for(int j=0;j<attr.getLength();j++){
//获得节点的所有属性
Node node = attr.item(j); System.out.println("属性名:"+node.getNodeName()+"---属性值:"+node.getNodeValue());
}
//遍历每个节点的子节点
NodeList childLists = bookNode.getChildNodes();
//输出孙子节点的个数
System.out.println("第"+(i+1)+"本书共有"+childLists.getLength()+"子节点");
//遍历输出孙子节点的内容
for(int k=0;k<childLists.getLength();k++){
Node childNode = childLists.item(k);
//如果是元素节点
if(childNode.getNodeType()==Node.ELEMENT_NODE){
System.out.print(childNode.getNodeName()+"---");
System.out.println(childNode.getFirstChild().getNodeValue());
}
}
}
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
运行输出结果:
输出第一个有9个节点是因为解析的时候把上一个结束标签和下一个开始标签之间的空白也堪称一个节点了需要注意的是当Element节点输出的节点值是空值,例如<element>这是一个element</element>
这里的<element>
节点的内容是”这是一个element”,但是输出element.getValue(),是空值,因为解析器吧内容看成一个text类型的<element>
节点的子节点,所以输出<element>
的子节点的内容才是“这是一个element”。
=============================
开始遍历第1本书
第1本书共有1属性
属性名:id---属性值:1
第1本书共有9子节点
name---null
author---马尔克斯
year---1900
price---50
=============================
开始遍历第2本书
第2本书共有1属性
属性名:id---属性值:2
第2本书共有11子节点
name---哈利波特
author---罗琳
year---2000
price---60
language---English
写
- 写文件首先创建一个Document对象,创建方法和读取文件的一样
- 然后使用document的creteElement(“节点名”),来创建一个新的Element节点对象
- Element的setAttribute(“属性名”,”属性值”),来设置属性的名称和内容
- Element 的appendChild(“子节点对象”),来添加子节点
- 创建TransformerFactory对象调用newInstance()来返回一个Transformer对象
- Transformer对象的setOutputProperty(OutputKeys.INDENT, “yes”)设置格式
- Transformer对象的transformer(new DOMSource(document), new StreamResult(new File(“book1.xml”))),把document对象和文件流转换为xml文件
用到的类和方法
<”|–”后面跟的该类的方法>
DocumentBuilderFactory
|-- newInstance();//返回实例对象
|-- newDocumentBuilder
DocumentBuilder
|-- newDocument()
Document
|-- setXmlStandalone(true);//设置不显示dtd和schema
|-- createElement("节点名");
|-- appendChild("根节点");//根节点添加到DOM树中
Element
|-- setAttribute("属性名", "属性值");
|-- appendChild("子节点");
TransformerFactory
|-- newInstance();
|-- newTransformer();
Transformer
|-- setOutputProperty(OutputKeys.INDENT, "yes");//设置输出样式带缩进
|-- transform(new DOMSource("document对象"), new StreamResult(new File("输出文件名")));
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.newDocument();
document.setXmlStandalone(true);//设置不显示dtd和schema
Element bookstore = document.createElement("bookstore");
Element book = document.createElement("book");
book.setAttribute("id", "001");
bookstore.appendChild(book);
//将根节点添加到DOM树中
document.appendChild(bookstore);
//创建TransformerFactory对象
TransformerFactory tft = TransformerFactory.newInstance();
//创建Transformer对象
Transformer tf = tft.newTransformer();
tf.setOutputProperty(OutputKeys.INDENT, "yes");
//把document对象和文件流转换为xml文件
tf.transform(new DOMSource(document), new StreamResult(new File("book1.xml")));
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SAX
读
SAX解析方式要用到handler,所以先创建一个handler继承自DefaultHandler的类
顺序:
1. 创建SAXParserFactory
```SAXParserFactory spf = SAXParserFactory.newInstance();```
2. 获得SAXParser
```SAXParser saxParser = spf.newSAXParser();```
3. 解析xml文件,传入handler对象
```saxParser.parse("books.xml", new SAXParserHandler());```
//创建SAXParserFactory
SAXParserFactory spf = SAXParserFactory.newInstance();
try {
//获得SAXParser
SAXParser saxParser = spf.newSAXParser();
//解析xml文件,传入handler对象
saxParser.parse("books.xml", new SAXParserHandler());
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SAXParserHandler类
public class SAXParserHandler extends DefaultHandler {
//开始遍历节点
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
super.startDocument();
System.out.println("开始遍历");
}
//结束遍历节点
@Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
super.endDocument();
System.out.println("结束遍历");
}
//遍历xml开始标签
@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);
//当为book父节点时
if(qName.equals("book")){
int num=attributes.getLength();
System.out.print(qName+"有"+num+"个属性:");
for(int i=0;i<num;i++){
System.out.println(attributes.getQName(i)+"---"+attributes.getValue(i));
}
}else if(!qName.equals("bookstore")){//为子节点
System.out.print(" "+qName+"---");
}
}
//遍历xml结束标签
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
super.endElement(uri, localName, qName);
}
//遍历节点的值,遍历节点名之后该方法自动执行
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
super.characters(ch, start, length);
String value = new String(ch,start,length);
//判断是否为空内容节点
if(!value.trim().equals("")){
System.out.println(value);
}
}
}
输出结果:
开始遍历
book有1个属性:id---1
name---百年孤独
author---马尔克斯
year---1900
price---50
book有1个属性:id---2
name---哈利波特
author---罗琳
year---2000
price---60
language---English
结束遍历
写
用到的类和方法
SAXTransformerFactory
|-- newInstance();//返回实例对象
|-- newTransformerHandler();
TransformerHandler
|-- getTransformer();
|-- setResult(new StreamResult(new File("输出的文件名")));
|-- startDocument();//打开document
|-- startElement(String uri, String localName, String qName, Attributes atts);
|-- endElement(String uri, String localName, String qName);
|-- endDocument();//关闭document
Transformer
|-- setOutputProperty(OutputKeys.ENCODING, "utf-8");//字符格式
|-- setOutputProperty(OutputKeys.INDENT, "yes");//缩进
AttributesImpl//属性对象
|-- clear();
|-- addAttribute(String uri, String localName, String qName, String type, String value);
此方法特别麻烦,一般情况下不使用
//创建xml文件
public void testCreat(){
//创建SAXTransformerFactory
SAXTransformerFactory saxtft = (SAXTransformerFactory)
SAXTransformerFactory.newInstance();
try {
//创建TransformerHandler对象
TransformerHandler tfhHandler = saxtft.newTransformerHandler();
//创建Transformer对象
Transformer tr = tfhHandler.getTransformer();
tr.setOutputProperty(OutputKeys.ENCODING, "utf-8");
tr.setOutputProperty(OutputKeys.INDENT, "yes");
//创建result对象
File file = new File("books2.xml");
if(!file.exists()){
file.createNewFile();
}
Result result = new StreamResult(file);
//关联handler和创建的文件的result
tfhHandler.setResult(result);
//利用handler对象进行xml的编写
//打开document
tfhHandler.startDocument();
AttributesImpl attr = new AttributesImpl();
tfhHandler.startElement("", "", "bookstore", attr);
attr.clear();
attr.addAttribute("", "", "id", "", "1");
tfhHandler.startElement("", "", "book", attr);
tfhHandler.endElement("", "", "book");
tfhHandler.endElement("", "", "bookstore");
//关闭document
tfhHandler.endDocument();
} catch (TransformerConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
JDOM
JDOM是一款开源的解析工具,简单便捷,非常好用。
首先的在BuildPath中导入jdom-2.0.5的jar包
读
顺序:
- 创建SAXBuilder对象
SAXBuilder saxBuilder = new SAXBuilder();
2. 创建FileInputStream的文件流对象
FileInputStream fis = new FileInputStream("books.xml");
3. 创建document接受解析的文件流对象
Document document = saxBuilder.build(fis);
4. 通过document获取xml对象的根节点
Element rootElement = document.getRootElement();
5. 获得根节点的所有子节点list集合
List<Element> childrenList = rootElement.getChildren();
//1--创建SAXBuilder对象
SAXBuilder saxBuilder = new SAXBuilder();
try {
//2--创建FileInputStream的文件流对象
FileInputStream fis = new FileInputStream("books.xml");
//3--创建document接受解析的文件流对象
Document document = saxBuilder.build(fis);
//4--通过document获取xml对象的根节点
Element rootElement = document.getRootElement();
//5--获得根节点的所有子节点list集合
List<Element> childrenList = rootElement.getChildren();
//6--遍历所有子节点
for(Element element : childrenList){
System.out.println("子节点名:"+element.getName()+"属性"+element.getAttributeValue("id"));
List<Element> childsList = element.getChildren();
for(Element element2 : childsList){
System.out.println(" 孙子节点:"+element2.getName()+"-->"+element2.getValue());
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JDOMException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
输出结果:
子节点名:book属性1
孙子节点:name-->s-001百年孤独
孙子节点:author-->马尔克斯
孙子节点:year-->1900
孙子节点:price-->50
子节点名:book属性2
孙子节点:name-->哈利波特
孙子节点:author-->罗琳
孙子节点:year-->2000
孙子节点:price-->60
孙子节点:language-->English
写
用到的类和方法
Document //直接new创建对象使用JDOM下的Document包
|-- setRootElement("根节点名");
Element //直接new创建对象使用JDOM下的Document包
|-- setAttribute("属性名", "属性值");
|-- addContent("子节点");
XMLOutputter //输出document到文件
|-- output("document对象", new FileOutputStream(new File("输出的文件名")));
|-- setOutputProperty(OutputKeys.INDENT, "yes");//缩进
创建新一个RSS类型的XML文件
//创建document对象
Document document = new Document();
Element rss = new Element("rss");
rss.setAttribute("version", "2.0");
document.setRootElement(rss);
Element title = new Element("title");
title.setText("各种新闻要闻");
rss.addContent(title);
XMLOutputter outputter = new XMLOutputter();
try {
outputter.output(document, new FileOutputStream(new File("rssnew2.xml")));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
DOM4J
DOM4J也需要先导入相关的jar包才能使用
读
顺序:
创建SAXReader对象
SAXReader saxReader = new SAXReader();
通过read(in)方法返回Document对象
Document document = saxReader.read(new FileInputStream("books.xml"));
获得root节点
Element rootElement = document.getRootElement();
通过element对象的elementIterator方法获取迭代器获得根节点的子节点
Iterator<Element>itElement = rootElement.elementIterator();
//1.创建SAXReader对象
SAXReader saxReader = new SAXReader();
try {
//2.通过read(in)方法返回Document对象
Document document = saxReader.read(new FileInputStream("books.xml"));
//3.获得root节点
Element rootElement = document.getRootElement();
//4.通过element对象的elementIterator方法获取迭代器获得根节点的子节点
Iterator<Element>itElement = rootElement.elementIterator();
//5.遍历迭代器
while(itElement.hasNext()){
Element element = itElement.next();
System.out.println("节点名:"+element.getName());
List<Attribute>attrList = element.attributes();
for(Attribute attr:attrList){
System.out.println("属性名:"+attr.getName()+"--属性值:"+attr.getValue());
}
//获得孙子节点Iterator
Iterator<Element> iterator = element.elementIterator();
while(iterator.hasNext()){
Element itElement2 = iterator.next();
System.out.println(" 孙子节点:"+itElement2.getName()+"---"+itElement2.getStringValue());
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
输出:
节点名:book
属性名:id--属性值:1
孙子节点:name---s-001百年孤独
孙子节点:author---马尔克斯
孙子节点:year---1900
孙子节点:price---50
节点名:book
属性名:id--属性值:2
孙子节点:name---哈利波特
孙子节点:author---罗琳
孙子节点:year---2000
孙子节点:price---60
孙子节点:language---English
写
用到的类和方法
DocumentHelper //DOM4J包下的类
|-- createDocument();//返回一个document对象
Document
|-- addElement("rss");//添加根节点
Element
|-- addAttribute("属性名", "属性值");
|-- addElement("子节点");
|-- setText(String arg0);//添加内容
XMLWriter //输出document到文件
|-- new XMLWriter(new FileOutputStream(new File("输出的文件名")));
|-- write("document对象");
|-- close();//关闭写入流
同样是以一个RSS类型的XML文件为例子
Document document = DocumentHelper.createDocument();
Element rss = document.addElement("rss");
rss.addAttribute("version", "2.0");
try {
XMLWriter writer = new XMLWriter(new FileOutputStream(new File("rssnews.xml")));
writer.write(document);
writer.close();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}