【问题标题】:Sorting XML by subnode content按子节点内容对 XML 进行排序
【发布时间】:2020-08-14 12:48:13
【问题描述】:

我有一个具有以下结构的 XML 文档

<movements status="1">
    <movement>
        <article>49-000003</article>
        <lot>0I0311</lot>
        <type>4</type>
        <date></date>
    </movement>
    <movement>
        <article>49-000013</article>
        <lot>0I0312</lot>
        <type>4</type>
        <date></date>
    </movement>
    <movement>
        <article>49-000001</article>
        <lot>0I0313</lot>
        <type>4</type>
        <date></date>
    </movement>
</movements>

我如何(使用 xmllint)对其进行排序,以便移动节点按文章排序?

我需要输出是另一个 XML 文件。

【问题讨论】:

  • 我不确定这可以用 xmllint 完成;它可以使用 xquery 轻松完成,但为此您需要使用 xidel。如果有的话,我可以发布一个答案。
  • @JackFleeting 感谢您的回复。我可以在 Mac 上安装的任何东西都可用。我想我可以通过 Homebrew formulae.brew.sh/formula/xidel 安装它
  • @JackFleeting iMac:~ sig$ xidel --version Xidel 0.9.8

标签: xml xmllint


【解决方案1】:

在您的 iMac 上尝试这样的操作,看看它是否有效:

xidel  your_file.xml --xquery 'for $node in //movement order by $node/article return $node' --output-format xml

【讨论】:

  • 有点用。我可以看到在我的终端上排序的数据。但是,我需要的是一个 xml 文件,就像对节点进行排序的原始文件一样。谢谢。
  • 感谢您的更新。对于未来的读者:--output-format xml &gt;&gt; new_file.xml 生成一个新的 XML 文件。
  • 是否可以更新命令,使子节点按字母顺序(文章、日期、批次、类型)排序?查看当前日期是最后一个。谢谢。
  • @Sig 可能,但我必须考虑清楚。无论如何,我认为最好将其作为一个单独的问题发布。
【解决方案2】:

如果您可以使用xmlstarlet (tr command),那么一个简单的 XSLT 应该可以工作...

XSLT 1.0 (test.xsl)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/*">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()">
        <xsl:sort select="article"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="movement">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:apply-templates select="node()">
        <xsl:sort select="name()"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

命令行

xmlstarlet tr test.xsl input.xml > output.xml

输出 (output.xml)

<movements status="1">
   <movement>
      <article>49-000001</article>
      <date/>
      <lot>0I0313</lot>
      <type>4</type>
   </movement>
   <movement>
      <article>49-000003</article>
      <date/>
      <lot>0I0311</lot>
      <type>4</type>
   </movement>
   <movement>
      <article>49-000013</article>
      <date/>
      <lot>0I0312</lot>
      <type>4</type>
   </movement>
</movements>

【讨论】:

  • 感谢您的回复。在我安装所有依赖项之前,您能帮我确认一下输出是一个排序的 XML 文件吗?干杯...
  • @Sig - 我不确定你的意思;输出包含在我的答案中,movement 元素按article 元素的值排序。
  • 我想知道输出是文件还是终端上的一些文本。 xidel 命令对我来说工作得很好,不需要创建任何额外的 XSLT 文件。因此,我接受了这一点。感谢您的宝贵时间。
  • @Sig - 您可以将输出重定向到新文件。
  • @Sig - 我还看到了您关于对movement 的孩子进行排序的评论。我也将它添加到 XSLT。
猜你喜欢
  • 2023-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多