【问题标题】:How to split a single XML file into multiple based on tags如何根据标签将单个 XML 文件拆分为多个
【发布时间】:2019-07-04 11:07:43
【问题描述】:

我有一个带有标签的 XML 文件。我想像这样拆分文件。

<?xml version="1.0" encoding="UTF-8"?>
<EMPRMART CREATION_DATE="08/20/2018 18:06:44" REPOSITORY_VERSION="187.96">
<REPOSITORY NAME="REP_DEV" VERSION="187" CODEPAGE="UTF-8" DATABASETYPE="Sybase">
<FOLDER NAME="MC_DEV" 
    <CONFIG DESCRIPTION ="Default ORDER configuration object" ISDEFAULT ="YES" NAME ="default_ORDER_config" VERSIONNUMBER ="1">
        <ATTRIBUTE NAME ="Advanced" VALUE =""/>
        <ATTRIBUTE NAME ="Order type" VALUE ="NO"/>
    </CONFIG>
    <ORDER DESCRIPTION ="" ISVALID ="YES" 
        <ATTRIBUTE NAME ="Normal" VALUE =""/>
        <ATTRIBUTE NAME ="Order type" VALUE ="NO"/>
    </ORDER>
    <ORDER DESCRIPTION ="" ISVALID ="YES" 
        <ATTRIBUTE NAME ="Medium" VALUE =""/>
        <ATTRIBUTE NAME ="Order type" VALUE ="NO"/>
    </ORDER>
    <ORDER DESCRIPTION ="" ISVALID ="YES" 
        <ATTRIBUTE NAME ="Advanced" VALUE =""/>
        <ATTRIBUTE NAME ="Order type" VALUE ="NO"/>
    </ORDER>
    <LOCATION DESCRIPTION ="" ISENABLED ="YES" 
    </LOCATION>
</FOLDER>
</REPOSITORY>
</EMPRMART>

下面是尝试过的代码。但它会将每一行生成一个新文件

awk  '
    BEGIN { RS = "</ORDER>" } 
    $0 ~ /[^[:blank:]\n]/ { 
        printf "%s\n", $0 RS >> FILENAME "_" ++i ".xml" 
    }
' test.xml

我想单独基于 ORDER 标签分割这个文件,如下所述

File1.xml
    <ORDER DESCRIPTION ="" ISVALID ="YES" 
        <ATTRIBUTE NAME ="Normal" VALUE =""/>
        <ATTRIBUTE NAME ="Order type" VALUE ="NO"/>
    </ORDER>        
File2.xml
    <ORDER DESCRIPTION ="" ISVALID ="YES" 
        <ATTRIBUTE NAME ="Medium" VALUE =""/>
        <ATTRIBUTE NAME ="Order type" VALUE ="NO"/>
    </ORDER>
File3.xml
<ORDER DESCRIPTION ="" ISVALID ="YES" 
        <ATTRIBUTE NAME ="Advanced" VALUE =""/>
        <ATTRIBUTE NAME ="Order type" VALUE ="NO"/>
    </ORDER>

【问题讨论】:

  • 您的 XML 无效。节点名称为ORDER 的节点未关闭。 FOLDERLOCATION 相同您缺少 &gt;

标签: linux shell unix awk


【解决方案1】:

为了实现您的要求,我不会使用 awk,而是使用良好的 XML 解析器,例如 xmlstarlet 或 xmlint。这里有一个未知数,即名称为ORDER 的节点总数。我们可以为选择写一个高级 XPath,但我们会保持简单:

xmlstarlet sel -t -v 'count(//ORDER)' file.xml

现在您有了计数,您可以遍历所有案例并将它们写入文件:

#!/usr/bin/env bash
xmlfile=file.xml

n=$(xmlstarlet sel -t -v 'count(//ORDER)' file.xml)
for i in $(seq 1 $n); do
   xmlstarlet sel -t -m "//ORDER[${i}]" -c . $xmlfile > "File${i}.xml"
done

【讨论】:

  • xmlstarlet 此实用程序未安装。
  • 如果您下载 cygwin for windows,可以选择包含 xmlstarlet 包。这就是我所做的。只需确保选择“查看”下拉菜单的“完整”选项...
【解决方案2】:

如果您确实使用gnu awk,这应该会给出您请求的结果。

awk '/<ORDER>/ {f=1;++a} f {print > "file_"a".xml"} /<\/ORDER>/ {f=0}' file

它将仅打印从 &lt;ORDER&gt;&lt;/ORDER&gt; 的行,作为名为 file_1.xmlfile_2.xml 等的文件中的一个部分。

【讨论】:

    【解决方案3】:

    在每个 UNIX 机器上的任何 shell 中使用任何 awk:

    awk '/<ORDER/{f=1; out="file_"(++c)".xml"} f{print > out} /<\/ORDER>/{close(out); f=0}' file
    

    它显然很脆弱,因为它只是对文本进行正则表达式匹配,而不是解析 XML,但它适用于您发布的示例和任何类似的文本。

    【讨论】:

      猜你喜欢
      • 2019-01-19
      • 1970-01-01
      • 2017-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-31
      • 2011-09-20
      相关资源
      最近更新 更多