XML ファイルから任意のデータをすばやく抽出して、CSV 形式にする必要がある場合があります。Unix ターミナルでこれを行うためのベスト プラクティスは何ですか? いくつかのコード例が欲しいのですが、たとえば、次の問題を解決するにはどうすればよいですか?
XML 入力の例:
<root>
<myel name="Foo" />
<myel name="Bar" />
</root>
私の望ましいCSV出力:
Foo,
Bar,
ピーターの答えは正しいですが、末尾の改行を出力します。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:template match="root">
<xsl:for-each select="myel">
<xsl:value-of select="@name"/>
<xsl:text>,</xsl:text>
<xsl:if test="not(position() = last())">
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
実行するだけ
xsltproc stylesheet.xsl source.xml
CSV 結果を標準出力に生成します。
xsltproc、saxonまたはxalanなどのコマンドライン XSLT プロセッサを使用して XML を解析し、CSV を生成します。あなたの場合はスタイルシートの例です:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="root">
<xsl:apply-templates select="myel"/>
</xsl:template>
<xsl:template match="myel">
<xsl:for-each select="@*">
<xsl:value-of select="."/>
<xsl:value-of select="','"/>
</xsl:for-each>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
XMLStarlet は、XML ドキュメントをクエリ/編集/チェック/変換するためのコマンド ライン ツールキットです (詳細については、「XMLStarlet コマンド ライン XML ツールキット」を参照してください) 。
ファイルを書き込む必要はありません。ファイルを xmlstarlet にパイプして、xpath フィルターを適用するだけです。
cat file.xml | xml sel -t -m 'xpathExpression' -v 'elemName' 'literal' -v 'elname' -n
-m 式 -v 値 '' 含まれるリテラル -n 改行
したがって、xpath の場合、xpath 式は //myel/@name となり、2 つの属性値が提供されます。
非常に便利なツールです。
任意の要素の name 属性だけが必要な場合は、簡単ではあるが不完全な解決策があります。
(サンプルテキストはファイルの例にあります)
grep "名前" の例 | カット -d"\"" -f2,2 | xargs -I{} エコー "{},"
これは、あなたの質問が要求することを正確に実行する小さな Ruby スクリプトです(「myel」という要素から「name」という属性を引き出します)。簡単に一般化できるはずです
#!/usr/bin/ruby -w
require 'rexml/document'
xml = REXML::Document.new(File.open(ARGV[0].to_s))
xml.elements.each("//myel") { |el| puts "#{el.attributes['name']}," if el.attributes['name'] }
テスト ファイルは test.xml にあります。
sed -n 's/^\s`*`<myel\s`*`name="\([^"]`*`\)".`*`$/\1,/p' test.xml
たとえば、各ミエルが1行にあることが厳密に指定されていない場合、最初にxmlファイルを「正規化」する必要があります(したがって、各ミエルは1つの個別の行にあります)
xmlファイルが「test.xml」であると仮定して、元の質問に答えます。
<root>
<myel name="Foo" />
<myel name="Bar" />
</root>
cat text.xml | tr -s "\"" " " | awk '{printf "%s,\n", $3}'