如何按属性对 XML 元素进行排序?

如何按属性对 XML 元素进行排序?

如何对这个 XML 进行排序?

  1. 首先按字母顺序排列:modulebefore property
  2. 然后按字母顺序命名属性:<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 foxmlstarlet 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 中选择这些块,然后仅对您感兴趣的块进行排序,或者对整个文档进行智能排序。

如果您想实现自动化,这不是一个好的解决方案,但对于一次性来说是有好处的。

相关内容