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)
我认为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 的处理器来完成此操作。但到那时,手工编写自己的小型流解析器可能会更容易。