1

個々の文字列 (キー?) に基づいて XML ファイルを分割する最善の方法を (Grep/Sed/Awk で知っていることを使用して) 見つけようとしています。現在のすべての FAQ エントリの SQL ダンプである XML ファイルを持っているので、エントリ ID と、かなり大きな HTML 形式のドキュメントが含まれています。これらのエントリを分割して、簡単にエディターにポップし、フォーマットをクリーンアップして新しい KB / FAQ システムにインポートできるようにしようと考えています。これが私のデータの例です:

 <article id="3">
  <language>en</language>
  <category>Category Name</category>
  <keywords>Keywords, by, comma</keywords>
  <question>Question?</question>
  <answer>HTML Formatting</answer>
  <author>Author</author>
  <data>2010-05-13 09:32</data>
 </article>

XML ファイルには、私が連続して持っているすべての KB 記事がこの形式で含まれています。私はそれを理解するためにbashに慣れていますが、検索に基づいて複数のファイルに分割する方法がわかりません。

乾杯、

粘土

4

3 に答える 3

6

XPathを使用して記事を抽出する

ファイルが有効なXMLである場合は、xgrepXMLStarletなどのユーティリティを使用して、ファイルのXPath式を解析できます。たとえば、xgrepを使用します。

xgrep -x "//article[@id]" /tmp/foo

必要なのはこれだけかもしれません。ただし、記事は分割されません。正規表現を使用するよりも確実にXMLの正しい部分を抽出するだけです。

記事ノードをパイプラインでファイルに分割する

実際に記事を別々のファイルに分割する必要がある場合は、次のようにすることができます。

xgrep -x "//article[@id]" /tmp/foo.rb |
ruby -ne 'BEGIN { counter=0 }
          counter += 1 if /<article/
          if /<article/ ... /<\/article/
            File.open("#{counter}.xml", "a") { |f| f.puts $_ }
          end'

もちろん、Ruby XMLライブラリですべてを行うことができますが、私はこの種の問題をシェルパイプラインとして扱うことを好みます。あなたのマイレージは異なる場合があります。

また、上記のRubyスクリプトでは、記事IDではなく、記事に順番に番号が付けられることに注意してください。XMLに重複するIDがある場合は、これが望ましい場合があります。

XmlSimpleを使用した純粋なRuby

さて、さて...私はこれを放っておくことができませんでした。最初は上記のようにパイプラインで外部シェルユーティリティを使用するのは良い考えのように思えましたが、とにかくPerlまたはRubyを使用する場合は、XmlSimpleライブラリを使用する方がよいでしょう。

以下のRubyスクリプトは、パイプラインバージョンよりも少し長いですが、より多くの制御と柔軟性を提供します。これを出発点として、すべての可能性を検討してください。

#!/usr/bin/env ruby

require 'xmlsimple'

counter = 0
node_name = 'article'
xml = XmlSimple.xml_in '/tmp/foo'

xml[node_name].uniq.each do |node|
  counter = sprintf("%03d", counter.next)
  XmlSimple.xml_out(node,
                    RootName: node_name,
                    OutputFile: "/tmp/#{counter}.xml")
end
于 2012-07-11T22:44:01.803 に答える
2
cat file.xml | \
perl -p -i -e 'open(F, ">", ($1).".xml") if /<article id="(\d+)"/; print F;' 

記事の ID に基づいて xml ファイルを分割します。各記事セクションは、名前に ID 番号を付けて独自のファイルに保存されます。higeファイルでも非常に高速に動作します(この場合sedawk、などのソリューションは非常に遅いです)。

于 2012-07-11T19:38:58.760 に答える
0

awk の簡単なアイデアを次に示します。

記事の開始タグのある行にヒットするたびに、カウンター変数を 1 つ増やします。次に、すべての行に対して、「echo $0 >> file$COUNTER」のようなシステム コールを作成します。これは非常に簡単に実装できるはずです

于 2012-07-11T19:34:35.380 に答える