如何根据 XML 文件中的特定属性名称删除重复的标签?

aol*_*an1 2 xml text-processing uniq

如何根据“groupName”删除重复的行并保留该行directoryId="1"

<Group id="123" groupName="ABC" lowerGroupName="abc" active="1" local="1" createdDate="2017-08-21 09:28:30.581" updatedDate="2017-08-21 09:28:30.581" type="GROUP" directoryId="10100"/>
<Group id="456" groupName="ABC" lowerGroupName="abc" active="1" local="0" createdDate="2017-08-21 09:28:30.634" updatedDate="2017-08-21 09:28:30.634" type="GROUP" directoryId="1"/>
Run Code Online (Sandbox Code Playgroud)

smh*_*ich 5

我认为uniq这不一定是正确的工具,因为它适用于空格分隔或固定宽度的文件(显然它只有两个与“列”相关的选项是--skip-fields--skip-chars),而您在这里拥有的是类似 XML 的列宽既不固定,列之间也没有任何简单的单字符分隔符的数据(等的值groupName原则上可以包含空格)。

相反,我会使用旨在处理 XML 的工具。

避免必须自己编写脚本的一种选择是基于 XPath 的过滤。可以从这些答案中了解如何使用 XPath 过滤唯一性- 重要的语法元素是following-sibling::preceding-sibling::轴。可以在此问题的答案中找到用于评估 XPath 表达式的命令行工具。在我尝试过的那些中,最容易安装的是basex此处建议),因此我将在下文中使用它。

如果我正确理解了您的问题,您希望将相同的行(XML 元素)减少groupName到最后一行(或者是否有另一个原因选择带有directoryId="1"?的行)。对于这样的 XML 文档:

<Groups>
<Group id="123" groupName="ABC" lowerGroupName="abc" active="1" local="1" createdDate="2017-08-21 09:28:30.581" updatedDate="2017-08-21 09:28:30.581" type="GROUP" directoryId="10100"/>
<Group id="456" groupName="ABC" lowerGroupName="abc" active="1" local="0" createdDate="2017-08-21 09:28:30.634" updatedDate="2017-08-21 09:28:30.634" type="GROUP" directoryId="1"/>
<Groups>
Run Code Online (Sandbox Code Playgroud)

我们必须将所有内容都包装在根元素 ( Groups) 中以使其成为格式良好的 XML,此要求可以使用以下 XPath 表达式来实现:

/Groups/Group[not(@groupName = following-sibling::Group/@groupName)]
Run Code Online (Sandbox Code Playgroud)

/Groups/Group选择要返回的元素,然后使用 中的表达式对其进行过滤[]@选择属性并following-sibling::匹配当前元素的所有后续同级元素(参见此处)。

运行这个会basex产生预期的结果:

/Groups/Group[not(@groupName = following-sibling::Group/@groupName)]
Run Code Online (Sandbox Code Playgroud)

相比之下,uniq它的缺点是basex会首先将整个 XML 文档读入内存,因此对于超过主内存大小的非常大的文件,这是不可行的。有一些 XML 处理器以流方式对 XML 进行操作,例如 XSLT 3.0 具有流转换,因此如果您必须处理大文件,那么可能有一种方法可以使用任何支持 XSLT 3.0 的处理器来完成此操作。但到那时,手工编写自己的小型流解析器可能会更容易。