2015-04-14 5 views
0

У меня есть xml, который я хочу проанализировать в csv, например, я начал работать с awk, я бы хотел продолжить его, но я знаю, что это можно сделать с помощью более языка, например perl Я нашел xmlstarlet, но у меня нет разрешения на установку на сервере, поэтому я открываю все решения. Так что мой Iinput XML являетсяAwk parse xml to csv

<?xml version="1.0"?> 
<root> 
    <record> 
    <id_client>50C</id_client> 
    <data> 
      <mail>[email protected]</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>[email protected]</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>[email protected]</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>[email protected]</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 с hearders

id_client;mail;num_tel;key 
50C;[email protected];001;C 
50C,[email protected];02200;D1 
70D;[email protected];5555;D2 
70D;[email protected];881.0;D3 
+0

Это XML выглядит немного сломана.Отсутствуют теги '', то, что должно быть закрывающим тегом '', является открытием '', а тег' 'во второй записи - только половина. Являются ли фактические входные данные также сломанными, или это просто пример? – Wintermute

+0

это моя ошибка, я исправлю его, однако файл не разбит, когда он сгенерирован. – iceman225

+0

Используйте XML-парсер, такой как xmllint. –

ответ

2

Вы столкнулись с множеством проблем, анализирующих 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;[email protected];001;C 
50C;[email protected]maiil.com;02200;D1 
70D;[email protected];5555;D2 
70D;[email protected];881.0;D3 
+0

Можно ли создать файл, чтобы автоматически excute xmlstarlet? – iceman225

+0

спасибо i'am goind, чтобы поговорить о xmlstarlet с моим шеф-поваром, это именно то, что нам нужно использовать! – iceman225

+0

Вы просто обернете вокруг него скрипт оболочки, как и вы, используя команду awk. –

1

Вы можете попробовать это:

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 

Таким образом, вы можете добавить другие линии без проблем, до тех пор, пока вы не измените ключи.

1

С 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, он будет работать так же хорошо; проконсультируйтесь с его man-страницей, чтобы узнать, как он хочет быть вызванным.

+0

Лучший ответ; используйте XSLT. Python - отличный выбор. Ruby также имеет XML-парсер в своей стандартной библиотеке. –

2

Один лайнер:

grep -e \<mail\> -e \<adress\> -e \<num_tel\> -e \<key\> kk.xml | sed 's/<[^>]*>//g' | awk '{ print $1 }' | paste -d ";" - - - - 

Объяснение:

  1. Получить соответствующие линии
  2. удалить теги XML
  3. уравновешивания пространства
  4. Вставить как столбцы
0
#!/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);