【问题标题】:Print XML element with AWK使用 AWK 打印 XML 元素
【发布时间】:2013-09-12 00:19:33
【问题描述】:

如何使用 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 元素的内容,从&lt;city...&gt;&lt;/city&gt;

【问题讨论】:

    标签: xml awk


    【解决方案1】:

    使用 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>
    

    data.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>
    

    【讨论】:

      【解决方案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 用于\&gt; 字边界功能。与其他 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>
      

      【讨论】:

      • 如果有两个城市,它会同时打印。我只想要第一个。
      • 有一个微不足道的调整,但如果您发布的问题以及您发布的代表性示例输入和预期输出实际上并未反映您想要的内容,那么请适当地更新您的问题,这样我们就不仅仅是旋转我们的轮子,试图猜测您的下一个需求变化可能是什么。
      猜你喜欢
      • 2019-04-15
      • 2019-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-06
      • 2017-09-30
      相关资源
      最近更新 更多