XML是流行的数据存储和数据交换技术,本章将讲解XML的定义和作用。(如果没有了解可以去我主页看看Java开发之框架基础技术第1章 反射(2023版本IEDA)来学习)本章将介绍DOM解析,它可以支持对XML节点的新增、删除、修改等功能,除此之外,还将介绍DOM4J解析,DOM4J 是一个开源库,是集易用和高性能于一体的解析方式。
2.1 XML简介
XML是Extensible Markup Language的缩写,即可扩展标记语言,是一种简单的存储语言,使用一系列简单的标记来描述结构化数据。
XML的特点:
- XML与操作系统、编程语言的开发平台都无关。
- 规范统一,实现不同系统之间的数据交互。
2.1.1 XML的文档结构
1.声明(Declaration):
XML文档通常以XML声明开始,它定义了文档的版本和编码方式。这通常位于文档的第一行,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
- version 属性指定了XML的版本号(通常是1.0)。
- encoding 属性指定了文档中使用的字符编码(例如UTF-8)。
2.标签(Label):
在XML中,通过用尖括号<>括起来的各种标签(Tag)来标记数据,标签成对使用来界定字符数据。例如,<author>
Holle</author>
中,<author>
是开始标签,</author>
是结束标签,Holle是标签描述的内容,表示作者信息。
注意
XML标签必须正确结束并正确地嵌套,缺少结束标签及如下的嵌套方式是错误的。
3.元素(Elements):
XML文档由一系列的元素组成。元素由开始标签、结束标签和(可选的)内容组成。开始标签和结束标签包含元素的名称,而内容则是元素所包含的文本或其他元素。
<book>
<title>你好!</title>
<author>Holle</author>
</book>
<book>
、<title>
和<author>
是元素的开始标签。</book>
、</title>
和</author>
是元素的结束标签。- “你好!” 和 “Holle” 是元素的内容。
4.根元素(Root Element):
每个XML文档必须有且仅有一个根元素,如"<books>``</books>
"。
根元素的特点如下。
- 根元素是一个完全包括文档中其他所有元素的元素。
- 根元素的起始标签要放在所有其他元素的起始标签之前。
- 根元素的结束标签要放在所有其他元素的结束标签之后。
5.属性(Attributes):
元素可以有属性,这些属性提供了关于元素的额外信息。属性总是包含在开始标签中,并且由名称和值组成,使用等号 (=) 分隔,并用引号包围值。
<book id="123">
<title>你好!</title>
<author>Holle</author>
</book>
- id=“123” 是
<book>
元素的一个属性。
语法:
<元素名 属性名="属性值">
//属性值用引号包裹。
注意
(1)一个元素可以有多个属性,多个属性之间用空格隔开,基本格式如下:
<元素名 属性名=“属性值” 属性名=“属性值”/>
(2)属性值中不能直接包含<、"、&。
(3)属性可以加在任何一个元素的起始标签上,但不能加在结束标签上。
6.XML中的特殊字符的处理(Processing of Special Characters in XML):
在XML中,有时在元素的文本中会涉及一些特殊字符(如<、>、'、"、&),而XML文档结构本身就用到这几个特殊字符,这会引起文档结构解析错误。有以下两种办法可以正常地解析包含特殊字符的内容。
(1)对这5个字符进行转义,也就是使用XML中的预定义实体代替这些字符。XML中的预定义实体和特殊字符的对应关系如下表所示。
<center>
表2-1XML中的预定义实体和特殊字符的对应关系
特殊字符 | 实体名称 |
---|---|
< | < |
> | > |
& | & |
" | " |
’ | ' |
(2)在元素的文本中使用CDATA节处理。CDATA节中的所有字符都会被当作元素字符数据的常量部分,而不是XML标签。定义CDATA节的语法如下(推荐)
语法:
<![CDATA[
要显示的字符
]]>
7.注释(Comments):
XML文档中可以包含注释,这些注释不会被解析器处理,只是作为文档中的说明存在。注释以<!--开始,以-->
结束。
<!-- This is a comment in XML -->
<book>
<title>你好!</title>
<author>Holle</author>
</book>
8.格式良好的XML文档(A well formed XML document):
格式良好的XML文档需要遵循如下规则。
- 有XML声明语句。
- 有且仅有一个根元素。
- 标签大小写敏感。
- 属性值用双引号包裹。
- 标签成对/空标签关闭。
- 元素正确嵌套。
9.空白字符(Whitespace):
XML文档中的空白字符(包括空格、制表符和换行符)通常会被保留,除非在元素内容中使用CDATA部分或实体引用(如 )。
10.处理指令(Processing Instructions):
处理指令是XML文档中可以出现的特殊指令,用于告知应用程序如何处理文档。处理指令以<?开始,以?>结束,并且不是XML的一部分,而是用于应用程序特定的目的。
<?xml-stylesheet type="text/css" href="style.css"?>
上面的处理指令用于链接一个CSS样式表到XML文档。
11.实体引用(Entity References):
在XML中,某些字符具有特殊含义(如<和&),因此不能直接在元素内容中使用。相反,应该使用实体引用来表示这些字符。例如,<应写作<
,&应写作&
。
请注意,XML文档必须有一个根元素,即所有其他元素都必须嵌套在根元素内部。此外,XML文档中的元素和属性名称是区分大小写的。
2.1.2 XML应用
在Java中,你可以使用javax.xml.parsers包中的DocumentBuilderFactory和DocumentBuilder类来解析XML文件。以下是一个简单的Java代码示例,展示了如何使用这些类来读取和解析XML文件:
首先,确保你的XML文件(例如students.xml)是有效的,并且与上面的示例类似:
<?xml version="1.0" encoding="UTF-8"?>
<students>
<student>
<name>张三</name>
<age>20</age>
<major>计算机科学</major>
</student>
<student>
<name>李四</name>
<age>22</age>
<major>电子工程</major>
</student>
</students>
然后,你可以使用以下Java代码来解析这个XML文件:
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import java.io.File;
public class XMLReader {
public static void main(String[] args) {
try {
File xmlFile = new File("students.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(xmlFile);
// 获取根元素
doc.getDocumentElement().normalize();
Element rootElement = doc.getDocumentElement();
// 遍历所有学生
NodeList studentList = rootElement.getElementsByTagName("student");
for (int i = 0; i < studentList.getLength(); i++) {
Element student = (Element) studentList.item(i);
// 获取每个学生的信息
String name = getTagValue("name", student);
String age = getTagValue("age", student);
String major = getTagValue("major", student);
System.out.println("Name: " + name + ", Age: " + age + ", Major: " + major);
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 辅助方法,用于从Element对象中获取标签的值
private static String getTagValue(String sTag, Element eElement) {
NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
Node nValue = (Node) nlList.item(0);
return nValue.getNodeValue();
}
}
这段代码首先使用DocumentBuilderFactory和DocumentBuilder来解析XML文件,并获取Document对象。然后,它找到根元素并遍历所有<student>
元素。对于每个<student>
元素,它使用辅助方法getTagValue来获取<name>
、<age>
和<major>
标签的值,并将这些值打印到控制台。
请注意,你可能需要处理XML中的空白字符和特殊字符,以及可能的null值或异常。这个示例中的getTagValue方法假设每个标签都有一个非空的文本值,并且没有检查这一点。在实际应用中,你可能需要添加额外的错误处理逻辑。
2.2 解析XML概述
在实际应用中,经常需要对XML文档进行各种操作,如在应用程序启动时读取XML配置文件信息,或者把数据库中的内容读取出来转换为XML文档形式,这些时候都会用到XML文档的解析技术。
目前常用的XML解析技术有4种
1.DOM
DOM是基于XML的树结构来完成解析的,DOM解析XML文档时,会根据读取的文档,构建一个驻留在内存中的,所以非常方便于各种操作,支持删除、修改、重新排列等多种功能。
当使用DOM(Document Object Model)来解析XML时,你可以按照以下步骤编写Java代码:
首先,确保你的项目包含了处理XML所需的库。在Java中,这些库通常是内置的,包含在javax.xml.parsers包中。
以下是一个简单的DOM解析XML的Java代码示例:
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import java.io.File;
import java.io.IOException;
public class XMLDOMParser {
public static void main(String[] args) {
// XML文件路径
String xmlFilePath = "students.xml";
try {
// 1. 创建DocumentBuilderFactory对象
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 2. 通过DocumentBuilderFactory对象创建DocumentBuilder对象
DocumentBuilder builder = factory.newDocumentBuilder();
// 3. 使用DocumentBuilder对象的parse方法解析XML文件,并返回Document对象
Document document = builder.parse(new File(xmlFilePath));
// 4. 规范化文档以解析所有实体引用
document.getDocumentElement().normalize();
// 5. 获取XML文档的根元素
Element rootElement = document.getDocumentElement();
// 假设根元素是<students>
System.out.println("Root element: " + rootElement.getNodeName());
// 6. 遍历根元素下的子元素(例如遍历<student>元素)
NodeList studentList = rootElement.getElementsByTagName("student");
// 7. 遍历每个<student>元素,并获取其内部子元素(如<name>、<age>、<major>)的值
for (int i = 0; i < studentList.getLength(); i++) {
Element student = (Element) studentList.item(i);
// 获取子元素的值
String name = getTagValue("name", student);
String age = getTagValue("age", student);
String major = getTagValue("major", student);
// 打印学生的信息
System.out.println("Student " + (i + 1) + ":");
System.out.println("Name: " + name);
System.out.println("Age: " + age);
System.out.println("Major: " + major);
System.out.println();
}
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
}
}
// 辅助方法,用于从Element中获取指定标签的值
private static String getTagValue(String tagName, Element element) {
NodeList nodeList = element.getElementsByTagName(tagName).item(0).getChildNodes();
Node node = (Node) nodeList.item(0);
return node.getNodeValue();
}
}
这个示例代码定义了一个XMLDOMParser类,其中包含一个main方法,用于演示如何使用DOM解析XML文件。它还包含了一个辅助方法getTagValue,用于从给定的Element对象中提取指定标签的值。
请注意,XML文件students.xml应该位于与你的Java类相同的目录下,或者你需要提供完整的文件路径。此外,XML文件的结构应该与代码中的标签名匹配,例如:
<students>
<student>
<name>John Doe</name>
<age>20</age>
<major>Computer Science</major>
</student>
<!-- 其他学生... -->
</students>
2.SAX
SAX是基于事件的解析,它是为了解决DOM解析的资源消耗而出现的。它不像DOM那样需要建立一颗完整的文档树,而是通过事件处理器完成对文档的解析。因为SAX解析不用事先调入整个文档,所以它的优势就是占用资源少,内存消耗小。
当使用SAX(Simple API for XML)来解析XML时,你需要实现一些SAX接口中的方法,如ContentHandler,以处理XML文档中的事件。以下是一个简单的Java SAX解析器示例:
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;
import java.io.File;
import java.io.IOException;
public class XMLSAXParser {
public static void main(String[] args) {
// XML文件路径
String xmlFilePath = "students.xml";
try {
// 1. 创建SAXParserFactory对象
SAXParserFactory factory = SAXParserFactory.newInstance();
// 2. 通过SAXParserFactory对象创建SAXParser对象
SAXParser saxParser = factory.newSAXParser();
// 3. 创建DefaultHandler对象,该对象需要实现ContentHandler接口
DefaultHandler handler = new DefaultHandler() {
private String currentElement = null;
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
currentElement = qName;
if (currentElement.equals("student")) {
// 处理<student>标签开始时的逻辑(如果有的话)
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
currentElement = "";
if (qName.equalsIgnoreCase("name") || qName.equalsIgnoreCase("age") || qName.equalsIgnoreCase("major")) {
// 可以在这里处理元素的结束,但通常我们会在characters()方法中处理文本内容
}
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (currentElement.equalsIgnoreCase("name")) {
System.out.println("Name: " + new String(ch, start, length).trim());
} else if (currentElement.equalsIgnoreCase("age")) {
System.out.println("Age: " + new String(ch, start, length).trim());
} else if (currentElement.equalsIgnoreCase("major")) {
System.out.println("Major: " + new String(ch, start, length).trim());
}
}
};
// 4. 使用SAXParser对象的parse方法解析XML文件,并传入Handler
saxParser.parse(new File(xmlFilePath), handler);
} catch (Exception e) {
e.printStackTrace();
}
}
}
这个示例代码定义了一个XMLSAXParser类,它使用SAX来解析XML文件。在main方法中,我们创建了SAXParserFactory和SAXParser对象,并定义了一个继承自DefaultHandler的匿名内部类来处理SAX事件。
在startElement方法中,我们检查当前元素的名称,并可以执行与该元素开始相关的任何逻辑(尽管在这个例子中我们没有)。
在characters方法中,我们检查当前元素的名称,并打印出元素的文本内容。
注意
SAX解析器可能会将连续的文本内容分割成多个characters事件,因此我们通常需要在该方法中处理文本内容。
在endElement方法中,我们可以执行与元素结束相关的任何逻辑(尽管在这个例子中我们并没有)。
最后,我们使用SAXParser对象的parse方法解析XML文件,并传入我们定义的Handler。
请确保XML文件students.xml具有与示例代码中的标签匹配的结构。
注意
DOM是W3C组织提供的解析XML文档的标准接口,SAX是社区产物,但也是一种事实上的标准。DOM和SAX只是定义了一些接口,以及部分默认实现(使用空方法实现接口)。
3.JDOM
DOM是不针对语言的,而JDOM是针对java的特定文档模型,它简化了与XML的交互并且比使用DOM更快。JDOM与DOM有两方面不同,首先,JDOM仅使用具体类而不使用接口。这在某些方面简化了APL,但是也限制了灵活性。
JDOM (Java Document Object Model) 是一个用于处理 XML 的 Java 库,它提供了一种简单直观的方式来解析、创建、修改和序列化 XML 文档。以下是一个使用 JDOM 解析 XML 文件的简单示例代码:
首先,确保你的项目中包含了 JDOM 的依赖。如果你使用 Maven,可以在 pom.xml 文件中添加以下依赖:
<dependency>
<groupId>org.jdom</groupId>
<artifactId>jdom2</artifactId>
<version>2.0.6</version>
</dependency>
接下来是一个使用 JDOM 解析 XML 文件的 Java 示例:
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import java.io.File;
import java.io.IOException;
public class JDOMExample {
public static void main(String[] args) {
try {
// 创建一个SAXBuilder实例
SAXBuilder builder = new SAXBuilder();
// 解析XML文件
File xmlFile = new File("students.xml");
Document document = builder.build(xmlFile);
// 获取根元素
Element root = document.getRootElement();
// 遍历XML结构
for (Element element : root.getChildren("student")) {
String name = element.getChildText("name");
String age = element.getChildText("age");
String major = element.getChildText("major");
System.out.println("Name: " + name);
System.out.println("Age: " + age);
System.out.println("Major: " + major);
System.out.println();
}
} catch (IOException | JDOMException e) {
e.printStackTrace();
}
}
}
在这个示例中,我们假设 students.xml 文件的内容如下:
<students>
<student>
<name>John Doe</name>
<age>25</age>
<major>Computer Science</major>
</student>
<student>
<name>Jane Smith</name>
<age>22</age>
<major>Mathematics</major>
</student>
<!-- 更多学生... -->
</students>
在这个 XML 文件中,<students>
是根元素,它包含多个<student>
子元素,每个 <student>
元素又包含 <name>
、<age>
和 <major>
子元素。
在 Java 代码中,我们使用 SAXBuilder 来解析 XML 文件,并使用 getRootElement 方法获取根元素。然后,我们遍历根元素下的所有 <student>
子元素,并使用 getChildText 方法获取每个<student>
元素下的 <name>
、<age>
和 <major>
元素的文本内容。最后,我们将这些信息打印到控制台。
4.DOM4J
DOM4J是一个非常优秀的Java XML API,具有性能优异功能强大和易用的特点,同时它也是一个开源库。DOM4J用于在Java平台上使用Java集合框架处理XML、XPath和XSLT,并与DOM、SAX和JAXP完全集成。
DOM4J 是另一个用于处理 XML 的 Java 库,它提供了类似于 JDOM 的功能,但具有自己的 API 和一些不同的特性。以下是使用 DOM4J 来解析 XML 文件的示例代码:
首先,确保你的项目中包含了 DOM4J 的依赖。如果你使用 Maven,可以在 pom.xml 文件中添加以下依赖:
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.3</version>
</dependency>
<!-- 如果你需要处理XML Schema,那么还需要下面的依赖 -->
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.2.0</version>
</dependency>
<!-- 如果你使用XPath表达式,确保你有这个依赖 -->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j-xpath</artifactId>
<version>2.1.3</version>
</dependency>
接下来是一个使用 DOM4J 解析 XML 文件的 Java 示例:
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
public class DOM4JExample {
public static void main(String[] args) {
try {
// 创建一个SAXReader实例
SAXReader reader = new SAXReader();
// 解析XML文件
File xmlFile = new File("students.xml");
Document document = reader.read(xmlFile);
// 获取根元素
Element root = document.getRootElement();
// 遍历XML结构
for (Object obj : root.elements("student")) {
Element student = (Element) obj;
String name = student.elementText("name");
String age = student.elementText("age");
String major = student.elementText("major");
System.out.println("Name: " + name);
System.out.println("Age: " + age);
System.out.println("Major: " + major);
System.out.println();
}
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
在这个示例中,我们假设 students.xml 文件的内容与之前的 JDOM 示例相同。我们使用 SAXReader 来解析 XML 文件,并使用 getRootElement 方法获取根元素。然后,我们遍历根元素下的所有 <student>
子元素,并使用 elementText 方法获取每个 <student>
元素下的 <name>
、<age>
和<major>
子元素的文本内容。最后,我们将这些信息打印到控制台。
2.3 使用DOM读取XML数据
2.3.1 DOM概念
DOM是Document Object Model的简称,即文档对象模型,DOM把XML文件映射成一棵倒挂的"树",以根元素为根节点,每个节点都以对象形式存在。
可以使用Oracle公司提供的JAXP(Java API for XML Processing)来解析XML。JAXP包含3个包。这3个包都在JDK中,DOM解析使用到的类都在这此包中。
- Org.w3c.dom:W3C推荐的用于使用DOM解析XML文档的接口。
- Org.xml.sax:用于使用SAX解析XML文档的接口。
- Java.xml.parsers:解析器工厂工具,获得并配置特殊的分析器。
使用DOM解析XML文档的步骤如下。
(1)创建解析器工厂对象,即DocumentBuilderFactory对象。
(2)由解析器工厂对象创建解析器对象,即DocumentBuilder对象。
(3)由解析器对象对指定的XML文件进行解析,构建相应的DOM树,创建Document对象。
(4)以Document对象为起点对DOM树的节点进行增加、删除、修改、查询等操作。
使用DOM解析XML时主要使用以下对象。
1.Node对象
Node对象是DOM结构中最基本的对象,代表了文档树中的一个抽象节点。在实际使用的时候,很少会真正用到Node对象,一般会用到如Document、Element、Text等Node对象的子对象来操作文档。Node对象的主要方法如下:
- getChildNodes():返回包含此节点所有子节点的NodeList。
- getFirstChild():如果节点存在子节点,则返回第一个子节点。
- getLastChild():如果节点存在子节点,则返回最后一个子节点。
- getNextSibing():返回在DOM树中这个节点的下一个兄弟节点。
- getPreviousSibings():返回在DOM树中这个节点的上一个兄弟节点。
- getNodeName():返回节点的名称。
- getNodeValue():返回节点的值。
- getNodeType():返回节点的类型。
2.NodeList对象
顾名思义,NodeList对象是指包含了一个或多个节点(Node)的列表。可以简单地把它看成一个Node数组,也可以通过方法来获得列表中的元素,NodeList对象的常用方法如下。
- getLength():返回列表的长度。
- item(int index):返回指定位置的Node对象。
3.Document对象
Document对象代表整个XML文档,所有其他的Node都以一定的顺序包含在Document对象之内,排列成一个树状结构,可以通过遍历这棵"树"来得到XML文档的所有内容。
Document对象的主要方法如下。
- getElementsByTagName(String name):返回一个NodeList对象,它包含了所有个定标签名称的标签。
- getDocumentElement():返回一个代表这个DOM树的根节点的Element对象,也就是代表XML文档根元素的对象。
4.Element对象
Element对象代表XML文档中的标签元素,继承自Node,也是Node最主要的子对象。在标签中可以包含属性,因而Element对象中也有存取其属性的方法,如下所示。
- getAttribute(String attribute name):返回标签中给定属性名称的属性的值。
- getElementByTagName(String name):返回具有给定标签名的所有后代Element的NodeList。
注意
XML文档中的空白符也会被作为对象映射在DOM树中。因而,直接调用Node对象的getChildNodes()方法有时候会有些问题,有时不能够返回所期望的NodeList元素对象列表。解决的办法如下。
(1)使用Element的getElementsByName(String name),返回的NodeList就是所期待的对象。然后,可以用item()方法提取想要的元素。
(2)调用Node的getChildNodes()方法得到NodeList对象,每次通过item()方法提取Node对象后判断node.getNodeType()==Node.ELEMENT_NODE,即判断是否是元素节点,如果为true,则表示是想要的元素。
2.4 使用DOM维护XML数据
在XML应用中,需要经常对数据进行维护,首先来学习如何在XML文档添加数据。本章中,我们主要使用DOM和DOM4J两种方式来实现。
在Java中,你可以使用Java的内置库,如javax.xml.parsers,来解析、修改和序列化XML数据。以下是一个使用DOM(Document Object Model)来维护XML数据的简单示例。
首先,假设你有一个XML文件(example.xml)如下所示:
<students>
<student>
<id>1</id>
<name>John Doe</name>
</student>
<student>
<id>2</id>
<name>Jane Smith</name>
</student>
</students>
现在,你想添加一个新的学生到这个XML文件中。以下是如何使用DOM来实现这个目标的Java代码:
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
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 java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class XmlDomExample {
public static void main(String[] args) {
try {
// 加载XML文档
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(new File("example.xml"));
// 获取根元素
Node rootNode = doc.getFirstChild();
// 创建一个新的学生元素
Element newStudent = doc.createElement("student");
// 创建子元素并添加到新的学生元素
Element id = doc.createElement("id");
id.appendChild(doc.createTextNode("3"));
newStudent.appendChild(id);
Element name = doc.createElement("name");
name.appendChild(doc.createTextNode("Bob Johnson"));
newStudent.appendChild(name);
// 将新的学生元素添加到根元素的子节点列表
rootNode.appendChild(newStudent);
// 将修改后的文档写回到文件
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File("example_updated.xml"));
transformer.transform(source, result);
System.out.println("XML文件已更新");
} catch (Exception e) {
e.printStackTrace();
}
}
}
这个示例代码做了以下几件事:
- 使用DocumentBuilder解析XML文件到Document对象。
- 创建一个新的student元素,并添加id和name子元素。
- 将新的student元素添加到根元素的子节点列表。
- 使用Transformer将修改后的Document对象写回到新的XML文件。
注意
这个例子中的XML文件(example.xml)和更新后的XML文件(example_updated.xml)是两个不同的文件。如果你想要直接修改原始文件,你可能需要首先读取原始文件到一个Document对象,然后修改它,最后覆盖原始文件。但是,这通常不是推荐的做法,因为它可能会导致数据丢失或损坏,如果程序在写入文件时崩溃。相反,最好创建一个新的文件,并在确保数据完整后,再删除原始文件并重命名新文件。
2.5 使用DOM4J解析XML
2.5.1 DOM4J API概述
DOM4J使用起来非常简单。只要了解基本的XML-DOM模型就能使用。DOM4J的主要接口都在org.dom4j这个包里定义。
- Attribute:定义了XML的属性。
- Branch:为能够包含子节点的节点定义了公共行为。
- CDATA:定义了XML CDATA区域。
- CharacterData:标识接口,标识基于字符的节点。
- Comment:定义了XML注释的行为。
- Document:定义XML文档。
- DocumentType:定义XML DOCTYPE声明。
- Element:定义XML元素。
- ElementPath:被ElementHandler使用,用于取得当前正在处理的路径层次信息。
- Entity:定义XML实体。
- Node:为所有的DOM4J中的XML节点定义了多态行为。
- NodeFilter:定义了在dom4j节点产生的一个滤镜或谓词(Predicate)的行为。
- ProcessingInstrnction:定义XML处理指令。
- Text:定义XML文本节点。
- Visitor:用于实现Visitor模式。
- XPath:通过分析一个字符串提供一个XPath表达式。
2.5.2 使用DOM4J操作XML数据
在Java中,除了使用Java内置的XML解析库之外,还可以使用第三方库如DOM4J来更方便地操作XML数据。DOM4J是一个流行的Java库,用于处理XML、HTML和XPath。以下是一个使用DOM4J库来操作XML数据的简单Java代码示例:
首先,确保你的项目中包含了DOM4J的依赖。如果你使用Maven,可以在pom.xml中添加以下依赖:
<dependencies>
<!-- DOM4J dependency -->
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.3</version> <!-- 使用你需要的版本 -->
</dependency>
<!-- 如果你还需要XPath支持 -->
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.2.0</version>
</dependency>
</dependencies>
接下来是一个使用DOM4J添加新学生到XML文件的Java代码示例:
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class Dom4jExample {
public static void main(String[] args) {
try {
// 使用SAXReader读取XML文件
SAXReader reader = new SAXReader();
Document document = reader.read(new File("example.xml"));
// 获取根元素
Element root = document.getRootElement();
// 创建一个新的学生元素
Element newStudent = DocumentHelper.createElement("student");
// 创建并设置id和name子元素
Element id = DocumentHelper.createElement("id");
id.setText("3");
newStudent.add(id);
Element name = DocumentHelper.createElement("name");
name.setText("Bob Johnson");
newStudent.add(name);
// 将新的学生元素添加到根元素的子节点列表
root.add(newStudent);
// 将修改后的文档写回到文件
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter writer = new XMLWriter(new FileWriter(new File("example_updated.xml")), format);
writer.write(document);
writer.close();
System.out.println("XML文件已更新");
} catch (DocumentException | IOException e) {
e.printStackTrace();
}
}
}
这个示例做了以下几件事:
- 使用SAXReader读取XML文件到Document对象。
- 获取根元素。
- 创建一个新的student元素,并设置其id和name子元素。
- 将新的student元素添加到根元素的子节点列表。
- 使用OutputFormat和XMLWriter将修改后的Document对象写回到新的XML文件。
注意
这个示例中的example.xml是原始XML文件,example_updated.xml是更新后的XML文件。同样,建议先将数据写入新文件,并在验证无误后再覆盖原始文件。