基于Java实现XML文件的解析与更新

目录
  • 选择一个格式
  • XML 基础
  • 创建一个示例配置文件
  • 使用 Java 解析 XML
  • 使用 Java 访问 XML 的值
  • 使用 Java 更新 XML
  • 如何保证配置不出问题

在你使用 Java 编写软件时实现持久化配置。

当你编写一个应用时,你通常都会希望用户能够定制化他们和应用交互的方式,以及应用与系统进行交互的方式。这种方式通常被称为 “偏好preference” 或者 “设置setting”,它们被保存在一个 “偏好文件” 或者 “配置文件” 中,有时也直接简称为 “配置config”。配置文件可以有很多种格式,包括 INI、JSON、YAML 和 XML。每一种编程语言解析这些格式的方式都不同。本文主要讨论,当你在使用 Java 编程语言 来编写软件时,实现持久化配置的方式。

选择一个格式

编写配置文件是一件相当复杂的事情。我曾经试过把配置项使用逗号分隔保存在一个文本文件里,也试过把配置项保存在非常详细的 YAML 和 XML 中。对于配置文件来说,最重要是要有一致性和规律性,它们使你可以简单快速地编写代码,从配置文件中解析出数据;同时,当用户决定要做出修改时,很方便地保存和更新配置。

目前有 几种流行的配置文件格式。对于大多数常见的配置文件格式,Java 都有对应的库library。在本文中,我将使用 XML 格式。对于一些项目,你可能会选择使用 XML,因为它的一个突出特点是能够为包含的数据提供大量相关的元数据,而在另外一些项目中,你可能会因为 XML 的冗长而不选择它。在 Java 中使用 XML 是非常容易的,因为它默认包含了许多健壮的 XML 库。

XML 基础

讨论 XML 可是一个大话题。我有一本关于 XML 的书,它有超过 700 页的内容。幸运的是,使用 XML 并不需要非常了解它的诸多特性。就像 HTML 一样,XML 是一个带有开始和结束标记的分层标记语言,每一个标记(标签)内可以包含零个或更多数据。下面是一个 XML 的简单示例片段:

<xml>
      <node>
        <element>Penguin</element>
      </node>
    </xml>

在这个 自我描述的self-descriptive 例子中,XML 解析器使用了以下几个概念:

  • 文档Document: 标签标志着一个 文档 的开始, 标签标志着这个文档的结束。
  • 节点Node: 标签代表了一个 节点。
  • 元素Element: Penguin 中,从开头的 < 到最后的 > 表示了一个 元素。
  • 内容Content: 在 元素里,字符串 Penguin 就是 内容。

不管你信不信,只要了解了以上几个概念,你就可以开始编写、解析 XML 文件了。

创建一个示例配置文件

要学习如何解析 XML 文件,只需要一个极简的示例文件就够了。假设现在有一个配置文件,里面保存的是关于一个图形界面窗口的属性:

<xml>
      <window>
        <theme>Dark</theme>
        <fullscreen>0</fullscreen>
        <icons>Tango</icons>
    </window>
    </xml>

创建一个名为 ~/.config/DemoXMLParser 的目录:

$ mkdir ~/.config/DemoXMLParser

在 Linux 中,~/.config 目录是存放配置文件的默认位置,这是在 自由桌面工作组 的规范中定义的。如果你正在使用一个不遵守 自由桌面工作组Freedesktop标准的操作系统,你也仍然可以使用这个目录,只不过你需要自己创建这些目录了。

复制 XML 的示例配置文件,粘贴并保存为 ~/.config/DemoXMLParser/myconfig.xml 文件。

使用 Java 解析 XML

如果你是 Java 的初学者,你可以先阅读我写的 面向 Java 入门开发者的 7 个小技巧。一旦你对 Java 比较熟悉了,打开你最喜爱的集成开发工具(IDE),创建一个新工程。我会把我的新工程命名为 myConfigParser。

刚开始先不要太关注依赖导入和异常捕获这些,你可以先尝试用 javax 和 java.io 包里的标准 Java 扩展来实例化一个解析器。如果你使用了 IDE,它会提示你导入合适的依赖。如果没有,你也可以在文章稍后的部分找到完整的代码,里面就有完整的依赖列表。

Path configPath = Paths.get(System.getProperty("user.home"), ".config", "DemoXMLParser");
    File configFile = new File(configPath.toString(), "myconfig.xml");
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = null;
    builder = factory.newDocumentBuilder();
    Document doc = null;
    doc = builder.parse(configFile);
    doc.getDocumentElement().normalize();

这段示例代码使用了 java.nio.Paths 类来找到用户的主目录,然后在拼接上默认配置文件的路径。接着,它用 java.io.File 类来把配置文件定义为一个 File 对象。

紧接着,它使用了 javax.xml.parsers.DocumentBuilder 和 javax.xml.parsers.DocumentBuilderFactory 这两个类来创建一个内部的文档构造器,这样 Java 程序就可以导入并解析 XML 数据了。

最后,Java 创建一个叫 doc 的文档对象,并且把 configFile 文件加载到这个对象里。通过使用 org.w3c.dom 包,它读取并规范化了 XML 数据。

基本上就是这样啦。理论上来讲,你已经完成了数据解析的工作。可是,如果你不能够访问数据的话,数据解析也没有多少用处嘛。所以,就让我们再来写一些查询,从你的配置中读取重要的属性值吧。

使用 Java 访问 XML 的值

从你已经读取的 XML 文档中获取数据,其实就是要先找到一个特定的节点,然后遍历它包含的所有元素。通常我们会使用多个循环语句来遍历节点中的元素,但是为了保持代码可读性,我会尽可能少地使用循环语句:

NodeList nodes = doc.getElementsByTagName("window");
    for (int i = 0; i < nodes.getLength(); i++) {
     Node mynode = nodes.item(i);
     System.out.println("Property = " + mynode.getNodeName());

     if (mynode.getNodeType() == Node.ELEMENT_NODE) {
       Element myelement = (Element) mynode;

       System.out.println("Theme = " + myelement.getElementsByTagName("theme").item(0).getTextContent());
       System.out.println("Fullscreen = " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());
       System.out.println("Icon set = " + myelement.getElementsByTagName("icons").item(0).getTextContent());
     }
    }

这段示例代码使用了 org.w3c.dom.NodeList 类,创建了一个名为 nodes 的 NodeList 对象。这个对象包含了所有名字匹配字符串 window 的子节点,实际上这样的节点只有一个,因为本文的示例配置文件中只配置了一个。

紧接着,它使用了一个 for 循环来遍历 nodes 列表。具体过程是:根据节点出现的顺序逐个取出,然后交给一个 if-then 子句处理。这个 if-then 子句创建了一个名为 myelement 的 Element 对象,其中包含了当前节点下的所有元素。你可以使用例如 getChildNodes 和 getElementById 方法来查询这些元素,项目中还 记录了 其他查询方法。

在这个示例中,每个元素就是配置的键。而配置的值储存在元素的内容中,你可以使用 .getTextContent 方法来提取出配置的值。

在你的 IDE 中运行代码(或者运行编译后的二进制文件):

$ java ./DemoXMLParser.java
    Property = window
    Theme = Dark
    Fullscreen = 0
    Icon set = Tango

下面是完整的代码示例:

package myConfigParser;
    import java.io.File;
    import java.io.IOException;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.NamedNodeMap;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    import org.xml.sax.SAXException;
    public class ConfigParser {
            public static void main(String[] args) {
                    Path configPath = Paths.get(System.getProperty("user.home"), ".config", "DemoXMLParser");
                    File configFile = new File(configPath.toString(), "myconfig.xml");
                    DocumentBuilderFactory factory =
                    DocumentBuilderFactory.newInstance();
                    DocumentBuilder builder = null;

                    try {
                            builder = factory.newDocumentBuilder();
                    } catch (ParserConfigurationException e) {
                            e.printStackTrace();
                    }

                    Document doc = null;

                    try {
                            doc = builder.parse(configFile);
                    } catch (SAXException e) {
                            e.printStackTrace();
                    } catch (IOException e) {
                            e.printStackTrace();
                    }
            doc.getDocumentElement().normalize();

            NodeList nodes = doc.getElementsByTagName("window");
            for (int i = 0; i < nodes.getLength(); i++) {
               Node mynode = nodes.item(i);
               System.out.println("Property = " + mynode.getNodeName());

               if (mynode.getNodeType() == Node.ELEMENT_NODE) {
                   Element myelement = (Element) mynode;
                   System.out.println("Theme = " + myelement.getElementsByTagName("theme").item(0).getTextContent());
                   System.out.println("Fullscreen = " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());
                   System.out.println("Icon set = " + myelement.getElementsByTagName("icons").item(0).getTextContent());
               } // close if
            } // close for
        } // close method
    } //close class

使用 Java 更新 XML

用户时不时地会改变某个偏好项,这时候 org.w3c.dom 库就可以帮助你更新某个 XML 元素的内容。你只需要选择这个 XML 元素,就像你读取它时那样。不过,此时你不再使用 .getTextContent 方法,而是使用 .setTextContent 方法。

updatePref = myelement.getElementsByTagName("fullscreen").item(0);
    updatePref.setTextContent("1");
    System.out.println("Updated fullscreen to " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());

这么做会改变应用程序内存中的 XML 文档,但是还没有把数据写回到磁盘上。配合使用 javax 和 w3c 库,你就可以把读取到的 XML 内容写回到配置文件中。

TransformerFactory transformerFactory = TransformerFactory.newInstance();
    Transformer xtransform;
    xtransform = transformerFactory.newTransformer();
    DOMSource mydom = new DOMSource(doc);
    StreamResult streamResult = new StreamResult(configFile);
    xtransform.transform(mydom, streamResult);

这么做会没有警告地写入转换后的数据,并覆盖掉之前的配置。

下面是完整的代码,包括更新 XML 的操作:

package myConfigParser;
    import java.io.File;
    import java.io.IOException;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    import javax.xml.transform.Transformer;
    import javax.xml.transform.TransformerException;
    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;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    import org.xml.sax.SAXException;
    public class ConfigParser {
            public static void main(String[] args) {
                    Path configPath = Paths.get(System.getProperty("user.home"), ".config", "DemoXMLParser");
                    File configFile = new File(configPath.toString(), "myconfig.xml");
                    DocumentBuilderFactory factory =
                    DocumentBuilderFactory.newInstance();
                    DocumentBuilder builder = null;

                    try {
                            builder = factory.newDocumentBuilder();
                    } catch (ParserConfigurationException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                    }

                    Document doc = null;

                    try {
                            doc = builder.parse(configFile);
                    } catch (SAXException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                    } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                    }
            doc.getDocumentElement().normalize();
            Node updatePref = null;
    //        NodeList nodes = doc.getChildNodes();
            NodeList nodes = doc.getElementsByTagName("window");
            for (int i = 0; i < nodes.getLength(); i++) {
               Node mynode = nodes.item(i);
               System.out.println("Property = " + mynode.getNodeName());

               if (mynode.getNodeType() == Node.ELEMENT_NODE) {
                   Element myelement = (Element) mynode;
                   System.out.println("Theme = " + myelement.getElementsByTagName("theme").item(0).getTextContent());
                   System.out.println("Fullscreen = " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());
                   System.out.println("Icon set = " + myelement.getElementsByTagName("icons").item(0).getTextContent());
                   updatePref = myelement.getElementsByTagName("fullscreen").item(0);
                   updatePref.setTextContent("2");
                   System.out.println("Updated fullscreen to " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());
               } // close if

            }// close for
            // write DOM back to the file
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer xtransform;
            DOMSource mydom = new DOMSource(doc);
            StreamResult streamResult = new StreamResult(configFile);
            try {
                    xtransform = transformerFactory.newTransformer();
                    xtransform.transform(mydom, streamResult);
            } catch (TransformerException e) {
                    e.printStackTrace();
            }

        } // close method
    } //close class

如何保证配置不出问题

编写配置文件看上去是一个还挺简单的任务。一开始,你可能会用一个简单的文本格式,因为你的应用程序只要寥寥几个配置项而已。但是,随着你引入了更多的配置项,读取或者写入错误的数据可能会给你的应用程序带来意料之外的错误。一种帮助你保持配置过程安全、不出错的方法,就是使用类似 XML 的规范格式,然后依靠你用的编程语言的内置功能来处理这些复杂的事情。

这也正是我喜欢使用 Java 和 XML 的原因。每当我试图读取错误的配置值时,Java 就会提醒我。通常,这是由于我在代码中试图获取的节点,并不存在于我期望的 XML 路径中。XML 这种高度结构化的格式帮助了代码保持可靠性,这对用户和开发者来说都是有好处的。

以上就是基于Java实现XML文件的解析与更新的详细内容,更多关于Java XML解析 更新的资料请关注我们其它相关文章!

(0)

相关推荐

  • java实现简单解析XML文件功能示例

    本文实例讲述了java实现简单解析XML文件功能.分享给大家供大家参考,具体如下: package demo; import java.io.File; import java.io.IOException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException;

  • Java解析XML(4种方式)案例详解

    目录 1.DOM方式 2.SAX方式 3.JDOM方式 4.DOM4J方式 总结 xml文件 <?xml version="1.0" encoding="utf-8" ?> <class> <student> <firstname>cxx1</firstname> <lastname>Bob1</lastname> <nickname>stars1</nicknam

  • JAVA中4种解析XML文件的方法

    XML是一种通用的数据交换格式,它的平台无关性.语言无关性.系统无关性.给数据集成与交互带来了极大的方便.XML在不同的语言环境中解析方式都是一样的,只不过实现的语法不同而已. XML的解析方式分为四种: 1.DOM解析: 2.SAX解析: 3.JDOM解析: 4.DOM4J解析. 其中前两种属于基础方法,是官方提供的平台无关的解析方式:后两种属于扩展方法,它们是在基础的方法上扩展出来的,只适用于java平台. 针对以下XML文件,会对四种方式进行详细描述: <?xml version="

  • Java解析xml的四种方法汇总

    1. DOM(JAXP Crimson解析器) DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准.DOM是以层次结构组织的节点或信息片断的集合.这个层次结构允许开发人员在树中寻找特定信息.分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何工作.由于它是基于信息层次的,因而DOM被认为是基于树或基于对象的.DOM以及广义的基于树的处理具有几个优点.首先,由于树在内存中是持久的,因此可以修改它以便应用程序能对数据和结构作出更改.它还可以在任何时候在树中上下导航,而不是像SAX

  • Java编程中更新XML文档的常用方法

    本文简要的讨论了Java语言编程中更新XML文档的四种常用方法,并且分析这四种方法的优劣.其次,本文还对如何控制Java程序输出的XML文档的格式做了展开论述. JAXP是Java API for XML Processing的英文字头缩写,中文含义是:用于XML文档处理的使用Java语言编写的编程接口.JAXP支持DOM.SAX.XSLT等标准.为了增强JAXP使用上的灵活性,开发者特别为JAXP设计了一个Pluggability Layer,在Pluggability Layer的支持之下,

  • java解析XML详解

    目录 XML的主要用途 对比HTML 关于XML文件的解析? JDK自带的一套解析 总结 XML的主要用途 --数据存储和数据描述 --是一个优良的配置文件 --相当于一个小型数据库 --XML不依赖于任何一种编程语言,是独立的W3C提供的规范,所以可以完成多种语言之间的数据交换(重点) XML的语法严格,并且完全区分大小写 XML(eXtensible Markup Language)-描述事物本身 .xml XSL (eXtensible Stylesheet Language)-修饰XML

  • java解析XML几种方式小结

    java解析XML几种方式小结 第一种:DOM. DOM的全称是Document Object Model,也即文档对象模型.在应用程序中,基于DOM的XML分析器将一个XML文档转换成一个对象模型的集合(通常称DOM树),应用程序正是通过对这个对象模型的操作,来实现对XML文档数据的操作.通过DOM接口,应用程序可以在任何时候访问XML文档中的任何一部分数据,因此,这种利用DOM接口的机制也被称作随机访问机制. DOM接口提供了一种通过分层对象模型来访问XML文档信息的方式,这些分层对象模型依

  • 基于Java实现XML文件的解析与更新

    目录 选择一个格式 XML 基础 创建一个示例配置文件 使用 Java 解析 XML 使用 Java 访问 XML 的值 使用 Java 更新 XML 如何保证配置不出问题 在你使用 Java 编写软件时实现持久化配置. 当你编写一个应用时,你通常都会希望用户能够定制化他们和应用交互的方式,以及应用与系统进行交互的方式.这种方式通常被称为 “偏好preference” 或者 “设置setting”,它们被保存在一个 “偏好文件” 或者 “配置文件” 中,有时也直接简称为 “配置config”.配

  • Java基于正则表达式实现xml文件的解析功能详解

    本文实例讲述了Java基于正则表达式实现xml文件的解析功能.分享给大家供大家参考,具体如下: 这是我通过正则表达式实现的xml文件解析工具,有些XHTML文件中包含特殊符号,暂时还无法正常使用. 设计思路:常见的xml文件都是单根树结构,工具的目的是通过递归的方式将整个文档树装载进一个Node对象.xml文档树上的每一个节点都能看做一个Node对象,它拥有title.attribute和text三个自身变量以及一个childrenNode集合用来存放子节点,使用正则表达式完整装载. 一.编写N

  • Java持久化XML文件配置解析

    目录 选择一个格式 XML 基础 创建一个示例配置文件 使用 Java 解析 XML 使用 Java 访问 XML 的值 使用 Java 更新 XML 如何保证配置不出问题 在你使用 Java 编写软件时实现持久化配置. 当你编写一个应用时,你通常都会希望用户能够定制化他们和应用交互的方式,以及应用与系统进行交互的方式.这种方式通常被称为 “偏好preference” 或者 “设置setting”,它们被保存在一个 “偏好文件” 或者 “配置文件” 中,有时也直接简称为 “配置config”.配

  • python解析xml文件方式(解析、更新、写入)

    Overview 这篇博客内容将包括对XML文件的解析.追加新元素后写入到XML,以及更新原XML文件中某结点的值.使用的是python的xml.dom.minidom包,详情可见其官方文档:xml.dom.minidom官方文档.全文都将围绕以下的customer.xml进行操作: <?xml version="1.0" encoding="utf-8" ?> <!-- This is list of customers --> <c

  • java对XML文件的解析、节点的增加、删除操作总结

    1.java代码: 主要采用dom来进行操作 复制代码 代码如下: package test; import java.io.IOException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.T

  • Java web xml文件读取解析方式

    其实解析xml文件有四种方式:DOM,JDOM,DOM4J,SAX. 我们来说与平台无关的两种官方解析方式:DOM 和 SAX 一.DOM 解析 在 Java 代码中,xml 文件是标记型文档,这时用 dom 来解析 xml 文件 dom 会根据 html 的层级结构在内存中分配一个树形结构,把html的标签,属性和文本都封装成对象 DOM 解析步骤: 1.使用 newInstance 方法,创建一个 DocumentBuilderFactory 的对象. 2.创建一个 DocumentBuil

  • 基于Java创建XML(无中文乱码)过程解析

    这篇文章主要介绍了基于Java创建XML(无中文乱码)过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 package com.zyb.xml; import java.io.FileOutputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import org.dom4j.Document; i

  • 通过Java读取xml文件内容过程解析

    这篇文章主要介绍了通过Java读取xml文件内容过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 需要下载jar包dom4j:https://dom4j.github.io/ package com.zyb.xml; import java.io.File; import java.util.Iterator; import org.dom4j.Attribute; import org.dom4j.Document; import or

  • Java中使用DOM4J生成xml文件并解析xml文件的操作

    目录 一.前言 二.准备依赖 三.生成xml文件生成标准展示 四.解析xml文件 五.总结 一.前言 现在有不少需求,是需要我们解析xml文件中的数据,然后导入到数据库中,当然解析xml文件也有好多种方法,小编觉得还是DOM4J用的最多最广泛也最好理解的吧.小编也是最近需求里遇到了,就来整理一下自己的理解,只适合刚刚学习的,一起理解!今天我们把解析xml文件和生成xml文件在一起来展示. 二.准备依赖 <dependency> <groupId>dom4j</groupId&

  • java读取XML文件的四种方法总结(必看篇)

    JAVA操作XML文档主要有四种方式,分别是DOM.SAX.JDOM和DOM4J,DOM和SAX是官方提供的,而JDOM和DOM4J则是引用第三方库的,其中用的最多的是DOM4J方式.运行效率和内存使用方面最优的是SAX,但是由于SAX是基于事件的方式,所以SAX无法在编写XML的过程中对已编写内容进行修改,但对于不用进行频繁修改的需求,还是应该选择使用SAX. 下面基于这四种方式来读取XML文件. 第一,以DOM的方式实现. package xmls; import org.w3c.dom.D

随机推荐