構造化データ型のいくつかの出力があり、それをXMLに変換する必要があります。
マイユースケースは、Palo Altoファイアウォールが設定を復元するために使用できないコマンドラインインターフェイスを介して設定出力を提供することです。使用する前にXMLに変換する必要があります。
形式は次のとおりです(アイデアを理解するためのより大きなファイルの一部)。
unknown-applications {
unknown-tcp {
destinations-per-hour 10;
sessions-per-hour 10;
session-length {
maximum-bytes 100;
minimum-bytes 50;
}
}
unknown-udp {
destinations-per-hour 10;
sessions-per-hour 10;
session-length {
maximum-bytes 100;
minimum-bytes 50;
}
}
}
そして必要
<unknown-applications>
<unknown-tcp>
<destinations-per-hour>10</destinations-per-hour>
<sessions-per-hour>10</sessions-per-hour>
<session-length>
<maximum-bytes>100</maximum-bytes>
<minimum-bytes>50</minimum-bytes>
</session-length>
</unknown-tcp>
<unknown-udp>
<destinations-per-hour>10</destinations-per-hour>
<sessions-per-hour>10</sessions-per-hour>
<session-length>
<maximum-bytes>100</maximum-bytes>
<minimum-bytes>50</minimum-bytes>
</session-length>
</unknown-udp>
</unknown-applications>
これを達成できるパーサーのようなものはありますか?
編集:コメントのため、あまり投稿できないので:ありがとう。有望に見えます!
例を記載していないため、一部の部品が正しく変換されませんでした。
import {
network {
interface [ ethernet1/5 ethernet1/6];
}
}
に変換されます
<import>
<network>
<interface>[</interface>
</network>
</import>
しかし、そうしなければなりません。
<import>
<network>
<interface>
<member>ethernet1/5</member>
<member>ethernet1/6</member>
</interface>
</network>
</import>
メンバーにするために[]のようないくつかの特定のことがあるので、手動で行うことが可能かどうかわかりません... raw形式もxml形式でなければなりません。
答え1
入力形式は非標準なので、これを処理するにはパーサーを作成する必要があります。 2つのアプローチがあります。手続き型プログラミング言語(通常はトップダウン再帰的立下りパーサー)で「直接」作成することも、一種のパーサージェネレータを使用することもできます。後者のアプローチでは、入力文法のBNFを定義し、ツールがパーサーを構築します。 Scalaの使い方を知っていればとても簡単です。
XMLの世界でよく使われる別のパーサジェネレータはRExです。これはXQueryまたはXSLTからパーサーを生成するので、問題のXML生成の側面を非常に簡単にするので便利です。これは素晴らしいソフトウェアですが、残念ながら関連文書が不足しています。 。別のXML指向ツールは、Stephen Pembertonの「Invisible XML」(https://homepages.cwi.nl/~steven/ixml/) - RExが優れたソフトウェアですが、文書化が不足している場合、残念ながらInvisible XMLは文書化は優れていますが、リリースされたソフトウェアではありません。
私は別の安くて楽しい方法を考えました。正規表現に基づく非常に単純なエディタスクリプトを使用すると、次のことができます。
- 名前を引用符で囲み、終了コロンを追加します。
- セミコロンをカンマに置き換える
その後、多くのJSONパーサーが許可するものを取得します(セミコロンが区切り文字ではなくターミネーターであるため、これは請求書に収まりませんが、多くのJSONパーサーがこれを許可します)。
答え2
awk
以下は、データが表示されているものとまったく同じであると仮定する簡単なプログラムです。
- 先行タグは
{
タグのみを含む行にあり、 - データのある行には正確に1つのラベルが含まれ、その後に単語と
;
、 - それぞれは
}
何もせずに1行に表示されます。
スタックを使用して現在使用中のタグを追跡し、新しいタグが入力に表示されたらスタックにプッシュします。 aが見つかると、}
スタックの上部の終了マーカーが出力されます。データラインは{
単一文字で終わらないという事実で検出されます}
。
何らかの方法でデータを検証する試みは行われなかった。
$NF == "{" {
stack[++top] = $1 # push tag to stack
printf "<%s>\n", stack[top] # output opening tag
next
}
$NF == "}" {
printf "</%s>\n", stack[top--] # output closing tag + pop stack
next
}
{
sub(";$", "", $2) # remove ; from EOL
printf "<%s>%s</%s>\n", $1, $2, $1 # output tag with data
}
サンプルデータの場合、awk -f script.awk data.in
歩留まり
<unknown-applications>
<unknown-tcp>
<destinations-per-hour>10</destinations-per-hour>
<sessions-per-hour>10</sessions-per-hour>
<session-length>
<maximum-bytes>100</maximum-bytes>
<minimum-bytes>50</minimum-bytes>
</session-length>
</unknown-tcp>
<unknown-udp>
<destinations-per-hour>10</destinations-per-hour>
<sessions-per-hour>10</sessions-per-hour>
<session-length>
<maximum-bytes>100</maximum-bytes>
<minimum-bytes>50</minimum-bytes>
</session-length>
</unknown-udp>
</unknown-applications>
実行するxmlstarlet fo
と
<?xml version="1.0"?>
<unknown-applications>
<unknown-tcp>
<destinations-per-hour>10</destinations-per-hour>
<sessions-per-hour>10</sessions-per-hour>
<session-length>
<maximum-bytes>100</maximum-bytes>
<minimum-bytes>50</minimum-bytes>
</session-length>
</unknown-tcp>
<unknown-udp>
<destinations-per-hour>10</destinations-per-hour>
<sessions-per-hour>10</sessions-per-hour>
<session-length>
<maximum-bytes>100</maximum-bytes>
<minimum-bytes>50</minimum-bytes>
</session-length>
</unknown-udp>
</unknown-applications>