解析 12,000 多个 XML 文件

解析 12,000 多个 XML 文件

我有一个包含 12,000 多个 XML 文件的文件夹。我需要获取该文件夹中满足特定条件的文件列表。

在 XML 文件中,有一个名为 的节点/BillingData/InvoiceLinesList/InvoiceLinesInvoiceLines内可能有一个或多个InvoiceLinesList。在 中InvoiceLines,我需要搜索一个名为 的标签,<charge>其值为,以及同一个名为99的标签中有一个标签,其值为。InvoiceLines<chargeType>D

最好的方法是什么?使用awk我认为我也许能够做到这一点,但我无法找到一种搜索多个条件的方法,因为我不擅长awk。我在这里看到了一种潜在的方法,xmlstarlet但它只在单个标签中查找一个或其他值,而不是在多个标签中查找单独的值。

答案1

和通常都不适合解析 XML(以及其他类似格式awksed例如 JSON 和 YAML 等)。例如,对于这个 XML 示例,我们不知道节点的InvoiceLines存储顺序或它们是否由换行符分隔。 XML 格式不关心这些事情,但是awkorsed脚本很容易失败,除非特别小心地覆盖所有可能的情况(包括数据的各种可能的编码),在这种情况下,您将不得不编写一个 XML无论如何解析器。

因此,使用 XML 解析器(如内置的解析器xmlstarlet)是正确的做法。


如果在文件中至少找到一个所需的节点,以下命令将打印输入文件的文件名file.xml。如果多个InvoiceLines节点匹配,文件名将被打印多次,中间有换行符。这意味着我们从一开始就取消包含换行符的文件名。

xmlstarlet sel \
    -t -m '/BillingData/InvoiceLinesList/InvoiceLines[chargeType = "D" and charge = "99"]' \
    --inp-name -nl file.xml

XPATH 查询将匹配所有InvoiceLines具有子节点chargeTypecharge具有指定值的节点。使用@charge而不是charge针对一个进行测试charge 属性InvoiceLines顺便说一句,在节点中。

将其应用于单个目录中的所有 XML 文件:

xmlstarlet sel \
    -t -m '/BillingData/InvoiceLinesList/InvoiceLines[chargeType = "D" and charge = "99"]' \
    --inp-name -nl ./*.xml

如果文件太多并且上面抛出错误,您可以使用xargs

printf '%s\n' ./*.xml | xargs xmlstarlet -t -m ...

或者,find(这也将搜索子目录):

find . -type f -name '*.xml' -exec xmlstarlet -t -m ... {} +

uniq如果您想让文件列表唯一,则通过管道传输结果。


我使用以下 XML 来测试上述内容:

<BillingData>
    <InvoiceLinesList>
        <InvoiceLines>
            <chargeType>D</chargeType>
            <charge>99</charge>
        </InvoiceLines>
        <InvoiceLines>
            <chargeType>D</chargeType>
            <charge>99</charge>
        </InvoiceLines>
        <InvoiceLines>
            <chargeType>E</chargeType>
            <charge>99</charge>
        </InvoiceLines>
    </InvoiceLinesList>
</BillingData>

相关内容