如何使用 xml-patch 和 xpath 使用命名空间修补 xml 文件?

How to patch an xml file with namespaces using xml-patch and xpath?

提问人:s1m3n 提问时间:7/7/2020 更新时间:7/9/2020 访问量:1764

问:

我正在尝试使用XML补丁修补几个XML文件,更具体地说是使用此库 https://github.com/dnault/xml-patch

我可以正确修补任何不包含任何命名空间声明的 xml 文件。我正在修补一个 logback.xml 文件,一切正常。

问题是当我尝试修补如下所示的 web.xml 文件时:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" metadata-complete="true">

    <display-name>My App</display-name>
...
</web-app>

使用如下所示的 xml-patch 文件

<diff file="WEB-INF/web.xml">
    <add sel="web-app" >
        <simple>true</simple>
    </add>
</diff>

当我运行修补程序时,我收到以下异常:

Caused by: com.github.dnault.xmlpatch.PatchException: no matches for selector "web-app"
    at com.github.dnault.xmlpatch.Patcher.selectNodes(Patcher.java:441)
    at com.github.dnault.xmlpatch.Patcher.add(Patcher.java:252)
    at com.github.dnault.xmlpatch.Patcher.patch(Patcher.java:85)
    at com.github.dnault.xmlpatch.Patcher.patch(Patcher.java:65)
    at com.github.dnault.xmlpatch.CommandLineDriver.main(CommandLineDriver.java:62)

我相当有信心这一定是差异文件和命名空间的问题,我可能没有正确配置它们。

我尝试将命名空间声明添加到差异文件,但错误是相同的。

有什么想法吗?

XML XPath 命名空间

评论

1赞 E.Wiest 7/8/2020
由于您正在处理命名空间,因此如果您在选择表达式中添加通配符,输出是什么。喜欢这个:?这似乎是正确的方法。请参阅此处的示例:xmlpatch.sourceforge.net/srns.txtadd sel="*/web-app"
0赞 s1m3n 7/9/2020
你好。我已经尝试过这样的事情,但没有成功。您的示例会导致以下错误:选择器“*/web-app”没有匹配项
0赞 E.Wiest 7/10/2020
我想那是因为我说的是错误的XML补丁库。在 sourceforge () 上可用,而不是在 Github 上。很高兴你找到了一些有效的东西:)libxmlpatch

答:

1赞 wp78de 7/9/2020 #1

看起来这是该工具的确认问题。尽管如此,原始海报还提到了一种解决方法:

所以实际上我必须声明两次 defaultnamespace 才能 允许选择和添加新节点,而无需在 逐个添加带有“cfg:”前缀的节点。请参阅以下示例:

应用于您的示例,patch .xml 应如下所示。

<diff xmlns:app="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0" metadata-complete="true">
    <add sel="app:web-app">
        <simple>true</simple>
    </add>
</diff>

这样,修补就会成功。

评论

1赞 s1m3n 7/9/2020
这非常接近,但添加的元素向添加的 <simple /> 节点添加了一个不需要的“xmlns”属性:<simple xmlns=“”>true</simple>
1赞 s1m3n 7/9/2020 #2

还有另一种方法可以做到这一点:

<diff file="WEB-INF/web.xml">
    <add sel="/*['web-app'=local-name()]">
        <simple>true</simple>
    </add>
</diff>

这也会导致添加一个不需要但无害的“xmlns”属性:

<simple xmlns="">true</simple>