如何用xmlstarlet为XML新增或更新property属性?
使用xmlstarlet处理Hibernate配置XML:不存在则插入、存在则更新property节点
问题描述
我有如下基础XML:
<hibernate-configuration> <session-factory> <mapping class="com.model.Menu"/> </session-factory> </hibernate-configuration>
该基础XML可能包含部分property节点,也可能不包含,例如:
<hibernate-configuration> <session-factory> <mapping class="com.model.Menu"/> <property name="driver_class">some-class</property> <property name="driver_dialect">some-dialect</property> </session-factory> </hibernate-configuration>
需要使用xmlstarlet实现:若这些property节点不存在则插入,若已存在则更新其值,且不产生重复项。我了解单独的更新和插入操作,但由于无法提前知晓属性是否存在,不知道该如何处理,请问正确的实现方式是什么?
解决方案
可以通过先更新已存在节点,再插入不存在节点的逻辑实现需求:xmlstarlet的update指令对不存在的节点无任何影响,而insert指令可通过--if-not-exists确保仅在节点缺失时执行插入,具体操作如下:
1. 单条命令完成更新+插入
将更新和插入操作合并为一条命令,减少文件操作次数:
xmlstarlet edit --inplace \ # 更新已存在的driver_class节点值 --update "/hibernate-configuration/session-factory/property[@name='driver_class']" \ --value "com.mysql.cj.jdbc.Driver" \ # 更新已存在的driver_dialect节点值 --update "/hibernate-configuration/session-factory/property[@name='driver_dialect']" \ --value "org.hibernate.dialect.MySQL8Dialect" \ # 仅当driver_class不存在时插入该节点 --insert "/hibernate-configuration/session-factory" \ --type elem --name "property" \ --if-not-exists "/hibernate-configuration/session-factory/property[@name='driver_class']" \ --attr name "driver_class" --value "com.mysql.cj.jdbc.Driver" \ # 仅当driver_dialect不存在时插入该节点 --insert "/hibernate-configuration/session-factory" \ --type elem --name "property" \ --if-not-exists "/hibernate-configuration/session-factory/property[@name='driver_dialect']" \ --attr name "driver_dialect" --value "org.hibernate.dialect.MySQL8Dialect" \ hibernate.cfg.xml
2. 拆分执行(可选)
如果需要分步验证,也可以拆分为两条命令:
第一步:更新已存在的节点
xmlstarlet edit --inplace \ --update "/hibernate-configuration/session-factory/property[@name='driver_class']" \ --value "com.mysql.cj.jdbc.Driver" \ --update "/hibernate-configuration/session-factory/property[@name='driver_dialect']" \ --value "org.hibernate.dialect.MySQL8Dialect" \ hibernate.cfg.xml
第二步:插入不存在的节点
xmlstarlet edit --inplace \ --insert "/hibernate-configuration/session-factory" \ --type elem --name "property" \ --if-not-exists "/hibernate-configuration/session-factory/property[@name='driver_class']" \ --attr name "driver_class" --value "com.mysql.cj.jdbc.Driver" \ --insert "/hibernate-configuration/session-factory" \ --type elem --name "property" \ --if-not-exists "/hibernate-configuration/session-factory/property[@name='driver_dialect']" \ --attr name "driver_dialect" --value "org.hibernate.dialect.MySQL8Dialect" \ hibernate.cfg.xml
关键参数说明
--inplace:直接修改原XML文件,若仅需预览结果可去掉该参数,输出会打印到控制台--if-not-exists:核心控制逻辑,确保插入操作仅在目标节点不存在时执行,彻底避免重复项- 先更新后插入的顺序:即使节点已存在,更新操作会先覆盖原有值,后续插入操作会因节点已存在而自动跳过,不会产生冲突
内容的提问来源于stack exchange,提问作者Jose
相关产品推荐
相关产品推荐

