XMLからSMSデータを抽出する

XMLからSMSデータを抽出する

大きなSMSメッセージXMLファイルがあります。簡単にアクセスできるcsv形式にしたいです。 「address」、「messageBody」、「messageTime」の部分を具体的に抽出しようとしましたが、成功しませんでした。

<messageType>1</messageType><messageTime>1624297248761</messageTime><read>null</read><status>null</status><service_center>null</service_center><person>null</person><seen>1</seen></chat><chat><threadID>50</threadID><address>447917504050</address><messageBody>Yeah mate let's do lunch and catch up.</messageBody><messageType>1</messageType><messageTime>1629944007697</messageTime><read>null</read><status>null</status><service_center>null</service_center><person>null</person><seen>1</seen></chat><chat><threadID>50</threadID><address>447917563330</address><messageBody>You going now mate</messageBody>

私は次のような小さな成功を収めました。

cat SMS.xml | awk -F'address' '{print $2}'

しかし、これは行の最初の「アドレス」だけを取得し、残りは無視します。

このデータを読み取り可能なcsv形式に変換する方法についてのアイデアはありますか?

「messageTime」セクションの数字を説明するのを手伝ってくれてありがとう。

編集:実際のxmlファイルにはバランスの取れたオープンタグとクローズタグがあり、フォーマットが正しく指定されています。ここではいくつかの内容を抜粋しました。

答え1

XMLの形式が正しく、すべてのノードがいくつかの単一ノードの下にchat表示されると仮定すると、rootxqyqhttps://kislyuk.github.io/yq/):

xq -r '["address","messageBody","messageTime"], (.root.chat[] | [.address,.messageBody,.messageTime]) | @csv' file.xml

不足している開始タグと終了タグを追加して質問の破損したXMLを修正すると、次のCSV出力が生成されます。

"address","messageBody","messageTime"
,,"1624297248761"
"447917504050","Yeah mate let's do lunch and catch up.","1629944007697"
"447917563330","You going now mate",

答え2

その他コンマで区切られたデータ出力に対する回答:

xmlstarlet sel -t -m //chat -v messageTime -o , -v address -o , -v messageBody -n file.xml
1624297248761,,
1629944007697,447917504050,Yeah mate let's do lunch and catch up.
,447917563330,You going now mate

バッチメッセージの本文です。最後このコンマで区切られたデータは、最後まで3番目のフィールドを本文として持ちます。

メッセージ時間は、1970-01-01 00:00:00 UTC以降のミリ秒数です。これを処理する1つの方法はGNU awkを使用することです。

xmlstarlet sel -t -m //chat -v messageTime -o , -v address -o , -v messageBody -n file.xml \
| TZ=UTC gawk 'BEGIN {FS = OFS = ","} {$1 = strftime("%F %T", $1 / 1000)} 1'

出力

2021-06-21 17:40:48,,
2021-08-26 02:13:27,447917504050,Yeah mate let's do lunch and catch up.
1970-01-01 00:00:00,447917563330,You going now mate

この形式を使用すると、時系列で簡単に並べ替えることができます。

答え3

コメントで述べたように、XMLは正しくないため、次のようにすべてのテキストを新しいタグで囲みます。

<?xml version="1.0"?>
<myxml>
  <chat>
  ....your data which already includes </chat><chat> 
  </chat>
</myxml>

その後、次のように使用できますxmlstarlet(たとえば、住所を取得するため)。

xmlstarlet select --template --value-of /myxml/chat/address --nl input_file.xml

input_file.xml上記のように追加のラベルを含むデータを含める必要があります)

その他の例ここ

関連情報