XMLをCSVに変換

XMLをCSVに変換

スクリプトを使用してxmlをcsvに変換する必要があります。 xmlstarletの解決策が見つかりましたが、利用できないため、0ポイントに戻ります。これは私の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>

そして、必要なCSVはヘッダが出力されることに注意してください。

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

ライブラリをインストールすることはできませんが、awk、perl、bashを使用できるため、ソリューションが開いています。

答え1

さて、ここには非常に基本的な質問があります。 XMLは詳細仕様を含む複雑な言語です。ライブラリがなければ、これは難しいでしょう。 XMLは基本的に正しく解析する必要があります。

例えばXML::TwigPerlを使用すると、次のようになります。

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";
    }
}

すでに利用可能であることがわかりますXML::Twig。これは非常に一般的な「基本インストール」です。だからまず確認してみてください。

これを行うための汚いハッキング方法がありますが、私は本物これはお勧めできません。私の言葉は本当に、本当に、壊れやすく、ひどいコードを生成するからです。

私はこれをより強い言葉で繰り返すことはできません。これを行う前に、以下を確認してください。https://stackoverflow.com/a/1732454/2566198

そして: https://stackoverflow.com/a/28913945/2566198

場合によっては、「ユーザー固有」のPerlモジュールをインストールできます。これは特に関連性があります。

そして、あなたのコードが意図的にXML仕様に違反していることを認識してください。これをテキストファイルとして扱います。これはあらゆる種類の悪いことです。特にこれを破るXMLに対して完全に有効な作業を行うことができるので、さらにそうです。

ただし、次のことを行う必要がある場合:

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);

以下を印刷します。

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

どのような生産機能にもこれを使用するには、まずインストールを許可していない人を刺し、必要なライブラリをインストールするようにしてください。これは難しい仕事のように聞こえますが、私を信じてください。上流のデータ型は(通常は有効な方法で)変更されていますが、下流のデータ型が変更され、ある日不明に破損する問題を解決しようとするよりも悪いことはありません。標準を実装します。

答え2

次の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>

そして使用

xsltproc sample.xsl sample.xml

答え3

ltXML2ツールキット(エディンバラ大学)のlxprintfを使用してください。たとえば、次のようになります。

$ 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

XSLT2を使用しても大丈夫ですが、この種の抽出には少し過剰です。


XML FAQ:http://xml.silmaril.ie/

答え4

使用xmlstarlet:

$ echo 'id_localisation;id_client;key'; xmlstarlet sel -t -m '//record/data' -v 'concat(../id_localisation,";",id_client,";",key)' -nl file.xml
id_localisation;id_client;key
8PJ;50C;C
8PJ;25C;D1
ESP31;70D;D2
ESP31;10D;D3

ヘッダが出力され、各ノードの上位ノード値と現在のノードの合計値を結合するechoXPathクエリを使用してデータが抽出されます。record/dataid_localisationrecordid_clientkey

抽出されたデータにセミコロンまたは改行文字が含まれていない場合、CSVパーサーは出力を読み取ることができます。


使用中xq(部分的yqhttps://kislyuk.github.io/yq/):

$ xq -r '[ "id_localisation", "id_client", "key" ], (.root.record[] | .id_localisation as $id | .data[] | [ $id, .id_client, .key ]) | @csv' file.xml
"id_localisation","id_client","key"
"8PJ","50C","C"
"8PJ","25C","D1"
"ESP31","70D","D2"
"ESP31","10D","D3"

式を使用してjqCSVテーブルを作成します。まず、ヘッダーを含む配列を作成し、ノードごとにdata1つの配列でXML構造から必要なデータを抽出します。その後、フォーマッタは@csvこれらの配列をCSVレコードに変換します。

区切り文字を通常のカンマからセミコロンに変更するには、たとえばcsvformatCSVパーサーで使用しますcsvkit

$ xq -r '...as before...' file.xml | csvformat -D ';'
id_localisation;id_client;key
8PJ;50C;C
8PJ;25C;D1
ESP31;70D;D2
ESP31;10D;D3

関連情報