如何对这个 XML 进行排序?
- 首先按字母顺序排列:
module
beforeproperty
。 - 然后按字母顺序命名属性:
<module name="ClassTypeParameterName"/>
before<module name="PackageName"/>
。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE module PUBLIC "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN" "https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
<property name="severity" value="error"/>
<property name="fileExtensions" value="java"/>
<module name="NewlineAtEndOfFile"/>
<module name="FileTabCharacter"/>
<module name="TreeWalker">
<module name="PackageName"/>
<module name="ClassTypeParameterName"/>
<module name="InterfaceTypeParameterName"/>
<module name="MethodTypeParameterName"/>
<module name="LambdaParameterName"/>
<module name="PatternVariableName"/>
<module name="RecordComponentName"/>
<module name="RecordTypeParameterName"/>
<module name="TypeName">
<property name="format" value="^[A-Z][_a-zA-Z0-9]*$"/>
</module>
<module name="AvoidDoubleBraceInitialization"/>
<module name="AvoidNoArgumentSuperConstructorCall"/>
<module name="OneTopLevelClass"/>
<module name="OuterTypeFilename"/>
</module>
</module>
我想使用xq
这里使用的:在 UNIX 中使用 Bash 脚本对 XML 文件进行排序?
答案1
你可能想要这样的东西:
xq -x -S 'walk(if type == "array" then sort_by(."@name") else . end)' file
这使用-S
(或--sort-keys
) 根据键的名称对键(XML 标记)进行排序,以便键module
位于property
键之前。
然后,它使用递归walk()
函数应用于每个数组,根据属性的值(写为)sort_by()
对每个数组的元素进行排序。name
."@name"
这种walk()
用法几乎与jq
手册中的示例。
这将产生以下输出:
<module name="Checker">
<module name="FileTabCharacter"></module>
<module name="NewlineAtEndOfFile"></module>
<module name="TreeWalker">
<module name="AvoidDoubleBraceInitialization"></module>
<module name="AvoidNoArgumentSuperConstructorCall"></module>
<module name="ClassTypeParameterName"></module>
<module name="InterfaceTypeParameterName"></module>
<module name="LambdaParameterName"></module>
<module name="MethodTypeParameterName"></module>
<module name="OneTopLevelClass"></module>
<module name="OuterTypeFilename"></module>
<module name="PackageName"></module>
<module name="PatternVariableName"></module>
<module name="RecordComponentName"></module>
<module name="RecordTypeParameterName"></module>
<module name="TypeName">
<property name="format" value="^[A-Z][_a-zA-Z0-9]*$"></property>
</module>
</module>
<property name="fileExtensions" value="java"></property>
<property name="severity" value="error"></property>
</module>
请注意,xq
即使对于空节点,也会显式写出结束标记。如果您想修复该问题(将其<tag attr="..."></tag>
更改为<tag attr="..."/>
),请将结果传递给xmlstarlet fo
或xmlstarlet format
。
作为参考,原始 XML 文档转换为的 JSON 文档(不进行任何排序)以及jq
应用表达式的 JSON 文档等效于以下内容:
{
"module": {
"@name": "Checker",
"module": [
{ "@name": "NewlineAtEndOfFile" },
{ "@name": "FileTabCharacter" },
{
"@name": "TreeWalker",
"module": [
{ "@name": "PackageName" },
{ "@name": "ClassTypeParameterName" },
{ "@name": "InterfaceTypeParameterName" },
{ "@name": "MethodTypeParameterName" },
{ "@name": "LambdaParameterName" },
{ "@name": "PatternVariableName" },
{ "@name": "RecordComponentName" },
{ "@name": "RecordTypeParameterName" },
{
"@name": "TypeName",
"property": { "@name": "format", "@value": "^[A-Z][_a-zA-Z0-9]*$"
},
{ "@name": "AvoidDoubleBraceInitialization" },
{ "@name": "AvoidNoArgumentSuperConstructorCall" },
{ "@name": "OneTopLevelClass" },
{ "@name": "OuterTypeFilename" }
]
}
],
"property": [
{ "@name": "severity", "@value": "error" },
{ "@name": "fileExtensions", "@value": "java" }
]
}
}
答案2
我遇到了与OP非常相似的问题(增加了包含客户数据的xml问题,排除了在线工具),并首先沿着使用xq
.我以这个脚本为起点,取得了一些不错的成功:https://unix.stackexchange.com/a/659245/367314。
然而最后我发现了一个很好的插件,vscode
它允许您对代码块进行排序,也允许您配置深度。我想我会在这里发帖以防对其他人有帮助。
https://marketplace.visualstudio.com/items?itemName=1nVitr0.blocksort
如果您只想对文件中的某些块进行排序,您可以在 UI 中选择这些块,然后仅对您感兴趣的块进行排序,或者对整个文档进行智能排序。
如果您想实现自动化,这不是一个好的解决方案,但对于一次性来说是有好处的。