21、Java与XML交互:读取与解析实战

Java与XML交互:读取与解析实战

在编程中,我们常常需要存储具有特定结构的信息,并且希望这些信息在一定程度上是人类可读的,甚至可以由人工编辑。XML(可扩展标记语言)就是这样一种强大的工具,它能够很好地满足这些需求。Java为我们提供了丰富的工具来处理XML数据,包括读取、解析和修改等操作。接下来,我们将详细介绍如何使用Java来完成这些任务。

读取XML数据

我们将以 cars.xml 文件为例,学习如何使用Java将XML文件加载到Java对象中。首先,确保 cars.xml 文件存储在Java项目的当前目录下,这样在运行Java程序时就可以直接访问该文件。

以下是用于加载 cars.xml 文件的Java程序:

package loadinganxmlfile; 

import java.io.*; 
import javax.xml.parsers.*; 
import javax.xml.transform.*; 
import javax.xml.transform.dom.*; 
import javax.xml.transform.stream.*; 
import org.w3c.dom.*; 
import org.xml.sax.*; 

public class LoadingAnXMLFile { 
    public static void main(String[] args) { 

        try { 
            //Write code that can throw errors here 
        } 
        catch (ParserConfigurationException pce) { 
            System.out.println(pce.getMessage()); 
        } 
        catch (SAXException se) { 
            System.out.println(se.getMessage()); 
        } 
        catch (IOException ioe) { 
            System.err.println(ioe.getMessage()); 
        } 
    } 

    private static void PrintXmlDocument(Document xml) 
    { 
        try{ 
            Transformer transformer = 
             TransformerFactory.newInstance().newTransformer(); 
            StreamResult result = new StreamResult
             (new StringWriter()); 
            DOMSource source = new DOMSource(xml); 
            transformer.transform(source, result); 
            System.out.println(result.getWriter().toString()); 
        } 
        catch(TransformerConfigurationException e) 
        { 
            System.err.println("XML Printing Failed"); 
        } 
        catch(TransformerException e) 
        { 
            System.err.println("XML Printing Failed"); 
        } 
    } 
} 

在开始编写代码之前,需要注意该程序需要导入大量的库。其中, transform 类虽然在后续代码中并非必需,但我编写了一个名为 PrintXmlDocument() 的函数,用于在成功加载XML文档后将其打印到控制台。

接下来,我们的目标是创建一个 Document 对象,该对象包含 cars.xml 文件中的信息。创建 Document 对象的步骤如下:
1. 实例化 DocumentBuilderFactory :使用 DocumentBuilderFactory 类的静态方法 newInstance() 来创建一个 DocumentBuilderFactory 实例。

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
  1. 获取 DocumentBuilder 对象 :调用 factory newDocumentBuilder() 方法来获取一个 DocumentBuilder 对象。
DocumentBuilder builder = factory.newDocumentBuilder(); 
  1. 构建 Document 对象 :使用 builder parse() 方法来解析 cars.xml 文件,并将结果存储在 Document 对象中。
Document dom = builder.parse("cars.xml"); 

最终, main() 方法的代码如下:

public static void main(String[] args) { 
    DocumentBuilderFactory factory = 
    DocumentBuilderFactory.newInstance(); 
    try { 
        // Write code that can throw errors here... 
        DocumentBuilder builder = 
        factory.newDocumentBuilder(); 
        Document dom = builder.parse("cars.xml"); 

        PrintXmlDocument(dom); 
    } 
    catch (ParserConfigurationException pce) { 
        System.out.println(pce.getMessage()); 
    }  
    catch (SAXException se) { 
        System.out.println(se.getMessage()); 
    } 
    catch (IOException ioe) { 
        System.err.println(ioe.getMessage()); 
    } 
} 

运行该程序后,我们将得到原始XML文档的文本输出。

解析XML数据

接下来,我们将学习如何解析XML数据。 cars.xml 文件的内容如下:

<?xml version="1.0"?> 
<cars> 
    <owner name="Billy"> 
        <car vin="LJPCBLCX11000237"> 
            <make>Ford</make> 
            <model>Fusion</model> 
            <year>2014</year> 
            <color>Blue</color> 
        </car> 
        <car vin="LGHIALCX89880011"> 
            <make>Toyota</make> 
            <model>Tacoma</model> 
            <year>2013</year> 
            <color>Green</color> 
        </car> 
        <car vin="GJSIALSS22000567"> 
            <make>Dodge</make> 
            <model>Charger</model> 
            <year>2013</year> 
            <color>Red</color> 
        </car> 
    </owner> 
    <owner name="Jane"> 
        <car vin="LLOKAJSS55548563"> 
            <make>Nissan</make> 
            <model>Altima</model> 
            <year>2000</year> 
            <color>Green</color> 
        </car> 
        <car vin="OOKINAFS98111001"> 
            <make>Dodge</make> 
            <model>Challenger</model> 
            <year>2013</year> 
            <color>Red</color> 
        </car> 
    </owner> 
</cars> 

该文件的根节点是 cars ,其中包含两个 owner 节点( Billy Jane ),每个 owner 节点下又包含多个 car 节点。

我们的目标是提取 Jane 所拥有的汽车信息,并将其存储在自定义的 Car 类中,以便使用 Car 类的 toString() 方法将这些信息以格式化的方式打印到控制台。

在解析XML数据之前,我们需要了解一些XML术语。在XML中, element 是具有开始和结束标签的实体,包含其中的所有信息; node 是XML文档的构建块,所有的 element 都是 node ,但并非所有的 node 都是 element

访问 Jane 的XML元素

为了访问 Jane 的汽车信息,我们需要在 main() 函数中添加以下代码:
1. 获取根元素 :使用 dom getDocumentElement() 方法获取XML文档的根元素。

Element doc = dom.getDocumentElement(); 
  1. 获取所有 owner 节点 :调用根元素的 getElementsByTagName() 方法,获取所有 owner 元素,并将结果存储在 NodeList 对象中。
NodeList ownersList = doc.getElementsByTagName("owner"); 
  1. 遍历 owner 节点 :遍历 ownersList ,检查每个 owner 节点的 name 属性是否为 Jane
for(int i = 0; i < ownersList.getLength(); i++) 
{ 
    Element owner = (Element)ownersList.item(i); 
    if(owner.getAttribute("name").equals("Jane")) 
    { 
        NodeList carsList = owner.getElementsByTagName("car"); 
        PrintCars(carsList); 
    } 
} 

此时, main() 方法的代码如下:

public static void main(String[] args) { 
    DocumentBuilderFactory factory = 
    DocumentBuilderFactory.newInstance(); 
    try { 
        DocumentBuilder docBuilder = 
        factory.newDocumentBuilder(); 
        Document dom = docBuilder.parse("cars.xml"); 

        // Now, print out all of Jane's cars 
        Element doc = dom.getDocumentElement(); 
        NodeList ownersList = 
        doc.getElementsByTagName("owner"); 

        for(int i = 0; i < ownersList.getLength(); i++) 
        { 
            Element owner = (Element)ownersList.item(i); 
            if(owner.getAttribute("name").equals("Jane")) 
            { 
                NodeList carsList = 
                owner.getElementsByTagName("car"); 
                PrintCars(carsList); 
            } 
        } 
    } 
    catch (ParserConfigurationException pce) { 
        System.out.println(pce.getMessage()); 
    }  
    catch (SAXException se) { 
        System.out.println(se.getMessage()); 
    }  
    catch (IOException ioe) { 
        System.err.println(ioe.getMessage()); 
    } 
} 
打印 Jane 的汽车详细信息

接下来,我们需要定义 PrintCars() 方法,用于打印 Jane 的汽车详细信息。该方法的定义如下:

public static void PrintCars(NodeList cars) 
{ 
    for(int i = 0; i < cars.getLength(); i++) 
    { 
        Element carNode = (Element)cars.item(i); 
        Car carObj = new Car(); 
        carObj.color = carNode.getElementsByTagName("color").item(0).getTextContent(); 
        carObj.make = carNode.getElementsByTagName("make").item(0).getTextContent(); 
        carObj.model = carNode.getElementsByTagName("model").item(0).getTextContent(); 
        carObj.year = Integer.parseInt(carNode.getElementsByTagName("year").item(0).getTextContent()); 
        carObj.vin = carNode.getAttribute("vin"); 
        System.out.println(carObj.toString()); 
    } 
} 

该方法的具体步骤如下:
1. 遍历 cars 列表 :使用 for 循环遍历 cars 列表中的每个 car 节点。
2. 创建 Car 对象 :为每个 car 节点创建一个 Car 对象。
3. 提取汽车信息 :使用 getElementsByTagName() 方法提取 color make model year 信息,并使用 getAttribute() 方法提取 vin 信息。
4. 打印汽车信息 :调用 Car 对象的 toString() 方法,将汽车信息以格式化的方式打印到控制台。

以下是 Car 类的定义:

package readingxml; 

public class Car { 
    public String vin; 
    public String make; 
    public String model; 
    public int year; 
    public String color; 
    public Car() 
    { 
    } 

    @Override 
    public String toString() 
    { 
        return String.format("%d %s %s %s, vin:%s", year, 
        color, make, model, vin); 
    } 
} 

编译并运行该程序,我们将看到 Jane 所拥有的汽车信息以格式化的方式打印到控制台。

整个读取和解析XML数据的流程可以用以下mermaid流程图表示:

graph TD;
    A[开始] --> B[实例化DocumentBuilderFactory];
    B --> C[获取DocumentBuilder对象];
    C --> D[构建Document对象];
    D --> E[获取根元素];
    E --> F[获取所有owner节点];
    F --> G[遍历owner节点];
    G --> H{是否为Jane};
    H -- 是 --> I[获取Jane的car节点];
    I --> J[打印Jane的汽车信息];
    H -- 否 --> G;
    J --> K[结束];

通过以上步骤,我们成功地使用Java读取和解析了XML数据。XML和Java的结合非常强大,XML不仅人类可读,还包含了有价值的结构化信息,而Java能够很好地理解和处理这些信息。与处理原始文本文件相比,使用XML和Java编写的程序更加易于编写、理解和维护。

Java与XML交互:读取与解析实战

总结与注意事项

在整个使用 Java 读取和解析 XML 数据的过程中,有一些关键要点和注意事项需要我们牢记:

关键要点
  • 库的导入 :在编写 Java 程序处理 XML 时,需要导入大量的库,如 javax.xml.parsers.* javax.xml.transform.* 等。虽然有些库在某些代码中并非必需,但为了后续可能的功能扩展和代码的完整性,建议提前导入。
  • 对象的创建 :创建 Document 对象需要通过 DocumentBuilderFactory DocumentBuilder 来完成,不能直接实例化。这是为了确保 XML 文件的可解析性和数据结构的正确性。
  • XML 术语的理解 :在解析 XML 数据时,要清楚 element node 的区别。 element 是具有开始和结束标签的实体,包含其中的所有信息; node 是 XML 文档的构建块,所有的 element 都是 node ,但并非所有的 node 都是 element
注意事项
  • 异常处理 :在编写代码时,要注意对可能出现的异常进行处理,如 ParserConfigurationException SAXException IOException 等。通过捕获这些异常并进行相应的处理,可以提高程序的健壮性。
  • XML 格式的正确性 :在解析 XML 数据时,假设 XML 文件的格式是正确的。如果 XML 文件格式不正确,可能会导致程序出现异常或解析结果不准确。因此,在实际应用中,建议对 XML 文件进行有效性检查。
扩展应用

除了上述的读取和解析 XML 数据的基本操作,我们还可以进行一些扩展应用,如修改和写入 XML 数据。

修改 XML 数据

假设我们要修改 Jane 的某一辆汽车的信息,例如将 vin="LLOKAJSS55548563" 的汽车颜色改为 Yellow 。可以按照以下步骤进行:
1. 定位要修改的节点 :在 PrintCars() 方法中,找到对应的 carNode
2. 修改节点信息 :使用 carNode.getElementsByTagName("color").item(0).setTextContent("Yellow") 方法修改颜色信息。
3. 保存修改后的 XML 文件 :使用 Transformer 类将修改后的 Document 对象保存到文件中。

以下是修改后的 PrintCars() 方法和保存 XML 文件的代码示例:

public static void PrintCars(NodeList cars) 
{ 
    for(int i = 0; i < cars.getLength(); i++) 
    { 
        Element carNode = (Element)cars.item(i); 
        if (carNode.getAttribute("vin").equals("LLOKAJSS55548563")) {
            carNode.getElementsByTagName("color").item(0).setTextContent("Yellow");
        }
        Car carObj = new Car(); 
        carObj.color = carNode.getElementsByTagName("color").item(0).getTextContent(); 
        carObj.make = carNode.getElementsByTagName("make").item(0).getTextContent(); 
        carObj.model = carNode.getElementsByTagName("model").item(0).getTextContent(); 
        carObj.year = Integer.parseInt(carNode.getElementsByTagName("year").item(0).getTextContent()); 
        carObj.vin = carNode.getAttribute("vin"); 
        System.out.println(carObj.toString()); 
    } 
    try {
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        DOMSource source = new DOMSource(dom);
        StreamResult result = new StreamResult(new File("modified_cars.xml"));
        transformer.transform(source, result);
    } catch (TransformerConfigurationException e) {
        System.err.println("XML Saving Failed");
    } catch (TransformerException e) {
        System.err.println("XML Saving Failed");
    }
} 
写入 XML 数据

如果我们要创建一个新的 XML 文件,可以按照以下步骤进行:
1. 创建 Document 对象 :使用 DocumentBuilderFactory DocumentBuilder 创建一个新的 Document 对象。
2. 创建 XML 元素 :使用 Document 对象的 createElement() 方法创建 XML 元素,并使用 appendChild() 方法将元素添加到父元素中。
3. 设置元素属性和文本内容 :使用 setAttribute() 方法设置元素的属性,使用 setTextContent() 方法设置元素的文本内容。
4. 保存 XML 文件 :使用 Transformer 类将 Document 对象保存到文件中。

以下是创建新 XML 文件的代码示例:

import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class WriteXML {
    public static void main(String[] args) {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.newDocument();

            // 创建根元素
            Element root = doc.createElement("cars");
            doc.appendChild(root);

            // 创建 owner 元素
            Element owner = doc.createElement("owner");
            owner.setAttribute("name", "NewOwner");
            root.appendChild(owner);

            // 创建 car 元素
            Element car = doc.createElement("car");
            car.setAttribute("vin", "NEWVIN123");
            owner.appendChild(car);

            // 创建 make、model、year 和 color 元素
            Element make = doc.createElement("make");
            make.setTextContent("NewMake");
            car.appendChild(make);

            Element model = doc.createElement("model");
            model.setTextContent("NewModel");
            car.appendChild(model);

            Element year = doc.createElement("year");
            year.setTextContent("2024");
            car.appendChild(year);

            Element color = doc.createElement("color");
            color.setTextContent("NewColor");
            car.appendChild(color);

            // 保存 XML 文件
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource source = new DOMSource(doc);
            StreamResult result = new StreamResult(new File("new_cars.xml"));
            transformer.transform(source, result);

            System.out.println("XML file created successfully.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
总结

通过本文的介绍,我们学习了如何使用 Java 读取、解析、修改和写入 XML 数据。XML 和 Java 的结合为我们处理结构化数据提供了强大的工具。在实际应用中,我们可以根据具体需求灵活运用这些技术,实现各种功能。

以下是一个总结表格,对比了读取、解析、修改和写入 XML 数据的操作步骤:
| 操作类型 | 操作步骤 |
| ---- | ---- |
| 读取 XML 数据 | 1. 实例化 DocumentBuilderFactory ;2. 获取 DocumentBuilder 对象;3. 构建 Document 对象 |
| 解析 XML 数据 | 1. 获取根元素;2. 获取所有 owner 节点;3. 遍历 owner 节点,找到目标节点;4. 提取节点信息 |
| 修改 XML 数据 | 1. 定位要修改的节点;2. 修改节点信息;3. 保存修改后的 XML 文件 |
| 写入 XML 数据 | 1. 创建 Document 对象;2. 创建 XML 元素;3. 设置元素属性和文本内容;4. 保存 XML 文件 |

希望本文对你理解和应用 Java 与 XML 的交互有所帮助,让你在处理结构化数据时更加得心应手。

【顶级EI复现】计及连锁故障传播路径的电力系统 N-k 多阶段双层优化及故障场景筛选模型(Matlab代码实现)内容概要:本文介绍了名为《【顶级EI复现】计及连锁故障传播路径的电力系统 N-k 多阶段双层优化及故障场景筛选模型(Matlab代码实现)》的研究资源,重点围绕电力系统中连锁故障的传播机制,提出了一种N-k多阶段双层优化模型,并结合故障场景筛选方法提升系统安全性鲁棒性。该模型通过Matlab代码实现,可用于模拟复杂电力系统在多重故障下的响应特性,支持对关键故障路径的识别优化决策,适用于高水平科研复现工程仿真分析。文中还列举了大量相关技术方向的配套资源,涵盖智能优化算法、电力系统管理、机器学习、路径规划等多个领域,并提供了网盘链接以便获取完整代码资料。; 适合人群:具备电力系统、优化理论及Matlab编程基础的研究生、科研人员及从事能源系统安全分析的工程技术人员,尤其适合致力于高水平论文(如EI/SCI)复现创新的研究者。; 使用场景及目标:①复现顶级期刊关于N-k故障连锁传播的优化模型;②开展电力系统韧性评估、故障传播分析多阶段防御策略设计;③结合YALMIP等工具进行双层优化建模场景筛选算法开发;④支撑科研项目、学位论文或学术成果转化。; 阅读建议:建议读者按照文档提供的目录顺序系统学习,优先掌握双层优化场景筛选的核心思想,结合网盘中的Matlab代码进行调试实验,同时参考文中提及的智能算法电力系统建模范例,深化对复杂电力系统建模优化的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值