我正在尝试从 XML 文件中删除包含某个其他元素的所有元素。这是我正在尝试做的事情的一个非常简化的版本。假设我有 XML 文件
<RootEl>
<A>
<B/>
</A>
<A>
<C/>
</A>
</RootEl>
如果我想保留所有且仅包含 B 的 A,我可以使用以下命令行:
xml_grep -root A -cond B < TheFile.xml
但如果我想做相反的事情——只保留不包含 B 的 A,我就不知所措了。与上面类似的命令,即
xml_grep -root A -exclude B < TheFile.xml
给我
<RootEl>
<A>
</A>
<A>
<C/>
</A>
</RootEl>
而我想要的是
<RootEl>
<A>
<C/>
</A>
</RootEl>
如果我使用,我会得到同样不想要的答案
xml_grep -root A -exclude A/B < TheFile.xml
或者
xml_grep -exclude A/B < TheFile.xml
我可以弄清楚如何在 Python 中执行此操作,并且我认为在 xslt 中也是可能的。但我希望有一种方法可以在 xml_grep 中做到这一点。
顺便说一句,我确信有人会问为什么我不直接告诉它我想要包含 Cs 的 As。问题是,除了 B 或 C 之外,A 还可以包含 20 种左右的东西,所以我必须指定一个包含 C 或 D 或...或 Z 的 A。这需要更多的工作而不是指定一种人工智能不想要的。
问题删除包含特定元素的 XML 节点问基本相同的问题,但使用 xml_grep 没有答案。我希望有人可以提出这样的答案,因为 xml_grep 似乎相当流行并且是为这样的目的而构建的......几乎。
答案1
使用xmlstarlet
:
$ xmlstarlet ed -d '//A[not(B)]' file.xml
<?xml version="1.0"?>
<RootEl>
<A>
<B/>
</A>
</RootEl>
XPATH 表达式//A[not(B)]
将选择A
文档中不包含节点B
作为子节点的所有节点。这些选定的节点将被删除。
该表达式也可以写为//A[not(child::B)]
更明确一点。