3

如何使用 AWK 打印 XML 元素的内容 - 从开始标记到结束标记?

例如,考虑以下 XML:

<flight>
    <airline>Delta</airline>
    <flightno>22</flightno>
    <origin>Atlanta</origin>
    <destination>Paris</destination>
    <departure>5:40pm</departure>
    <arrival>8:10am</arrival>
</flight>
<city id="AT"> 
       <cityname>Athens</cityname> 
       <state>GA</state>
       <description> Home of the University of Georgia</description>
       <population>100,000</population>
       <location>Located about 60 miles Northeast of Atlanta</location>
       <latitude>33 57' 39" N</latitude>
       <longitude>83 22' 42" W</longitude>
</city>

所需的输出可以是city元素的内容,从<city...></city>

4

2 回答 2

5

使用 awk 和 sed 等工具解析 XML 的解决方案并不完美。您不能依赖 XML 始终具有人类可读的布局。例如,某些 Web 服务会省略换行,从而导致整个 XML 文档出现在一行中。

我建议使用 xmllint,它能够使用 XPATH(一种为 XML 设计的查询语言)选择节点。

以下命令将选择城市标签:

xmllint --xpath "//city" data.xml

XPath 非常有用。它使 XML 文档的每个部分都可寻址:

xmllint --xpath "string(//city[1]/@id)" data.xml

返回字符串“AT”。

格式不正确的 XML 数据

这次返回“city”标签的第一次出现。xmllint 也可以用来漂亮地打印结果:

$ xmllint --xpath "//city[1]" data.xml  | xmllint -format -
<?xml version="1.0"?>
<city id="AT">
  <cityname>Athens</cityname>
  <state>GA</state>
  <description> Home of the University of Georgia</description>
  <population>100,000</population>
  <location>Located about 60 miles Northeast of Atlanta</location>
  <latitude>33 57' 39" N</latitude>
  <longitude>83 22' 42" W</longitude>
</city>

数据.xml

在同一数据中,第一个“城市”标签全部出现在一行上。这是有效的 XML。

<data>
  <flight>
    <airline>Delta</airline>
    <flightno>22</flightno>
    <origin>Atlanta</origin>
    <destination>Paris</destination>
    <departure>5:40pm</departure>
    <arrival>8:10am</arrival>
  </flight>
  <city id="AT"> <cityname>Athens</cityname> <state>GA</state> <description> Home of the University of Georgia</description> <population>100,000</population> <location>Located about 60 miles Northeast of Atlanta</location> <latitude>33 57' 39" N</latitude> <longitude>83 22' 42" W</longitude> </city>
  <city id="DUB">
    <cityname>Dublin</cityname>
    <state>Dub</state>
    <description> Dublin</description>
    <population>1,500,000</population>
    <location>Ireland</location>
    <latitude>NA</latitude>
    <longitude>NA</longitude>
  </city>
</data>
于 2013-09-08T13:19:31.540 回答
2
$ awk -v tag='city' '$0~"^<"tag"\\>"{inTag=1} inTag; $0~"^</"tag">"{inTag=0}' file
<city id="AT">
       <cityname>Athens</cityname>
       <state>GA</state>
       <description> Home of the University of Georgia</description>
       <population>100,000</population>
       <location>Located about 60 miles Northeast of Atlanta</location>
       <latitude>33 57' 39" N</latitude>
       <longitude>83 22' 42" W</longitude>
</city>

使用上面的 GNU awk 来实现\>字边界功能。与其他awks 使用[^[:alnum:]_]或类似。

只打印第一次出现:

$ awk -v tag='city' '$0~"^<"tag"\\>"{inTag=1} inTag{print; if ($0~"^</"tag">") exit}' file
<city id="AT">
       <cityname>Athens</cityname>
       <state>GA</state>
       <description> Home of the University of Georgia</description>
       <population>100,000</population>
       <location>Located about 60 miles Northeast of Atlanta</location>
       <latitude>33 57' 39" N</latitude>
       <longitude>83 22' 42" W</longitude>
</city>
于 2013-09-08T11:41:45.660 回答