第二章 XML(2023版本IDEA)


  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中的预定义实体和特殊字符的对应关系

特殊字符实体名称
<&lt;
>&gt;
&&amp;
"&quot;
&apos;

  (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中,某些字符具有特殊含义(如<和&),因此不能直接在元素内容中使用。相反,应该使用实体引用来表示这些字符。例如,<应写作&lt;,&应写作&amp;

  请注意,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();  
        }  
    }  
}

这个示例代码做了以下几件事:

  1. 使用DocumentBuilder解析XML文件到Document对象。
  2. 创建一个新的student元素,并添加id和name子元素。
  3. 将新的student元素添加到根元素的子节点列表。
  4. 使用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();  
        }  
    }  
}

这个示例做了以下几件事:

  1. 使用SAXReader读取XML文件到Document对象。
  2. 获取根元素。
  3. 创建一个新的student元素,并设置其id和name子元素。
  4. 将新的student元素添加到根元素的子节点列表。
  5. 使用OutputFormat和XMLWriter将修改后的Document对象写回到新的XML文件。

注意
  这个示例中的example.xml是原始XML文件,example_updated.xml是更新后的XML文件。同样,建议先将数据写入新文件,并在验证无误后再覆盖原始文件。

  • 34
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值