1

このディスカッションでは、いくつかの優れたコマンドライン XML 操作ツールを見ました。また、コンパイル済みプログラムの代わりにスクリプトを使用して、XML ファイルからデータを抽出する新しい方法を模索しています。現在xmlstarletを試していますが、このツールの使用に制限されていません。

何万もの要素を含む XML データ ファイルがあります。検索用語のリストに基づいてこれらの要素のサブセットを抽出し、それらの要素を下流のスクリプトや変換にパイプするか、別の方法でルーティングしたいと考えています。検索用語は単純な文字列です。正規表現は必要ありません。通常のテキスト ファイルに対して grep を使用してこれを行っていた場合、おそらく次のような単純なことを行うでしょう。

grep -Ff StringsToSearchFor.txt MassiveFile.txt | [chain of additional commands]

これを達成する方法について xmlstarlet などのツールのドキュメントを調べてきましたが、思いつく最も近いものは、一時ファイルを使用するこの醜い試みです。(注、私はWindowsを使用しています):

REM Create tempOutput.xml, with an open root node 

REM %1 is the file containing the list of strings
REM %2 is the target XML file
for /F %%A in (%1) do (
   REM Search for a single matching node, and append the output to tempOutput.xml
   xml sel -I -t -c "path/to/search[targetElement='%%A']" %2 >> tempOutput.xml
)

REM Close root node to tempOutput.xml

REM After this stage, pass tempOutput.xml as the input to downstream XML transforms and tools

言うまでもなく、これは本当に醜いです。

-cXPath クエリの膨大なリストを一度に xmlstarletに渡すように for ループを変更することも 1 つの可能性だと思いますが、これも不必要に面倒で、まだ tempOutput.xml ファイルの使用に行き詰まると思います。

これを行うよりエレガントな方法はありますか?または、一時ファイルは本当に私の最善のアプローチですか?

4

3 に答える 3

1

ターゲット XML をソース ドキュメントとして受け取り、.xml を使用して文字列のリストを含むファイルを読み取る XSLT スタイルシートを作成できますdocument()。(XSLT 2.0 を使用している場合、このドキュメントは XML である必要はありません。) 次に、文字列のリストを解析し、対象の XML ドキュメントで XPath の一致を検索して文字列のいずれかを探します。

<xsl:for-each select="$strings-to-match">
  <xsl:for-each select="/path/to/search[targetElement = current()]">
    <!-- whatever format you need to output these in... -->
    <xsl:value-of select="." />
  </xsl:for-each>
</xsl:for-each>

これにより、一致する要素の文字列値 (連結された子孫テキスト ノード) が出力されます。下流のプログラムのニーズに応じて、その時点で必要なものを出力できます。

于 2013-09-19T16:51:12.910 に答える
0

だけでなく、特にそのファイルを繰り返し分析している場合は、XML データベースを試してみることを検討してください。それらのほとんどは、文字列検索のインデックスをサポートしているため、検索が大幅に高速化されます。XQuery 内でさらに分析を実行できれば、非常に満足できるかもしれません。

検索を実行する XPath (XQuery のサブセット) 式は次のようになります。

/path/to/search[targetElement = ('list', 'of', 'strings', 'to', 'search', 'for')]

一部の実装では XQuery Full Text がサポートされており、テキスト検索も強化されます (特に効率的なインデックスを使用)。

/path/to/search[targetElement contains text { 'list', 'of', 'strings' }]

この単語のリストを読むのは簡単ですが、保存方法と使用している実装によって異なります。

BaseXはそれらのデータベースの 1 つです (そしてオープン ソース ソフトウェア、免責事項: 私はそれらと多少提携しています)。galaxは XQuery Full Text もサポートしています。他の有名な XML データベースと XQuery プロセッサは、eXist DB、Saxon、Sedna、および Marklogic です。それらにはすべて、結果をSTDOUTに出力するコマンドラインツールがあるため、残りの処理チェーンにパイプできます。


子にその文字列が含まれている場合、そのすべてのクエリ (自分のものを含む) はすべての親要素を返します。targetElement/text()代わりに、探している針を含む要素に制限するために使用したい場合があります。

于 2013-09-19T20:17:17.390 に答える
0

私のXidelでは、次のように記述できます。

xidel --extract-exclude=search-terms  StringsToSearchFor.txt -e '$search-terms := tokenize($raw, $line-ending)[. != ""]' MassiveFile.txt -e 'path/to/search[targetElement = $search-terms]'

ただし、大きなファイルの場合は少し遅くなる可能性があります (ストリーミング xml を使用しても以前は高速でしたが、完全な XQuery を実装するときにすべての最適化を破棄しました。これはすでに十分に複雑でした)。

于 2013-09-19T18:21:04.417 に答える