我在模拟tomcat的过程中需要解析xml,所以在此总结下常用的sax/dom,Dom4j,jsoup等。
其实sax/dom使用有点复杂,建议使用DOM4j等技术。
这里sax和dom还有Dom4j借鉴于:https://blog.csdn.net/m0_37499059/article/details/80505567
先看xml
demo.xml
<?xml version="1.0" encoding="utf-8" ?>
<class>
<student>
<firstname>cxx1</firstname>
<lastname>Bob1</lastname>
<nickname>stars1</nickname>
<marks>85</marks>
</student>
<student rollno="493">
<firstname>cxx2</firstname>
<lastname>Bob2</lastname>
<nickname>stars2</nickname>
<marks>85</marks>
</student>
<student rollno="593" e="ee" class="12er">
<firstname id="12" class="12er">cxx3</firstname>
<lastname>Bob3</lastname>
<nickname>stars3</nickname>
<marks>85</marks>
</student>
</class>
SAX
package com.yuer.xml;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
/**
* 使用SAX解析xml
* 优点和缺点:
* SAX处理的优点非常类似于流媒体的优点。分析能够立即开始,而不是等待所有的数据被处理。
* 而且,由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中。这对于大型文档来说是个巨大的优点
*
*
* 缺点:不能修改文件,且不支持文件的随意读取
*
*
* @author Yuer
*
*/
public class SaxDemo {
public static void main(String[] args) throws Exception {
// 1.或去SAXParserFactory实例
SAXParserFactory factory = SAXParserFactory.newInstance();
// 2.获取SAXparser实例
SAXParser saxParser = factory.newSAXParser();
// 创建Handel对象
SAXDemoHandel handel = new SAXDemoHandel();
saxParser.parse("src/main/resources/demo.xml", handel);
}
}
class SAXDemoHandel extends DefaultHandler {
// 遍历xml文件开始标签
@Override
public void startDocument() throws SAXException {
super.startDocument();
System.out.println("sax解析开始");
}
// 遍历xml文件结束标签
@Override
public void endDocument() throws SAXException {
super.endDocument();
System.out.println("sax解析结束");
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
if (qName.equals("student")) {
System.out.println("============开始遍历student=============");
// System.out.println(attributes.getValue("rollno"));
} else if (!qName.equals("student") && !qName.equals("class")) {
System.out.print("节点名称:" + qName + "----");
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if (qName.equals("student")) {
System.out.println(qName + "遍历结束");
System.out.println("============结束遍历student=============");
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
String value = new String(ch, start, length).trim();
if (!value.equals("")) {
System.out.println(value);
}
}
}
运行结果
DOM
package com.yuer.xml;
import org.w3c.dom.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
/**
* 使用DOM方式解析xml
* 优点和缺点:
* 核心是按树形结构处理数据,dom解析器读入xml文件并在内存中建立一个结构一模一样的“树”,
* 这树各节点和xml各标记对应,通过操纵此“树”来处理xml中的文件。xml文件很大时,建立的“树”也会大,所以会大量占用内存。
* 所以优点很容易总结出来:支持随机读取,且能读和写。
* 缺点:读取大文件时很耗费内存。
* @author Yuer
*
*/
public class DomDemo {
//用Element方式
public static void element(NodeList list){
for (int i = 0; i <list.getLength() ; i++) {
Element element = (Element) list.item(i);
NodeList childNodes = element.getChildNodes();
for (int j = 0; j <childNodes.getLength() ; j++) {
if (childNodes.item(j).getNodeType()==Node.ELEMENT_NODE) {
//获取节点
System.out.print(childNodes.item(j).getNodeName() + ":");
//获取节点值
System.out.println(childNodes.item(j).getFirstChild().getNodeValue());
}
}
}
}
public static void node(NodeList list){
for (int i = 0; i <list.getLength() ; i++) {
Node node = list.item(i);
NodeList childNodes = node.getChildNodes();
for (int j = 0; j <childNodes.getLength() ; j++) {
if (childNodes.item(j).getNodeType()==Node.ELEMENT_NODE) {
System.out.print(childNodes.item(j).getNodeName() + ":");
System.out.println(childNodes.item(j).getFirstChild().getNodeValue());
}
}
}
}
public static void main(String[] args) {
//1.创建DocumentBuilderFactory对象
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//2.创建DocumentBuilder对象
try {
DocumentBuilder builder = factory.newDocumentBuilder();
Document d = builder.parse("src/main/resources/demo.xml");
NodeList sList = d.getElementsByTagName("student");
//element(sList);
node(sList);
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果
Dom4j
package com.yuer.xml;
import java.io.File;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
/**
* Dom4j方式解析xml
*
* Dom4j是基于底层api的更高级封装。
* dom4j是目前在xml解析方面是最优秀的(Hibernate、Sun的JAXM也都使用dom4j来解析XML),
* 它合并了许多超出基本 XML 文档表示的功能,包括集成的 XPath 支持、XML Schema 支持以及用于大文档或流化文档的基于事件的处理
* @author Yuer
*
*/
public class Dom4JDemo {
public static void main(String[] args) throws Exception {
//1.创建Reader对象
SAXReader reader = new SAXReader();
//2.加载xml
Document document = reader.read(new File("src/main/resources/demo.xml"));
//3.获取根节点
Element rootElement = document.getRootElement();
Iterator iterator = rootElement.elementIterator();
while (iterator.hasNext()){
Element stu = (Element) iterator.next();
List<Attribute> attributes = stu.attributes();
System.out.println("======获取属性值======");
for (Attribute attribute : attributes) {
System.out.println(attribute.getValue());
}
System.out.println("======遍历子节点======");
Iterator iterator1 = stu.elementIterator();
while (iterator1.hasNext()){
Element stuChild = (Element) iterator1.next();
System.out.println("节点名:"+stuChild.getName()+"---节点值:"+stuChild.getStringValue());
}
}
}
}
运行结果
jsoup
这个主要是用来解析html,相比于其他方式,jsoup简单很多了,也是基于文档树的,里面提供了很多方法用于处理html,xml当然也可以处理,且很容易理解。也可以用于爬虫。
package com.yuer.xml;
import java.io.File;
import java.io.IOException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
/**
* jsoup主要用来解析HTML,但是也可用于解析xml主要是很简便 也可用于爬虫
*
* @author Yuer
*
*/
public class TestJsoup {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
parseXml();
}
public static void parseXml() throws IOException {
// 将xml中的数据弄到StringBuffer中
// int i = 0;
// StringBuffer buff = new StringBuffer();
// FileInputStream fis = new FileInputStream(new File("src/main/resources/demo.xml"));
//
// while ((i = fis.read()) != -1) {
// buff.append((char) i);
// }
// 获取Document的方式有三种,第一种字符串,第二种文件(先封装为File,还可以指定编码格式如utf-8),第三种网址(需要先封装为URL)
// Document doc = Jsoup.parse(buff.toString());
Document doc = Jsoup.parse(new File("src/main/resources/demo.xml"),"utf-8");
// System.out.println(doc); // 这个会将整个xml打印和直接打印buff的效果一致
// 获取Elements的方式有很多种:根据id,class,tag,属性(好像是看是否存在这个属性)都可
Elements as = doc.getElementsByTag("firstname");
for (Element e : as) {
// 标签的文本值
System.out.println(e.text());
}
as = doc.getElementsByTag("student");
for (Element e : as) {
// 标签的对应属性的值 这里是rollno属性的值
System.out.println(e.attr("rollno"));
// 获取该标签的所有值 打印的值类似于这种格式:rollno="593" e="ee"
System.out.println(e.attributes());
// 还有一些在html中常用的获取id等等不写了这里主要展示分析xml的方法
// 还有如jquery的选择器的这里省略,在爬虫那里仔细介绍
}
// jsoup和DOM都类似,都采用的建立文档树,可以接受增删改属性,这里好像失效了
// 这里对元素的修改好像确实修改了,但是没有同步到xml中
Element e = doc.getElementsByTag("firstname").last();
System.out.println(doc);
// 这个可以修改一个Element,也可以直接修改多个如Elements,但是不知道为什么这里失效了
// e.attr("class", "class1");
// 增加移除属性 这里好像只支持class
// 修改文本值 不传值即是获取,传值即是修改
e.text(" Hello JSoup");
System.out.println(doc);
// e.appendText(" Hello JSoup");
}
}
运行结果
不过这里对于xml的修改好像没成功,不过对于xml生成的Document确实修改了,待解决。。。