簡體   English   中英

awk 將 xml 解析為 csv

[英]Awk parse xml to csv

我有一個 xml,我想將其解析為 csv,就像我開始使用 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 時會遇到很多問題: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

給出這個答案是為了說明從問題描述中顯示的特定 .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

使用 Python,它的標准庫中有一個XML 解析器,並且很有可能預裝在您必須部署到的服務器上:

#!/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 處理器,它也能正常工作; 查閱其聯機幫助頁以了解它希望如何被調用。

你可以試試這個:

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

這樣您就可以毫無問題地添加其他行,只要您不更改密鑰。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM