2016-04-08 3 views
0

に複数のような形式のXMLファイルを結合するために鋸山を使用します。は、どのように私はCSVファイルに複数のような形式のXMLファイルを解析したいCSV

私はnokogiri.org、Googleで検索し、SOのが、私は答えを見つけることができませんでした。

私は、現在のディレクトリに存在したノード/素子構造の点では同じ形式で10個のXMLファイルを、持っています。

単一のXMLファイルにXMLファイルを結合した後、私はadvisoryノードの特定の要素を引き出す必要があります。私は、CSVファイルに出力linktitlelocationos -> language -> name、およびreference -> nameデータをしたいと思います。

私のコードは、単一のXML文書を解析することが可能であり、私はそれを考慮1に入れたいのですが:私は、複数のXMLファイルをサポートしてにそれらを取得するためのコードを変更しようとした

# Parse the XML file into a Nokogiri::XML::Document object 
@doc = Nokogiri::XML(File.open("file.xml")) 

# Gather the 5 specific XML elements out of the 'advisory' top-level node 
data = @doc.search('advisory').map { |adv| 
    [ 
    adv.at('link').content, 
    adv.at('title').content, 
    adv.at('location').content, 
    adv.at('os > language > name').content, 
    adv.at('reference > name').content 
    ] 
} 

# Loop through each array element in the object and write out as CSV row 
CSV.open('output_file.csv', 'wb') do |csv| 
    # Explicitly set headers until you figure out how to get them programatically 
    csv << ['Link', 'Title', 'Location', 'OS Name', 'Reference Name'] 
    data.each do |row| 
    csv << row 
    end 
end 

:多くの鋸山:: XML :: Documentオブジェクトは:

xml_docs = [] 

Dir.glob("*.xml").each do |file| 
    xml = Nokogiri::XML(File.new(file)) 
    xml_docs << Nokogiri::XML::Document.new(xml) 
end 

これが成功したことで、正しいオブジェクトの配列xml_docsを作成しますが、私は1つのオブジェクトにこれらの6つのオブジェクトを変換する方法を知りません。

これはサンプルXMLです。すべてのXMLファイルは、同じノード/素子構造を使用します。

<advisories> 
    <title> Not relevant </title> 
    <customer> N/A </customer> 
    <advisory id="12345"> 
    <link> https://www.google.com </link> 
    <release_date>2016-04-07</release_date> 
    <title> The Short Description Would Go Here </title> 
    <location> Location Name Here </location> 
    <os> 
     <product> 
     <id>98765</id> 
     <name>Product Name</name> 
     </product> 
     <language> 
     <id>123</id> 
     <name>en</name> 
     </language> 
    </os> 
    <reference> 
     <id>00029</id> 
     <name>Full</name> 
     <area>Not Defined</area> 
    </reference> 
    </advisory> 
    <advisory id="98765"> 
    <link> https://www.msn.com </link> 
    <release_date>2016-04-08</release_date> 
    <title> The Short Description Would Go Here </title> 
    <location> Location Name Here </location> 
    <os> 
     <product> 
     <id>12654</id> 
     <name>Product Name</name> 
     </product> 
     <language> 
     <id>126</id> 
     <name>fr</name> 
     </language> 
    </os> 
    <reference> 
     <id>00052</id> 
     <name>Partial</name> 
     <area>Defined</area> 
    </reference> 
    </advisory> 
</advisories> 

コードは鋸山:: XML ::ドキュメントを活用するが、鋸山:: XML :: Builderは、このためのより良い動作する場合、私が調整して喜ん以上ですそれに応じて私のコード。

+0

ようこそスタックオーバーフロー。あなたがここに回っていいのは残念ですが、残念ながらあなたはSOのポイントを逃しました。私たちはあなたの*コードの間違いや問題を修正するのを手伝っています。一番下のリンクを含む「[ask]」と「[mcve]」をお読みください。私たちはあなたの努力の証拠を見たいと思います:何を試しましたか?なぜそれは動作しませんでしたか?試していないと、どこで検索しましたか、なぜその場所に必要な情報がないのですか?私たちにXMLを渡し、あなたが何をしたいのかを私たちに伝えれば、あなたが書いたときに遭遇した問題を解決する方法を私たちに尋ねるのではなく、問題を解決するコードを書くことができます。 –

+0

私はまもなく私が試みたもので私の質問を変更します。私はあまりにも長い間質問をしたくなかったが、私ができることがわかるだろう。メモをありがとう! –

+0

ようこそ。 SOは、プログラミング問題、問題と解決策の料理の種類のオンライン参照であるという野心的な目標を持っています。彼らは検索エンジンのトップ結果からもわかるように、それをうまくやっていますが、質問と回答の質が高いままでいることを確認するという継続的な仕事です。長い質問は高品質を意味するものではないので、書くことや思考や努力をするのは難しいですが、最終結果は素晴らしいです。あなたは答えを得て、将来は他の人もやってください。みんなの問題を解決する戦いへようこそ! :-) –

答えて

0

は、私はこのように、1つのXMLファイルを解析するの、最初の部分を処理したい:

require 'nokogiri' 

doc = Nokogiri::XML(<<EOT) 
<advisories> 
    <advisory id="12345"> 
    <link> https://www.google.com </link> 
    <title> The Short Description Would Go Here </title> 
    <location> Location Name Here </location> 
    <os> 
     <language> 
     <name>en</name> 
     </language> 
    </os> 
    <reference> 
     <name>Full</name> 
    </reference> 
    </advisory> 
    <advisory id="98765"> 
    <link> https://www.msn.com </link> 
    <release_date>2016-04-08</release_date> 
    <title> The Short Description Would Go Here </title> 
    <location> Location Name Here </location> 
    <os> 
     <language> 
     <name>fr</name> 
     </language> 
    </os> 
    <reference> 
     <name>Partial</name> 
    </reference> 
    </advisory> 
</advisories> 
EOT 

注:これは、彼らが質問に重要ではありませんでしたので、削除ノードを持っています。気を散らしているように頼むときは、毛羽立ちを取り除いてください。

doc.search('advisory').map{ |advisory| 
    link = advisory.at('link').text 
    title = advisory.at('title').text 
    location = advisory.at('location').text 
    os_language_name = advisory.at('os > language > name').text 
    reference_name = advisory.at('reference > name').text 

    { 
    link: link, 
    title: title, 
    location: location, 
    os_language_name: os_language_name, 
    reference_name: reference_name 
    } 
} 

DRY'dことができるが何をするかの一例として書かれていた:これは、コードの中核された状態で

# => [ 
     {:link=>" https://www.google.com ", :title=>" The Short Description Would Go Here ", :location=>" Location Name Here ", :os_language_name=>"en", :reference_name=>"Full"}, 
     {:link=>" https://www.msn.com ", :title=>" The Short Description Would Go Here ", :location=>" Location Name Here ", :os_language_name=>"fr", :reference_name=>"Partial"} 
    ] 

あなたが作業は、出力CSVにあなたのループの修正版にそれを適合し、読むことを持ったら:簡単にCSVを介して出力だろうハッシュの配列の結果は、ことを実行している

XMLファイル。これはテストされていませんが、右に見えるについて:あなたは'wb'のファイルモードを使用していた

CSV.open('output_file.csv', 'w', 
    headers: ['Link', 'Title', 'Location', 'OS Name', 'Reference Name'], 
    write_headers: true 
) do |csv| 
    Dir.glob("*.xml").each do |file| 
    xml = Nokogiri::XML(File.read(file)) 
    # parse a file and get the array of hashes 
    end 

    # pass the array of hashes to CSV for output 
end 

注意。 CSVはテキスト形式になっているため、ほとんどの場合、bとCSVが必要です。 の場合は、バイナリデータに遭遇し、'b'も使用しますが、それはドラゴンを含むパスを導く可能性があります。

はまた、これはreadを使用していることに注意してください。readはスケーラブルではありません。つまり、ファイルの大きさには気を付けません。実際に適合するかどうかにかかわらず、ファイルをメモリに読み込もうとします。それを避ける理由はたくさんありますが、プログラムを膝にかけるのが最善です。 XMLファイルが使用可能な空きメモリを超える場合は、NokogiriがサポートするSAXパーサーを使用して書き直したいと思うでしょう。それを行う方法は別の質問です。


実際ハッシュの配列の配列でした。

foo = [] # => [] 
foo += [{}] # => [{}] 

foo = [] # => [] 
foo << [{}] # => [[{}]] 
foo.flatten # => [{}] 

あなたはおそらくこれをやってみたかった:私は、私はそこに終わったが、私は簡単にこの上

瞑想array.flatten使用することができたかどうかはわかりません

いつでも私はflattenを使用しなければなりません。私はそれが何かの配列の配列でなくても配列を作成できるかどうかを見ています。時にはそれらが非常に便利なので、実際には悪いわけではありませんが、何かが間違っていて、flattenが安価な方法であることがわかったので、ハッシュの配列が必要でした。問題を見つけて修正し、より高速で効率的なコードにする方がよいでしょう。 (また、無駄な努力や時期尚早の最適化だと言う人もいますが、効率的なコードを書くことは非常に優れた特性と目標です)。

+0

"ドラゴンを含む道" ...笑。私はすぐにこれを試してみます。詳細な説明をいただきありがとうございます! –

+0

ありがとう、これは良い作品です。私は 'xml.search'のそれぞれに変数を割り当て、それらを新しい配列に書き出しました。いったん私はそれに6つのオブジェクトを持つ配列を持っていた、それは実際にハッシュの配列の配列でした。私はそこでどのように終わったのか分かりませんが、 'array.flatten'を使い、ハッシュ値をCSVに割り当てるハッシュを繰り返し処理できました。完了した回答を投稿する必要がありますか? Btw、私はあなたの名前を何度も見たことがあります - 私はあなたに感謝の機会を得てうれしいです。あなたは私と他の多くの人々を助けてくれました - ありがとう! –

+0

ハッシュの配列の配列を持っていたなら、おそらく正しく連結していないでしょう。私は説明を追加します。修正が見つからない限り、完了した回答を追加しないでください。あなたのコードを投稿しても、他人にはあまり役立つものではありません。私の目標は返すことです。私はこのことをずっとやっており、良い指導者がたくさんいました。私は教え、指導、そしてそれを前払いするのが楽しいです。 –

関連する問題