【问题标题】:Extracting XML Child Node values based on a parent基于父节点提取 XML 子节点值
【发布时间】:2018-11-30 02:35:37
【问题描述】:

我有一个相当大的 xml,看起来像这样:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE tv SYSTEM "xmltv.dtd">
<tv source-info-url="http://blah blah blah.com/" source-info-name="blah.com" generator-info-name="zap2xml" generator-info-url="zap2xml@gmail.com">
                        <channel id="IX.XXXXXX.blah.com">
                                <display-name>WCBS</display-name>
                                <display-name>2 WCBS</display-name>
                                <display-name>2</display-name>
                                <icon src="https://blah blah blah.png" />
                        </channel>
                        <channel id="IX.XXXXX.blah.com">
                                <display-name>WCBSDT</display-name>
                                <display-name>2 WCBSDT</display-name>
                                <display-name>2</display-name>
                                <icon src="https://blah blah blah.png" />
                        </channel>
                        <channel id="IX.XXXXX.blah.com">
                                <display-name>WNBC</display-name>
                                <display-name>4 WNBC</display-name>
                                <display-name>4</display-name>
                                <icon src="https://blah blah blah.png" />
                        </channel>
                        .....
    </tv>

现在,我只想遍历 .xml,提取频道 ID TAG 值,然后提取第一个和第三个“显示名称”标记值,并根据该 ID 在每个频道显示它们。

我有这个:

#!/bin/bash
file='/path/to/xml/file/file.xml'
cat $file | while read line ; do
        if [[ $line == *"<channel id="* ]]; then
        channelid=$(echo $line|awk -F'"' '{print $2}')
        channelnum=$(xmlstarlet sel -t -v "//channel[@id='$channelid']//display-name[3]" -n $file)
        callsign=$(xmlstarlet sel -t -v "//channel[@id='$channelid']//display-name[1]" -n $file)
        clear
        echo "Here are the details for channel id: $channelid"
        echo ""
        echo "Channel Number is: $channelnum"
        echo "Channel Call Sign is: $callsign"
        echo ""
        sleep 2
        fi
done

which DOES 做我想做的事,但整个过程变慢了,因为它不断尝试查找它遇到的每个通道的外部实体链接 - 输出:

Here are the details for channel id: IX.XXXXX.blah.com

Channel Number is: 2
Channel Call Sign is: WCBS

/path/to/the/epg.xml:2.30: failed to load external entity "/path/to/the/script/xmltv.dtd"
<!DOCTYPE tv SYSTEM "xmltv.dtd">
                                ^
/path/to/the/xmlfile.xml:2.30: failed to load external entity "/path/to/the/script/xmltv.dtd"
<!DOCTYPE tv SYSTEM "xmltv.dtd">

如何抑制这些查找?我只想解析这些值。

【问题讨论】:

    标签: xml parsing entity external xmlstarlet


    【解决方案1】:

    如何抑制这些查找?

    您可以先使用xmlstarlet fo (format) command 删除 DOCTYPE 声明。

    您还应该能够通过使用xmlstarlet sel (select) command 和XPath 来获得您需要的所有值。尝试使用正则表达式对文件进行分类、读取行和解析可能很脆弱。

    完整示例...

    #!/bin/bash
    
    file='/path/to/the/file.xml'
    
    xmlstarlet fo -D $file | \
    xmlstarlet sel -T -t -m "/tv/channel" \
        -v "concat('Here are the details for channel id: ', @id)" -nl -nl \
        -v "concat('  Channel Number is: ', display-name[3])" -nl \
        -v "concat('  Channel Call Sign is: ', display-name[1])" -nl -nl
    

    输出...

    Here are the details for channel id: IX.XXXXXX.blah.com
    
      Channel Number is: 2
      Channel Call Sign is: WCBS
    
    Here are the details for channel id: IX.XXXXX.blah.com
    
      Channel Number is: 2
      Channel Call Sign is: WCBSDT
    
    Here are the details for channel id: IX.XXXXX.blah.com
    
      Channel Number is: 4
      Channel Call Sign is: WNBC
    

    【讨论】:

    • 这很棒@Daniel。绝对快速,是使用的一个很好的例子。但是,我怎样才能像我一样将 id、channel 和 sign 作为变量一起捕获(即,如果你愿意的话,一个“记录”)?这就是逐行/正则表达式例程的原因....您的示例很好地解析了所有内容,但它将结果作为 BATCH 而不是逐个记录/行转储。
    • @AMPSYS - 您可以在问题中添加所需输出的示例吗?
    • 我想将频道号和呼号捕获为匹配其父频道 ID 的变量。我现在只是回显输出以测试该捕获,但真正的目的是操作其他文件或在数据库中创建/更新记录。这更有意义吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-19
    相关资源
    最近更新 更多