【问题标题】:Parsing large XML file for specific instance of a repeating element为重复元素的特定实例解析大型 XML 文件
【发布时间】:2014-01-28 12:45:24
【问题描述】:

我有一个非常大的 XML 文件,我需要从中提取一些信息。我一直在尝试使用sed 脚本来执行此操作,但遇到了一些问题。实际上,同一个 XML 文件有两种版本,一种格式很好,另一种只是一个巨大的单行 XML。每个人都有不同的问题。

格式化文件:

我要从中提取数据的元素之一称为<name>,但该元素有多个实例,我只想要数据在一个特定的上下文中。这就是我的意思:

XML 看起来像这样:

 <object uid="1234567890-00000000">
   <name>Object Name</name>
   <country>United States</country>
   <state>Texas</state>
   <county>Travis</county>
   <timeZone>-06:00</timeZone>
   <datum uid="datum_UID">
     <name>Datum Name</name>
     <code>DUID</code>
   </datum>
 </object>

我的最终目标是生成一个以空格分隔的两列文件,其中包含第一列中的对象uid 和第二列中的对象name。我的第一个想法是 sed 分别为每个结果构建两个临时文件,然后将它们组合成一个。问题是,当我 sed 获取名称元素时,我无法弄清楚如何只获取对象 &lt;name&gt; 元素,而不是获取基准 &lt;name&gt; 元素。

我用于查找对象uidsed 脚本似乎运行良好:

sed -n -e 's/^.*<object uid="\([-0-9]*\)">.*/\1/p' $infile > $outfile

$infile 是大 XML 文件,$outfile 是我想要保存生成的uids 的任何位置。这是我为name 提供的内容,这显然行不通,因为它将与&lt;name&gt; 标记的每个实例匹配:

sed -n -e 's/^.*<name>\([^<]*\)<.*/\1/p' $infile > $outfile2

有没有办法用sed 做到这一点?请记住,该文件非常大(超过 5000 万行)。我通过多行搜索找到了this blog,我可以尝试,但如果我理解正确,这会在搜索之前将所有行连接到保持缓冲区中,而我对sed 的了解不够知道这是否是一个非常糟糕的主意,超过 5000 万行。

单行文件:

我尝试使用一个 sed 脚本使用单行文件一步完成所有操作,但最终我只得到了最后一个匹配项作为输出。这是我为此使用的sed 脚本:

sed -n -e 's/^.*<object uid="\([-0-9]*\)"><name>\([^<]*\)<.*/\1 \2/p' $infile > $outfile

我想我知道为什么这个表达式不起作用(开头和结尾的 .* 匹配我想要的数据之前/之后的所有内容),但我无法修复它。我已经尝试了表达式的一些变化,但我从来没有得到我正在寻找的结果。它要么只打印最后一个结果,要么打印整行(在这种情况下是整个文件)。如何从单行文件中解析出每个匹配项?

【问题讨论】:

    标签: xml parsing sed


    【解决方案1】:

    这里有一个使用XML解析工具xmlstarlet的方法:

    xmlstarlet sel -t -m //object -v @uid -nl -v name -nl test.xml  | paste - -
    
    1234567890-00000000 Object Name
    2   second
    

    鉴于此“test.xml”:

    <objects>
    <object uid="1234567890-00000000">
       <name>Object Name</name>
       <country>United States</country>
       <state>Texas</state>
       <county>Travis</county>
       <timeZone>-06:00</timeZone>
       <datum uid="datum_UID">
         <name>Datum Name</name>
         <code>DUID</code>
       </datum>
     </object>
    <object uid="2">
       <name>second</name>
       <datum uid="datum_UID">
         <name>not me</name>
       </datum>
     </object>
    </objects>
    

    【讨论】:

    • 这在我创建一个包含 2 或 3 条记录的小测试文件时有效,但是当我通过它运行较大的文件时,我没有得到任何输出。该程序在大约 1 秒后终止,没有任何类型的输出。进一步调查表明这可能是包装器标记中的 xmlns 或版本存在问题。当包含这些时,它不起作用,但是当它们不包含时,它会起作用。这些是否需要在xmlstarlet 命令中省略或以某种方式处理?
    猜你喜欢
    • 2014-10-03
    • 1970-01-01
    • 1970-01-01
    • 2017-12-29
    • 2017-10-30
    • 1970-01-01
    • 1970-01-01
    • 2011-05-09
    • 1970-01-01
    相关资源
    最近更新 更多