【问题标题】:Awk parse xml to csvawk 将 xml 解析为 csv
【发布时间】:2015-06-20 02:14:03
【问题描述】:

我有一个要解析为 csv 的 xml,就像我开始使用 awk 一样,我想继续使用它,但我知道可以使用 perl 之类的语言来完成它,我也找到了 xmlstarlet,但我没有在服务器上安装的权限,所以我对解决方案持开放态度。 所以我的 iinput xml 是

<?xml version="1.0"?>
<root>
  <record>
   <id_client>50C</id_client>  
  <data>
          <mail>1@mail.com</mail>
          <adress>10  </adress>
          <num_tel>001</num_tel>
          <key>C</key>
      <contact>
        <name>toto</name>
        <birth>01/30/009</birth>
        <city>London</city>
      </contact>
  </data> 
  <data>
          <mail>2@gmaiil.com</mail>
          <adress>20</adress>
          <num_tel>02200</num_tel>
          <key>D1</key>
      <contact>
        <name>tata</name>
        <birth>02/08/2004</birth>
        <city>Bruges</city>
      </contact>
  </data> 
</record>
   <record>
   <id_client>70D</id_client>  
  <data>
          <mail>3@gmail.com</mail>
          <adress>7Bcd</adress>
          <num_tel>5555</num_tel>
          <key>D2</key>
      <contact>
        <name>titi</name>
        <birth>05/07/2014</birth>
        <city>Paris</city>
      </contact>
  </data>
  <data>
          <mail>4@gmail.com</mail>
          <adress>888</adress>
          <num_tel>881.0</num_tel>
          <key>D3</key>
      <contact>
        <name>awk</name>
        <birth>05/08/1999</birth>
        <city>Lisbone</city>
      </contact>
  </data>

我想将这个 csv 与听众一起输出到一个过度文件中

id_client;mail;num_tel;key 
50C;1@mail.com;001;C
50C,2@gmail.com;02200;D1
70D;3@gmail.com;5555;D2 
70D;4@gmail.com;881.0;D3

【问题讨论】:

  • XML 看起来有点损坏。缺少&lt;/record&gt;标签,应该是结束&lt;/root&gt;标签是一个开始&lt;root&gt;,而第二条记录中的&lt;/key&gt;标签只有一半。实际输入数据是否也损坏了,还是只是示例?
  • 这是我的错误,我纠正了它,但是文件在生成时没有损坏
  • 好的。您是否可以访问任何 XML 处理工具,例如 xsltproc、xalan、xmllint 或 xmlstarlet?您不想使用 awk 或其他纯文本工具来执行此操作。你能从 CPAN 安装 Perl 模块吗?如果一切都失败了,你可以访问 Python 吗?
  • 我没有安装任何东西的权限,因为它是客户服务器,只是放置我的文件并使用它。你误读了我我想使用 awk 因为我开始理解语法
  • 我认为我们没有误读您:awk 只是解决 (xml) 问题的一个坏方法。 XML 数据需要真正理解 XML 的工具。

标签: xml csv awk


【解决方案1】:

在逐行解析 XML 时会遇到很多问题:XML 不是面向行的数据格式。

使用特定于 XML 的工具。它可以是多么简单:

xmlstarlet sel -t \
  -m / -o "id_client;mail;num_tel;key" -n -b \
  -m /root/record/data -v ../id_client -o ";" -v mail -o ";" -v num_tel -o ";" -v key -n \
file.xml
id_client;mail;num_tel;key
50C;1@mail.com;001;C
50C;2@gmaiil.com;02200;D1
70D;3@gmail.com;5555;D2
70D;4@gmail.com;881.0;D3

【讨论】:

  • 是否可以创建文件以自动执行 xmlstarlet ?
  • 谢谢你,我会和我的厨师谈谈 xmlstarlet 它正是我们需要使用的!
  • 您只需在其周围包裹一个 shell 脚本,就像使用 awk 命令一样。
【解决方案2】:

给出这个答案是为了说明从问题描述中显示的特定 .xml 格式中提取信息的基于文本的过程(相同的 .xml 可以采用不同的格式 - 例如,没有换行符 - 使描述的过程这里不合适)。

如果可能,请使用特定于 XML 的工具作为xmllint

基于文本的单行:

cat input.xml | grep -e \<mail\> -e \<adress\> -e \<num_tel\> -e \<key\> | sed 's/<[^>]*>//g' | sed 's/^\s*//g; s/\s*$//g' | paste -d ";" - - - -

解释:

  1. 读取输入文件 (cat input.xml)
  2. 获取适当的标签行(使用grep
  3. 删除带有的XML标签,只留下标签内容(带有sed
  4. 修剪空格(再次使用 sed;单个 sed 命令中的两个表达式:一个用于前导空格,一个用于尾随空格)
  5. 每 4 行粘贴为列(使用 paste

【讨论】:

  • 嗨,如果它们有空格,这就是不正确地取值。我怎么会忽略空格?
  • 你好阿努。我已更新该行以使用 sed 而不是 awk 来修剪值。这是一个较长的声明,但提供了您想要的灵活性。
【解决方案3】:

使用 Python,它的标准库中有一个 XML parser,并且很有可能被预安装在您必须部署到的服务器上:

#!/usr/bin/python

import xml.etree.ElementTree as ET
import sys

tree = ET.parse(sys.argv[1])
root = tree.getroot()

print "id_client;mail;num_tel;key"

# Rudimentary error handling: If a field is not there,
# print (nil) in its stead.    
def xml_read(node, key):
    p = node.find(key)
    if p is None:
        return "(nil)"
    return p.text

for r in root.iter("record"):
    for d in r.iter("data"):
        print xml_read(r, "id_client") + ";" + xml_read(d, "mail") + ";" + xml_read(d, "num_tel") + ";" + xml_read(d, "key")

或者,如果您可以访问 XSLT 处理器(尽管我不敢这样),您可以使用以下样式表:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/root">id_client;mail;num_tel;key
<xsl:for-each select="record">
  <xsl:for-each select="data"><xsl:value-of select="../id_client"/>;<xsl:value-of select="mail"/>;<xsl:value-of select="num_tel"/>;<xsl:value-of select="key"/><xsl:text>&#xa;</xsl:text></xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet> 

使用

xsltproc filename.xsl filename.xml

xalan -xsl filename.xsl -in filename.xml

其中filename.xsl 是包含上述XSLT 的文件。如果您有不同的 XSLT 处理器,它也能正常工作;请查阅其手册页以了解如何调用它。

【讨论】:

  • 最佳答案;使用 XSLT。 Python 也是一个不错的选择。 Ruby 在其标准库中也有一个 XML 解析器。
【解决方案4】:

你可以试试这个:

awk 'BEGIN{ RS="record"; FS="[<>]" } { print $10 "," $14 "," $18 }' file

这不是最便携的方式。更好的是:

awk -F'[<>]' '$2 == "mail" || $2 == "adress" { printf "%s\, ", $3 }; $2 == "num_tel" { print $3 }' a

这样你就可以毫无问题地添加其他行,只要你不改变键。

【讨论】:

    【解决方案5】:
    #!/usr/bin/perl
    use XML::DT;
    
    my %handler=(
      -default  => sub{ $c},                # $c - element contents
      -type     => { data => "MAP" },       # data suns became (tag => $c)
    
      id_client => sub{ father(id=>$c);},
      data      => sub{ print father("id"),";$c->{mail};$c->{num_tel};$c->{key}\n"},
    );
    dt(shift, %handler);
    

    【讨论】:

      猜你喜欢
      • 2015-08-08
      • 2015-07-06
      • 1970-01-01
      • 2015-05-26
      • 2018-05-18
      • 2021-07-04
      • 1970-01-01
      • 2016-05-08
      • 2016-05-04
      相关资源
      最近更新 更多