Awk将xml解析为csv

Awk将xml解析为csv,xml,csv,awk,Xml,Csv,Awk,我有一个xml,我想将其解析为csv,就像我开始使用awk一样,我想继续使用它,但我知道可以使用perl这样的超语言,我也找到了xmlstarlet,但我没有在服务器上安装的权限,所以我对超解决方案持开放态度。 所以我的输入xml是 <?xml version="1.0"?> <root> <record> <id_client>50C</id_client> <data> <ma

我有一个xml,我想将其解析为csv,就像我开始使用awk一样,我想继续使用它,但我知道可以使用perl这样的超语言,我也找到了xmlstarlet,但我没有在服务器上安装的权限,所以我对超解决方案持开放态度。 所以我的输入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>
你可以试试这个:

awk 'BEGIN{ RS="record"; FS="[<>]" } { print $10 "," $14 "," $18 }' file
awk'BEGIN{RS=“record”;FS=“[]”“}{print$10”、“$14”、“$18}”文件
这不是最方便的方法。最好是:

awk -F'[<>]' '$2 == "mail" || $2 == "adress" { printf "%s\, ", $3 }; $2 == "num_tel" { print $3 }' a
awk-F'[]'$2==“邮件”| |$2==“地址”{printf“%s\,”,$3}$2==“num_tel”{print$3}'a
这样,只要不更改密钥,就可以毫无问题地添加其他行。

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

#!/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> 


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

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

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

基于文本的一行:

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 ";" - - - -
cat input.xml | grep-e \-e \-e \-sed's/]*>//g'| sed's/^\s*//g;s/\s*$//g'|粘贴-d”;“-”-
说明:

  • 读取输入文件(
    cat input.xml
  • 获取相应的标记行(使用
    grep
  • 使用删除XML标记,只保留标记内容(使用
    sed
  • 修剪空格(再次使用
    sed
    ;单个sed命令中有两个表达式:一个用于前导空格,一个用于拖带空格)
  • 将每4行粘贴为列(使用
    粘贴

  • 逐行解析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
    

    该XML看起来有点不完整。缺少
    标记,应该是结束
    标记的是开始
    ,第二条记录中的
    标记只有一半。实际输入的数据是否也被破坏了,或者仅仅是示例?这是我的错误,我纠正了它,但是文件在生成时没有被破坏。您是否可以访问任何XML处理工具,如xsltproc、xalan、xmllint或xmlstarlet?您不希望使用awk或其他纯文本工具执行此操作。您可以从CPAN安装Perl模块吗?如果其他一切都失败了,你有权访问Python吗?我没有安装anithing的权限,因为客户服务器只是把我的文件放进去并使用它。你误读了我,我想使用awk,因为我开始理解syntaxI,我想我们不会误读你:awk只是(xml)问题的一个糟糕的解决方案。XML数据需要真正理解XML的工具;使用XSLT。Python也是一个不错的选择。Ruby的标准库中也有一个XML解析器。是否可以创建文件来自动执行xmlstarlet?谢谢,我要和我的厨师谈谈xmlstarlet,这正是我们需要使用的!您只需在其周围包装一个shell脚本,就像使用awk命令一样。您好,如果值有空格,则无法正确获取这些值。我怎么会忽略空格?你好,阿努。我已经更新了行,使用sed而不是awk来修剪值。这是一个较长的语句,但提供了所需的灵活性。
    xalan -xsl filename.xsl -in filename.xml
    
    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 ";" - - - -
    
    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
    
    #!/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);