converte xml para csv

2

eu preciso converter um xml para csv usando script. Eu encontrei uma solução com xmlstarlet, mas não está disponível, então estou retornando ao ponto 0. Aqui está o meu xml.

<root>
  <record>
  <id_localisation>8PJ</id_localisation>
  <data>
   <id_client>50C</id_client>  
      <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>
  <id_client>25C</id_client> 
      <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>Spa</city>
      </contact>
  </data> 
</record>
  <record>
  <id_localisation>ESP31</id_localisation>
  <data>
   <id_client>70D</id_client>  
            <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>StMarine</city>
      </contact>
  </data>
  <data>
        <id_client>10D</id_client>
          <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>Bahrein</city>
      </contact>
  </data>
 </record>
 </root>

E o csv que eu preciso, note que os cabeçalhos são enviados

id_localisation;id_client;key
8PJ;50C;C
 8PJ;25C;D1
 ESP1;70D;D2
 ESP1;10D;D3

Não consigo instalar nenhuma biblioteca, mas posso usar o awk, o perl, o bash, por isso estou aberto à solução.

    
por iceman225 21.04.2015 / 15:47

3 respostas

2

OK. Há um problema bem fundamental aqui. XML é uma linguagem complexa com uma especificação detalhada. Sem bibliotecas isso é difícil - XML é basicamente uma coisa que precisa de uma análise adequada.

Então, por exemplo, usando XML::Twig com o Perl, você obteria :

use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig->new()->parsefile ( 'your_xml_file.xml' );

print "id_localisation;id_client;key\n";
foreach my $record ( $twig->root->children('record') ) {
    foreach my $data ( $record->children('data') ) {
        print join( ";",
            $record->first_child_text('id_localisation'),
            $data->first_child_text('id_client'),
            $data->first_child_text('key'),
            ),
            "\n";
    }
}

Você pode achar que XML::Twig já está disponível - é uma 'instalação padrão' bastante comum. Então, verifique isso primeiro.

Existe um tipo sujo de maneira hacky de fazer isso, mas eu realmente não recomendaria fazer isso. Quero dizer realmente, porque faz código frágil e horrível.

Eu não posso reiterar isso em termos mais strongs. Antes de fazer isso, consulte: link

e: link

Note que você pode instalar módulos perl 'por usuário' em determinadas circunstâncias, o que pode ser particularmente relevante aqui.

E reconheça que seu código viola deliberadamente a especificação XML - tratando-a como um arquivo de texto. Isso é todo tipo de juju ruim, não menos importante, porque existem algumas coisas perfeitamente válidas que você pode fazer em XML, que irão quebrar isso.

No entanto, se você ABSOLUTAMENTE DEVE:

use strict;
use warnings;

open ( my $input_xml, "<", 'your_xml_file.xml' ) or die $!;
my $loca = "";
print "id_localisation;id_client;key\n";

for (<$input>) {
    my ($value) = (m/>(\w+)</);
    if (m/id_localisation/) { $loca = $value; }
    if (m/id_client/)       { print "$loca;$value;"; }
    if (m/key/)             { print "$value\n"; }
}
close($input);

Que imprimirá:

id_localisation;id_client;key
8PJ;50C;C
8PJ;25C;D1
ESP31;70D;D2
ESP31;10D;D3

Se você estiver planejando usar isso para qualquer tipo de função de produção, primeiro cutuque quem não permitir que você instale as coisas e faça com que instalem as bibliotecas de que você precisa. Isso pode soar como trabalho duro, mas confie em mim - não há nada pior do que tentar solucionar algo que misteriosamente quebrou um dia porque o formato de dados upstream mudou (em uma forma válida), mas um script downstream não implementa o padrão.

    
por 21.04.2015 / 17:05
1

Eu teria sugerido o seguinte arquivo xsl

<?xml version="1.0"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output type="text" indent="yes" omit-xml-declaration="yes" />

<xsl:template match="//record">

<xsl:for-each select="data"  >
<xsl:value-of select="../id_localisation" />;<xsl:value-of select="id_client" />;<xsl:value-of select="key "/><xsl:text>;
</xsl:text>
</xsl:for-each>
</xsl:template>

</xsl:stylesheet>

para ser usado com

xsltproc sample.xsl sample.xml
    
por 21.04.2015 / 17:02
0

Use o lxprintf do kit de ferramentas ltXML2 (Edinburgh University), por exemplo:

$ lxprintf -e data "%s;%s;%s\n" ../id_localisation id_client key test.xml
8PJ;50C;C
8PJ;25C;D1
ESP31;70D;D2
ESP31;10D;D3

Usar o XSLT2 é bom, mas é um exagero para esse tipo de extração.

Perguntas frequentes sobre XML: link

    
por 12.07.2016 / 00:35

Tags