使用 xPath 修改 XML 文件

2024-03-21

我想使用 xPath 修改现有的 XML 文件。如果该节点不存在,则应该创建它(如果需要,还可以创建它的父节点)。一个例子:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <param0>true</param0>
  <param1>1.0</param1>
</configuration>

以下是我想要插入/修改的几个 xPath:

/configuration/param1/text()         -> 4.0
/configuration/param2/text()         -> "asdf"
/configuration/test/param3/text()    -> true

XML 文件之后应如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <param0>true</param0>
  <param1>4.0</param1>
  <param2>asdf</param2>
  <test>
    <param3>true</param3>
  </test>
</configuration>

我试过这个:

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
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.Node;
import org.w3c.dom.NodeList;

try {
  DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
  Document doc = domFactory.newDocumentBuilder().parse(file.getAbsolutePath());
  XPath xpath = XPathFactory.newInstance().newXPath();

  String xPathStr = "/configuration/param1/text()";
  Node node = ((NodeList) xpath.compile(xPathStr).evaluate(doc, XPathConstants.NODESET)).item(0);
  System.out.printf("node value: %s\n", node.getNodeValue());
  node.setNodeValue("4.0");

  TransformerFactory transformerFactory = TransformerFactory.newInstance();
  Transformer transformer = transformerFactory.newTransformer();
  transformer.transform(new DOMSource(doc), new StreamResult(file));
} catch (Exception e) {
  e.printStackTrace();
}

运行此代码后,文件中的节点发生更改。正是我想要的。但如果我使用以下路径之一,node为空(因此NullPointerException被抛出):

/configuration/param2/text()
/configuration/test/param3/text()

如何更改此代码以便创建节点(以及不存在的父节点)?

EDIT:好的,澄清一下:我有一组参数想要保存到 XML。在开发过程中,该集合可能会发生变化(添加一些参数,移动一些参数,删除一些参数)。所以我基本上想要有一个函数将当前的参数集写入已经存在的文件中。它应该覆盖文件中已存在的参数,添加新参数并保留旧参数。

对于阅读来说也是一样,我可以只使用 xPath 或其他一些坐标并从 XML 中获取值。如果不存在,则返回空字符串。

我对如何实现它没有任何限制,xPath、DOM、SAX、XSLT...一旦编写了功能,它就应该很容易使用(就像 BeniBela 的解决方案)。

因此,如果我要设置以下参数:

/configuration/param1/text()         -> 4.0
/configuration/param2/text()         -> "asdf"
/configuration/test/param3/text()    -> true

结果应该是起始 XML + 那些参数。如果它们已经存在于该 xPath 处,则它们将被替换,否则它们将被插入到该点。


如果您想要一个没有依赖项的解决方案,您可以仅使用 DOM 而无需 XPath/XSLT。

Node.getChildNodes|getNodeName / NodeList.* 可用于查找节点,Document.createElement|createTextNode、Node.appendChild 可用于创建新节点。

然后您可以编写自己的简单“XPath”解释器,它会在路径中创建丢失的节点,如下所示:

public static void update(Document doc, String path, String def){
  String p[] = path.split("/");
  //search nodes or create them if they do not exist
  Node n = doc;
  for (int i=0;i < p.length;i++){
    NodeList kids = n.getChildNodes();
    Node nfound = null;
    for (int j=0;j<kids.getLength();j++) 
      if (kids.item(j).getNodeName().equals(p[i])) {
    nfound = kids.item(j);
    break;
      }
    if (nfound == null) { 
      nfound = doc.createElement(p[i]);
      n.appendChild(nfound);
      n.appendChild(doc.createTextNode("\n")); //add whitespace, so the result looks nicer. Not really needed
    }
    n = nfound;
  }
  NodeList kids = n.getChildNodes();
  for (int i=0;i<kids.getLength();i++)
    if (kids.item(i).getNodeType() == Node.TEXT_NODE) {
      //text node exists
      kids.item(i).setNodeValue(def); //override
      return;
    }

  n.appendChild(doc.createTextNode(def));    
}

然后,如果您只想更新 text() 节点,您可以将其用作:

DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
Document doc = domFactory.newDocumentBuilder().parse(file.getAbsolutePath());

update(doc, "configuration/param1", "4.0");
update(doc, "configuration/param2", "asdf");
update(doc, "configuration/test/param3", "true");
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 xPath 修改 XML 文件 的相关文章

  • Java 7u51/7u55 带星号的清单变量

    我正在部署一个小程序 其中包含清单中的下一个变量 Manifest Version 2 0 Ant Version Apache Ant 1 8 2 Trusted Library true Permissions all permissi
  • Mediaplayer 播放几次后停止播放

    我有一个按钮 按下它会播放一个随机声音剪辑 然后播放另一个声音剪辑 然后通过一个媒体播放器播放另一个声音剪辑 但是多次按下该按钮 15 20 次 后 所有音频都会停止 我在播放最后一个音频剪辑后释放媒体播放器 所以我不认为这是原因 有什么指
  • 我从 String placeName = placeText.getText().toString(); 收到空指针异常

    您好 想从编辑文本中获取地名并在地图上标记 这是我的代码 其中出现空指针异常 请帮助我应该做什么以及哪里出错了 因为我从对话框中的编辑文本字段获取地名 View layout View inflate this R layout alert
  • 我想使用对话框显示两个数字选择器

    我试图仅使用 java 在对话框上显示两个数字选择器 代码正在工作 但我无法将其排列为相等的宽度 这是我的代码 RelativeLayout relative new RelativeLayout mContext final Number
  • 单击一次文件丢失

    将 Clickonce 与 VS 2010 和 NET Framework Client profile 3 5 一起使用 我有几个文件夹 其中包含运行时所需的应用程序级 XML 和 或文本文件 这些文件夹位于要使用它们的同一项目中 这些文
  • 参考接口创建对象

    引用变量可以声明为类类型或接口类型 如果变量声明为接口类型 则它可以引用实现该接口的任何类的任何对象 根据上面的说法我做了一个理解上的代码 正如上面所说声明为接口类型 它可以引用实现该接口的任何类的任何对象 但在我的代码中显示display
  • Map:为 Integer 和 Double 类型定义方法,但不为 String 类型定义方法

    我正在尝试定义一个方法putIfGreaterThan 为了我的新Map class 给定一个键 仅当新值大于旧值时 它才会用新值替换旧值 我知道我可以通过组合来实现这一点 通过有一个private final Map
  • Spark SQL 失败,因为“常量池已超过 JVM 限制 0xFFFF”

    我在 EMR 4 6 0 Spark 1 6 1 上运行此代码 val sqlContext SQLContext getOrCreate sc val inputRDD sqlContext read json input try inp
  • Java 套接字 - 读和写

    问题 客户端没有收到任何消息 这是客户端和服务器的完整代码 CLIENT public class Client extends Socket public Client String hostName int port throws Un
  • 检查更新时 Maven 无限期挂起

    我正在使用 Maven 构建一个项目 我是新手 并且它挂起 mvn package INFO Scanning for projects INFO INFO Building Presentation Reports INFO task s
  • Netty Nio java 中的通信

    我想在 Netty nio 中创建一个具有两个客户端和一个服务器的通信系统 更具体地说 首先 我希望当两个客户端与服务器连接时从服务器发送消息 然后能够在两个客户端之间交换数据 我正在使用本示例提供的代码 https github com
  • Java MYSQL/JDBC 查询从缓存的连接返回过时的数据

    我一直在 Stackoverflow 中寻找答案 但似乎找不到不涉及 Hibernate 或其他数据库包装器的答案 我直接通过 Tomcat 6 Java EE 应用程序中的 MYSQL 5 18 JDBC 驱动程序使用 JDBC 我正在缓
  • 覆盖Java中的属性[重复]

    这个问题在这里已经有答案了 在 Java 中 我最近有几个项目 我使用了这样的设计模式 public abstract class A public abstract int getProperty public class B exten
  • AWS SQS Batch SendMessageBatchRequest 非常慢

    我的应用程序使用 SendMessageBatchRequest 将每个请求发布 10 条消息到 AWS SQS 每条消息的大小小于250字节 该应用程序预计每天发布约一百万条记录 但要实现这一目标 消息发布的速度非常慢 AmazonSQS
  • Java 中的连接路径

    In Python我可以连接两条路径os path join os path join foo bar gt foo bar 我正在尝试在 Java 中实现相同的目标 而不用担心是否OS is Unix Solaris or Windows
  • “mvn”不被识别为内部或外部命令、可操作程序或批处理文件

    可能是之前问过问题 但我发现了非常奇怪的错误 当我跑步时mvn versionbin 中的命令给出了版本和其他信息 但是 当我跑到垃圾箱外面时 它会出现异常 下面提到的结果 C Program Files apache maven 3 0
  • 在 Spark MLlib 上使用 Java 中的 Breeze

    在尝试从Java使用MLlib时 使用微风矩阵运算的正确方法是什么 例如scala 中的乘法很简单 matrix vector 相应的功能在Java中是如何表达的 有一些方法 例如 colon times 可以通过正确的方式调用 breez
  • com.fasterxml.jackson.databind.JsonMappingException:无法反序列化 org.springframework.data.domain.Sort 的实例 START_ARRAY 令牌

    我的 objectMapper 正在获取类型的值Page
  • Selenium Webdriver - 单击多个下拉菜单时出现陈旧元素异常,而 HTML DOM 不会更改

    我尝试自动化一个场景 其中条件是我必须从下拉列表中选择一个选项 然后它旁边有另一个下拉列表 我必须单击下一个下拉列表中的一个选项才能启用按钮 我尝试使用代码 但它仅单击第一个选项 并显示错误为过时的元素引用 元素未附加到页面文档 请帮忙 如
  • 为什么我们不能在函数式接口中重载抽象方法? (爪哇)

    所以我熟悉java中的函数式接口 以及它们与lambda表达式的使用 一个函数式接口只能包含一个抽象方法 当从 lambda 表达式使用这一孤独方法时 您不需要指定其名称 因为接口中只有一个抽象方法 编译器知道这就是您正在引用的方法 Exa

随机推荐

  • 我应该为每个环境变量使用 configMap 吗?

    我现在正在使用 helm 我的项目是这样的 值 yaml environmentVariables KEY1 VALUE1 KEY2 VALUE2 配置映射 yaml apiVersion v1 kind ConfigMap metadat
  • //什么是路径,它与/有什么不同

    我们知道根目录是 根据posix 还有另一个与 不同的目录 当您 ls 和 ls 时 输出是相同的 就像 stat 一样 但是如果您 cd 和 cd 它们是不同的 尽管目录内容相同 这真的让我很困惑 有人得到答案吗 From Bash FA
  • 当 CDK 定义时,是否可以在本地运行 AWS Step Functions?

    AWS Step Functions 可以使用以下命令在本地 Docker 环境中运行Step Functions 本地 Docker https docs aws amazon com step functions latest dg s
  • Firebug Net 选项卡中报告的读取时间

    请参阅 Firebug 的 网络 选项卡中的屏幕截图 http www scdi org avernet try firefox times png http www scdi org avernet try firefox times p
  • LOCAL_MODULE_TAGS有什么用?

    我想更新包中的 Android mk 文件以构建新包 但我不明白该文件的目的是什么LOCAL MODULE TAGS is 什么是LOCAL MODULE TAGS do 更正 不再建议使用用户标签 反而 Add LOCAL MODULE
  • gitlab - 图标被矩形替换

    我最近安装了 gitlab 似乎所有图标都被矩形替换了 其他一切似乎都工作正常 知道是什么原因造成的吗 edit on another computer I seem to get Korean characters instead of
  • Ruby on Rails 实时搜索(过滤)

    我正在关注 Railscasts Rails ajax 教程并遇到了一些麻烦 实时搜索不起作用 我必须单击搜索按钮才能获取结果 我有两个搜索过滤器 第一个是 select tag 第二个是一个复选框 这是我的代码 结果 html erb t
  • 默认启动项目由什么决定?

    我有一个包含 Visual Studio 项目文件的开源项目 有一个包含四个项目文件的解决方案文件 当源文件被分发和解压时 Visual Studio 选择错误的项目作为默认项目 新用户不知道他们需要右键单击某个项目 然后选择设置为启动项目
  • Kendo Grid 导出到 Excel 时出错“无法读取 jQuery.js 文件中未定义的属性‘长度’”

    我正在尝试将剑道网格导出到 Excel 然后我在控制台中出现错误 如果有人知道的话请帮助我 提前致谢 angular js 13920 TypeError Cannot read property length of undefined a
  • 向我的免费 G​​itHub 帐户添加协作者?

    我创建了一个 GitHub 帐户 我想授予某人写入权限 以便他可以像我一样进行推送 有没有办法通过免费计划添加协作者 如果没有 我能做什么 除了购买付费帐户 这是我将来会做的 Go to Manage Access设置下的页面 https
  • 如何将旧式 Windows 图元文件写入文件

    我可以生成旧的 未增强的 图元文件 如何将其写入磁盘 使其成为正确的 wmf 文件 佩措尔德没有提到这一点 http www user tu chemnitz de heha petzold ch18b htm 但是将图元文件写入磁盘有一个
  • PHP 比较字符串是否(几乎)相等

    我需要比较可以用多种方式书写的名称 例如 像 St Thomas 这样的名字有时会写成 St Thomas 或 Sant Thomas 最好 我希望构建一个函数 为比较提供 平等 的百分比 就像一些论坛所做的那样 这篇文章已编辑 5 例如
  • 如何从应用程序后台录制视频:Android

    我正在开发一个应用程序 它将能够通过使用从应用程序后台录制视频Service 问题描述 1 我创建了一个活动来启动服务 如下所示 package com android camerarecorder import android app A
  • 由于缩放问题,响应式网站无法正确显示水平线

    我正在使用CSS向网站添加响应式功能 该网站已经属于他们一段时间了 现在正在添加响应式功能 以便它可以支持移动版本 我面临一个问题 假设有多行由水平线分隔 在某个地方我正在使用hr在某些地方我只是简单地使用div to 这是小提琴的示例链接
  • 在 ASP:Repeater 中查找控件

    我正在尝试访问中继器内的控件 该控件位于 标记内 我正在使用 FindControl 但它总是显示为 Null 我究竟做错了什么 我的猜测是 FindControl 只能用于记录级事件 例如 ItemDataBound protected
  • 评估连接速度的最佳方法

    我正在开发一个应用程序 需要通过流媒体获取音乐文件以进行现场播放 在请求歌曲 api 中 我可以指定带宽 例如 50kbps 100kbps 300 600 或 1 Mbps 带宽越大 获取文件的时间就越多 因为我不希望用户受到限制 所以我
  • 在 R Shiny 中捕获选择输入?

    我试图捕获当人们按下应用程序上的 获取 URL 按钮时所选择的 URL 应该发生的是event reactive 应该看看input go button并看到它已被按下 然后它应该执行表达式以从选择输入中获取所选的 url 不幸的是它什么也
  • FacesContext 和“Servlet”上下文

    有没有与 FacesContext 等效的东西 但是在 servlet 环境中 我有一些 DAOSessionManager 来处理我的数据库的事务 当当前页面是使用 JSF 编写时 我可以使用 FacesContext 来识别当前的 ht
  • python ssh 密码提示

    我试图在使用 ssh 时根据提示自动传递密码 通常 rsa 密钥用于防止密码提示 但我不能保证每个用户都正确设置 因此我希望脚本在用户给出密码时自动设置密码 这里是 ssh subprocess Popen ssh localhost py
  • 使用 xPath 修改 XML 文件

    我想使用 xPath 修改现有的 XML 文件 如果该节点不存在 则应该创建它 如果需要 还可以创建它的父节点 一个例子