2016-10-13 20 views
0

この文書はファイアウォールの設定からの出力です。私はファイアウォールルールのハッシュを構築しようとしています。私は私が必要とするものは何でもCSV /コンソール/に後で出力このデータになります。RubyとNokogiriを使用してXMLを解析する方法

<table index="44" title=" from PUBLIC to DMZ administrative service rules on Firewall01" ref="FILTER.BLACKLIST"> 
    <headings> 
    <heading>Rule</heading> 
    <heading>Action</heading> 
    <heading>Source</heading> 
    <heading>Destination</heading> 
    <heading>Service</heading> 
    <heading>Log</heading> 
    </headings> 
    <tablebody> 
    <tablerow> 
     <tablecell><item>test_inbound</item></tablecell> 
     <tablecell><item>Allow</item></tablecell> 
     <tablecell><item gotoref="CONFIG.3.452">[Group] test_b2_group</item></tablecell> 
     <tablecell><item>[Host] Any</item></tablecell> 
     <tablecell><item>[Host] Any</item></tablecell> 
     <tablecell><item>Yes</item></tablecell> 
    </tablerow> 
    <tablerow> 
     <tablecell><item>host02_inbound</item></tablecell> 
     <tablecell><item>Allow</item></tablecell> 
     <tablecell><item gotoref="CONFIG.3.447">[Group] host02_group</item></tablecell> 
     <tablecell><item>[Host] Any</item></tablecell> 
     <tablecell><item>[Host] Any</item></tablecell> 
     <tablecell><item>Yes</item></tablecell> 
    </tablerow> 
    <tablerow> 
     <tablecell><item>randomhost</item></tablecell> 
     <tablecell><item>Allow</item></tablecell> 
     **<tablecell><item gotoref="CONFIG.3.383">[Group] Host_group_2</item><item gotoref="CONFIG.3.382">[Group] another_server</item></tablecell>** 
     <tablecell><item gotoref="CONFIG.3.510">[Group] crazy_application</item><item gotoref="CONFIG.3.511">[Group] internal_app</item><item gotoref="CONFIG.3.525">[Group] online_application</item></tablecell> 
     <tablecell><item gotoref="CONFIG.3.783">[Group] junos-https</item></tablecell> 
     <tablecell><item>No</item></tablecell> 
    </tablerow> 
    </tablebody> 
</table> 

我々は、列のヘッダーおよび3つのファイアウォールルールを持っています。それらの分野で唯一の値があるので、

#!/usr/bin/env ruby 

require 'nokogiri' 
require 'csv' 

fwpol = File.open(ARGV[0]) { |f| Nokogiri::XML(f) } 
rule_array = [] 

fwpol.xpath('./table/tablebody/tablerow').each do |item| 
    rules = {} 

    rules[:name] = item.xpath('./tablecell/item')[0].text 
    rules[:action] = item.xpath('./tablecell/item')[1].text 
    rules[:source] = item.xpath('./tablecell/item')[2].text 
    rule_array << rules 
end 

puts rule_array 

最初の2つのハッシュエントリ、完全に:name:action作品:

は、ここに私のコードです。

コードを実行すると、複数の値がある場所には印刷されません。太字のXML行は、私が何を参照しているかを示しています。私は何とか値を繰り返し処理する必要がありますが、これまでのところ私の試みは無駄でした。

+0

コードに問題がある場合は、問題を示すために必要な最小限のコードと最小限の入力データと、それに何が期待できるかを示す必要があります。 "[mcve]" –

答えて

2

以下の方法で、複数の要素テキストを配列として取得できます。

require 'nokogiri' 
require 'csv' 

fwpol = File.open(ARGV[0]) { |f| Nokogiri::XML(f) } 
rule_array = [] 

fwpol.xpath('./table/tablebody/tablerow').each do |item| 
    rules = {} 

    rules[:name] = item.xpath('./tablecell[1]/item').text 
    rules[:action] = item.xpath('./tablecell[2]/item').text 
    rules[:source] = item.xpath('./tablecell[3]/item').map(&:text) 
    rule_array << rules 
end 

puts rule_array 

出力はこちらです。

{:name=>"test_inbound", :action=>"Allow", :source=>["[Group] test_b2_group"]} 
{:name=>"host02_inbound", :action=>"Allow", :source=>["[Group] host02_group"]} 
{:name=>"randomhost", :action=>"Allow", :source=>["[Group] Host_group_2", "[Group] another_server"]} 
+0

こんにちは、ありがとうございました。私が設定した例では動作しないようです。私はまだ1つのエントリ/要素を出力に持っています。 – hatlord

+0

回答のプログラムの結果を更新しました。ルビーのバージョンは? – ta1k0tme

+0

それはうまくいく、謝罪します。私はもっ​​と慎重に読むことを学ぶ必要があります!ヘルプ/回答ありがとう! – hatlord

1

私はこのような何かしたい:

require 'nokogiri' 

doc = Nokogiri::XML(<<EOT) 
<table index="44" title=" from PUBLIC to DMZ administrative service rules on Firewall01" ref="FILTER.BLACKLIST"> 
    <tablebody> 
    <tablerow> 
     <tablecell><item>test_inbound</item></tablecell> 
     <tablecell><item>Allow</item></tablecell> 
     <tablecell><item gotoref="CONFIG.3.452">[Group] test_b2_group</item></tablecell> 
     <tablecell><item>[Host] Any</item></tablecell> 
     <tablecell><item>[Host] Any</item></tablecell> 
     <tablecell><item>Yes</item></tablecell> 
    </tablerow> 
    <tablerow> 
     <tablecell><item>randomhost</item></tablecell> 
     <tablecell><item>Allow</item></tablecell> 
     <tablecell><item gotoref="CONFIG.3.383">[Group] Host_group_2</item><item gotoref="CONFIG.3.382">[Group] another_server</item></tablecell> 
     <tablecell><item gotoref="CONFIG.3.510">[Group] crazy_application</item><item gotoref="CONFIG.3.511">[Group] internal_app</item><item gotoref="CONFIG.3.525">[Group] online_application</item></tablecell> 
     <tablecell><item gotoref="CONFIG.3.783">[Group] junos-https</item></tablecell> 
     <tablecell><item>No</item></tablecell> 
    </tablerow> 
    </tablebody> 
</table> 
EOT 

rule_array = doc.search('tablerow').map{ |row| 
    name, action, source = row.search('tablecell')[0, 3].map{ |tc| tc.search('item').map(&:text) } 

    { 
    name: name, 
    action: action, 
    source: source 
    } 
} 
実行は最後の2つのエントリ itemているハッシュの配列、含む rule_arrayを返します、

require 'ap' 
ap rule_array 

# >> [ 
# >> [0] { 
# >>  :name => [ 
# >>  [0] "test_inbound" 
# >>  ], 
# >>  :action => [ 
# >>  [0] "Allow" 
# >>  ], 
# >>  :source => [ 
# >>  [0] "[Group] test_b2_group" 
# >>  ] 
# >> }, 
# >> [1] { 
# >>  :name => [ 
# >>  [0] "randomhost" 
# >>  ], 
# >>  :action => [ 
# >>  [0] "Allow" 
# >>  ], 
# >>  :source => [ 
# >>  [0] "[Group] Host_group_2", 
# >>  [1] "[Group] another_server" 
# >>  ] 
# >> } 
# >> ] 

:しないでください:

fwpol = File.open(ARGV[0]) { |f| Nokogiri::XML(f) } 

それは使用する方が簡単です:

fwpol = Nokogiri::XML(File.read(ARGV[0])) 

の代わりにやって:その小グループを反復その後、[0, 3]

item.xpath('./tablecell/item')[0].text 
item.xpath('./tablecell/item')[1].text 
item.xpath('./tablecell/item')[2].text 

を単に、あなたが欲しいものをスライスし、一度テーブルセルタグを見つけます。それは速く、コードの繰り返しを減らします。

How to avoid joining all text from Nodes when scraping」も参照してください。

+0

ありがとう!とてもうまく動作します!これをスキンする方法はたくさんあると思います! – hatlord

関連する問題