如何使用AWK将多个XML中的数据提取到表中

时间:2016-07-23 10:55:44

标签: xml bash awk

我在一个目录中有多个XML文件,我想从中提取不同类型的数据到一个类似于表的输出(字段之间的选项卡)。 此外,我想有标题(列名),以及一些列中的布尔插值。

我准备了2个样本XML文件,可以在下面找到,我希望有一个AWK命令,它将运行该目录中的所有文件,并提取以下值:

  1. 文件名称
  2. “property1”(数字)
  3. 的值
  4. “property2”(布尔值)
  5. 的值
  6. 字符串“$ test1 $”
  7. 字符串“$ test2 $”,如果存在

    • 在真实目录中,我有200多个文件,我希望所有这些文件都能在输出中表示,即使其中一些文件没有任何上述值。

      < / LI>
    • 请注意,值“$ test1 $”和“$ test2 $”位于不同的父元素下。 “property1”和“property2”元素(上面列表中的#2和#3)将始终保持不变,但不一定按相同的顺序排列(如下面的输入文件所示)。

    • 我知道如何使用文件名和上面列表中的其他值之一(使用AWK中的FILENAME内置参数)获取所需的输出,但是我似乎无法正确添加其他值。

    • 据我所知,AWK是用于此类事情的最佳工具,但是如果你想到另一种能提供相同输出的工具,那么我对它的确比较好:-)

  8. 请在下面找到XML文件(输入数据):

    TextXML1.xml:

     <?xml version="1.0" encoding="UTF-8"?>
    <TestXML1>
        <properties>
            <property name="property1" value="500"></property>
            <property name="property2" value="true"></property>
        </properties>
        <attrs>
            <attr type='parameter' name='T1234'>
                <parameter input='$test1$'></parameter>
            </attr>
            <attr type='parameter' name='H5H7'>
                <parameter input='$test2$'></parameter>
            </attr>
        </attrs>
    </TestXML1>
    

    TestXML2.xml:

     <?xml version="1.0" encoding="UTF-8"?>
    <TestXML2>
        <properties>
            <property name="property2" value="False"></property>
            <property name="property1" value="300"></property>
        </properties>
        <attrs>
            <attr type='parameter' name='TD837'>
                <parameter input='$test1$'></parameter>
            </attr>
            <attr type='parameter' name='JQE284'>
                <parameter input='$test3$'></parameter>
            </attr>
        </attrs>
    </TestXML2>
    

    所需的输出:

        File name   property1   property2   $test1$     $test2$
    TestXML1.xml   500      True        True        True
    TestXML2.xml   300      True        True        False
    

    非常感谢!

2 个答案:

答案 0 :(得分:1)

以下是如何使用GNU awk为第3个arg提取所有名称,值和输入以匹配()和真正的多维数组:

$ cat tst.awk
match($0,/\<name="([^"]*)".*\<value="([^"]*)"/,a) { n2v[a[1]][ARGIND] = a[2] }
match($0,/\<input=\047([^\047]*)\047/,a) { inputs[a[1]][ARGIND] }
END{
    printf "Filename"
    for (name in n2v) {
        printf "%s%s", OFS, name
    }
    for (input in inputs) {
        printf "%s%s", OFS, input
    }
    print ""

    for (fileNr=1; fileNr<ARGC; fileNr++) {
        printf "%s", ARGV[fileNr]
        for (name in n2v) {
            printf "%s%s", OFS, (fileNr in n2v[name] ? n2v[name][fileNr] : "N/A")
        }
        for (input in inputs) {
            printf "%s%s", OFS, (fileNr in inputs[input] ? "True" : "False")
        }
        print ""
    }
}

$ awk -f tst.awk TestXML1.xml TestXML2.xml
Filename property1 property2 $test1$ $test2$ $test3$
TestXML1.xml 500 true True True False
TestXML2.xml 300 false True False True

您可以轻松调整它,只选择您关心的那些。

答案 1 :(得分:0)

正如其他人已经指出的那样,你不应该使用像awk这样的面向行的工具来处理XML。请使用类似xmlstarlet的XML感知工具。这是您问题的部分解决方案:

xmlstarlet sel -t -v //property/@value -nl -v //parameter/@input -nl TestXML1.xml TestXML2.xml