如何提取XML文件的特定元素?

时间:2012-07-22 09:26:08

标签: xml linux bash

我有一个包含某些语言文本的XML文件。我想用一种语言提取文本并将它们存储在一个单独的文件中。我怎样才能做到这一点? 以下是我文件的一些起始行:

<?xml version="1.0" encoding="UTF-8"?>
<tmx version="1.4b">
  <header creationtool="ORESAligner" creationtoolversion="1.0" datatype="plaintext" segtype="paragraph" adminlang="en-us" srclang="EN" o-tmf="ORES"/>
  <body>
    <tu tuid="55_100:6">
      <prop type="session">55</prop>
      <prop type="committee">3</prop>
      <tuv xml:lang="EN">
        <seg>RESOLUTION 55/100</seg>
      </tuv>
      <tuv xml:lang="AR">
        <seg>القرار 55/100</seg>
      </tuv>
      <tuv xml:lang="ZH">
        <seg>第55/100号决议</seg>
      </tuv>
      <tuv xml:lang="FR">
        <seg>RÉSOLUTION 55/100</seg>
      </tuv>
      <tuv xml:lang="RU">
        <seg>РЕЗОЛЮЦИЯ 55/100</seg>
      </tuv>
      <tuv xml:lang="ES">
        <seg>RESOLUCIÓN 55/100</seg>
      </tuv>
    </tu>
  </body>
</tmx>

现在说我只想要英文文本。期望的输出应该是:

RESOLUTION 55/100

我该如何使用这个脚本?我是工作XML文件的新手,不知道如何使用这个XPath表达式。据我所知,xmlstarlet能够修改XML文件。但我不知道怎么......?

4 个答案:

答案 0 :(得分:3)

使用XmlStarlet提取英文节点

您可以使用query your XML xmlstarlet 用于XPath,并仅返回具有英语属性的节点。例如:

$ xmlstarlet sel -t -v "//tuv[@xml:lang='EN']/seg/text()" /tmp/foo
RESOLUTION 55/100

将节点值存储在具有语言扩展名的文件中

如果要将这些值存储在某些基于语言的文件中,则可以将找到的每个节点的值转储到具有基于语言的扩展名的文件中(例如,英语为“EN”)。

# Don't overwrite LANG; use some other variable.
language='EN'

xmlstarlet sel \
    --noblanks \
    --text \
    --template \
    --match "//tuv[@xml:lang='${language}']" \
    --value-of seg \
    -n \
    /tmp/foo > "/tmp/foo.$language"

通过此示例,所有匹配节点的内容将写入 /tmp/foo.EN 以进行进一步处理。您当然可以调整shell重定向以满足任何其他要求。

答案 1 :(得分:1)

如果xml文件格式正确,则可以使用简单的sed命令:

sed -n '/xml:lang="EN"/ {
N
s_.*<seg>\([^<]*\)</seg>_\1_p
}
' input_file

说明

sed -n '/xml:lang="EN"/ {           # 1) exec sed with no print flag, find a line
                                    # matching xml:lang="EN"
N                                   # 2) read the next line
s_.*<seg>\([^<]*\)</seg>_\1_p       # 3) replace everything until </seg> with 
                                    # the text between <seg> and </seg> and print
}
' input_file

如果您想保留seg代码,可以更改第3步:

sed -n '/xml:lang="EN"/ {
N
s_.*\(<seg>[^<]*</seg>\)_\1_p
}
' input_file

答案 2 :(得分:1)

以下XPath表达式提取您要查找的信息:

/tmx/body/tu/tuv[@xml:lang='EN']/seg

有许多工具允许您使用XPath表达式处理XML文件。如果您使用命令行工作,可以查看xmlsh

很难说出需求的上下文,但我想这会超出这里给出的简单情况,你会想看看XSLT和/或XQuery。

答案 3 :(得分:0)

您可以使用命令行工具xml_grep,如下所示:

xml_grep --cond "tu/tuv[@xml:lang='EN']/seg" --text_only file.tmx

--cond的参数是类似XPath的表达式。它的语法类似于xstarlet等所期望的,但不完全相同。