大家好,又见面了,我是你们的朋友全栈君。
目录
Java中有两种解析XML文件的方式:DOM解析和SAX解析。
一、使用DOM4j进行XML的DOM解析
DOM解析是一次性将整个XML文档加载进内存,在内存中构建Document的对象树,通过Document对象,得到树上的节点对象,通过节点对象访问(操作)到XML文档的内容。
通常使用Dom4j工具进行XML的DOM解析,首先要到Dom4j的官网https://dom4j.github.io/下载包并加载到IDE开发工具中(例如eclipse)。
1.1、使用DOM4j查询XML文档
XML文档在DOM解析中可以被映射为多种节点,其中比较重要和常见的是元素节点(Element)、属性节点(Attribute)和文本节点(Text)。
查询节点主要可以使用以下方法:
- Document new SAXReader().read(File file) —— 读取XML文档
- Element Document.getRootElement() —— 获取XML文档的根元素节点
- Iterator Element.nodeIterator() —— 获取当前元素节点下的所有子节点
- Iterator<Element> Element.elementIterator(元素名) —— 指定名称的所有子元素节点
- Iterator<Attribute> Element.attributeIterator() —— 获取所有子属性节点
- List<Element> Element.elements() —— 获取所有子元素节点
- List<Attribute> Element.attributes() —— 获取所有子属性字节
- Element Element.element(元素名) —— 指定名称的第一个子元素节点
- Attribute Element.attribute(属性名) —— 获取指定名称的子属性节点
- String Element.attributeValue(属性名) —— 获取指定名称的子属性的属性值
- String Attribute.getName() —— 获取属性名称
- String Attribute.getValue() —— 获取属性值
- String Element.getText() —— 获取当前元素节点的子文本节点
- String Element.elementText(元素名) —— 获取当前元素节点的指定名称的子文本节点
示例:在eclipse中读取以下students.xml文档的内容,并打印至控制台
<?xml version="1.0" encoding="UTF-8"?>
<Students>
<Student id="001">
<name>张三</name>
<age>19</age>
<gender>男</gender>
<grade>计算机1班</grade>
</Student>
<Student id="002">
<name>李四</name>
<age>20</age>
<gender>男</gender>
<grade>计算机2班</grade>
</Student>
</Students>
package xml;
import java.io.File;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class ReadAndPrintXML {
public static void main(String[] args) throws Exception {
// 创建一个XML解析器对象
SAXReader reader = new SAXReader();
// 读取XML文档,返回Document对象
Document document = reader.read(new File("E:\\xml\\students.xml"));
// 获取根元素节点
Element root = document.getRootElement();
StringBuilder sb = new StringBuilder();
recursion(root, sb);
System.out.println(sb.toString());
}
private static void recursion(Element ele, StringBuilder sb) {
sb.append("<");
// 解析元素节点
sb.append(ele.getName());
// 解析属性节点
List<Attribute> attributes = ele.attributes();
for(Attribute attribute : attributes) {
sb.append(" ");
sb.append(attribute.getName());
sb.append("=");
sb.append(attribute.getValue());
}
sb.append(">");
// 解析文本节点
sb.append(ele.getText());
// 递归解析元素节点
List<Element> elements = ele.elements();
for(Element element : elements) {
recursion(element, sb);
}
sb.append("<" + ele.getName() + "/>\n");
}
}
1.2、使用DOM4j修改XML文档
①写出内容到xml文档
XMLWriter writer = new XMLWriter(OutputStream out, OutputFormat format)
writer.write(Document doc)
上面的OutputFormat对象可以由OutputFormat类的两个静态方法来生成:
- createPrettyPrint() —— 生成的OutputFormat对象,使写出的XML文档整齐排列,适合开发环境使用
- createCompactFormat() —— 生成的OutputFormat对象,使写出的XML文档紧凑排列,适合生产环境使用
②生成文档或增加节点
- Document DocumentHelper.createDocument() —— 生成一个新的XML Document对象
- Element Element.addElement(元素节点名) —— 增加一个子元素节点
- Attribute Element.addAttribute(属性名,属性值) —— 增加一个子属性节点
③修改节点
- Attribute.setValue(属性值) —— 修改属性节点值
- Attribute Element.addAttribute(同名属性名,属性值) —— 修改同名的属性节点值
- Element.setText(内容) —— 修改文本节点内容
④删除节点
- Element.detach() —— 删除元素节点
- Attribute.detach() —— 删除属性节点
示例:生成一个和前面的students.xml一样的XML文档,并写入到磁盘
import java.io.FileOutputStream;
import java.io.UnsupportedEncodingException;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
public class WriteXML {
public static void main(String[] args) throws Exception {
// 创建一个XMLWriter对象
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter writer = new XMLWriter(new FileOutputStream("E:\\xml\\students2.xml"), format);
// 生成一个新的Document对象
Document doc = DocumentHelper.createDocument();
// 增加Students元素节点
Element students = doc.addElement("Students");
// 增加两个Student元素节点
Element student1 = students.addElement("student");
Element student2 = students.addElement("student");
// 为两个Student元素节点分别增加id属性节点
student1.addAttribute("id", "001");
student2.addAttribute("id", "002");
// 分别增加name, age, gender, grade元素子节点
student1.addElement("name").setText("张三");
student1.addElement("age").setText("19");
student1.addElement("gender").setText("男");
student1.addElement("grade").setText("计算机1班");
student2.addElement("name").setText("李四");
student2.addElement("age").setText("20");
student2.addElement("gender").setText("男");
student2.addElement("grade").setText("计算机2班");
// 将Document对象写入磁盘
writer.write(doc);
writer.close();
}
}
1.3、使用xPath技术
使用dom4j查询比较深的层次结构的节点时,比较麻烦,因此可以使用xPath技术快速获取所需的节点对象。
首先也需要在eclipse中导入xPath的jar包,我这里使用的是jaxen-1.1-beta-6.jar
①使用xPath的方法
- List<Node> Document.selectNodes(xpath表达式) —— 查询多个节点对象
- Node Document.selectSingleNode(xpath表达式) —— 查询一个节点对象
②xPath表达式语法
- / —— 绝对路径,表示从xml文档的根位置开始
- // —— 相对路径,表示不分任何层次结构的选择元素
- * —— 表示匹配所有元素
- [] —— 条件,表示选择符合条件的元素
- @ —— 属性,表示选择属性节点
- and —— 关系,表示条件的与关系
- text() —— 文本,表示选择文本内容
示例:
import java.io.File;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
public class XPathTest {
public static void main(String[] args) throws Exception {
SAXReader reader = new SAXReader();
Document doc = reader.read(new File("E:\\xml\\students.xml"));
// 选择所有的student元素
List<Node> list = doc.selectNodes("//Student");
// 选择文本内容是"张三"的name元素
Element name = (Element) doc.selectSingleNode("//name[text()='张三']");
// 选择所有id属性节点
List<Node> list2 = doc.selectNodes("//@id");
// 选择id属性为002的student元素
Element student = (Element) doc.selectSingleNode("//Student[@id='002']");
// 选择根元素节点的所有子节点
Element root = doc.getRootElement();
List<Node> list3 = doc.selectNodes("/Students/*");
}
}
二、使用SAX方式解析XML文档
SAX方式解析的原理是:在内存中加载一点,读取一点,处理一点。对内存要求比较低。
JDK内置了SAX解析工具,存放在org.xml.sax包中。
2.1、使用SAX解析方式查询XML文档
核心的API类:
1、SAXParser.parse(File f, DefaultHandler dh)方法:解析XML文件
参数一File:表示读取的XMl文件
参数二DefaultHandler:SAX事件处理程序,包含SAX解析的主要逻辑。开发人员需要写一个DefaultHandler的子类,然后将其对象作为参数传入parse()方法。
2、 SAXParserFactory类,用于创建SAXParser对象,创建方式如下:
SAXParser parse = SAXParserFactory.newInstance().newSAXParser();
3、DefaultHandler类的主要方法:
- void startDocument() —— 在读到文档开始时调用
- void endDocument() —— 在读到文档结束时调用
- void startElement(String uri, String localName, String qName, Attributes attributes) —— 读到开始标签时调用
- void endElement(String uri, String localName, String qName) —— 读到结束标签时调用
- characters(char[] ch, int start int length) —— 读到文本内容时调用
示例:使用SAX解析方式读取上面students.xml的内容,并打印至控制台。
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 SAXTest {
public static void main(String[] args) throws Exception {
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
parser.parse(new File("E:\\xml\\students.xml"), new MyDefaultHandler());
}
}
class MyDefaultHandler extends DefaultHandler{
@Override
public void startDocument() throws SAXException {
System.out.println("----文档开始解析-------");
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
System.out.print("<" + qName);
for(int i = 0; i < attributes.getLength(); i++) {
System.out.print(" " + attributes.getQName(i) + "=" + attributes.getValue(i));
}
System.out.print(">");
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
System.out.print(new String(ch, start, length));
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
System.out.print("</" + qName + ">");
}
@Override
public void endDocument() throws SAXException {
System.out.println("\n----文档开始解析结束-----");
}
}
2.2、对比DOM解析和SAX解析
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/156676.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...