2017-02-05 5 views
0

원래 게시물이 엉망이었습니다.이 편집이 더 명확 해지기를 바랍니다.빌더를 사용하여 XML을 생성하여 XML 내부의 구조를 반복하는 방법

배열 안에 중첩 된 해시에서 XML을 생성하려고합니다. 나는 Nokogiri 건축업자를 사용하려고 시도했으나 제대로 할 수는 없습니다. Tin Man의 도움 덕분에 조금 더 가까워졌습니다. 그러나 제 예제는 해독 될만큼 명확하지 않았습니다. 나는 또한 중요한 정보를 놓쳤다.

내가 생성하는 데 필요한 XML입니다 : 지금까지 내가 다음 코드와의 긴밀한 입수했습니다

<?xml version="1.0" encoding="UTF-8"?> 
    <Report Tool="FirewallParserv1"> 
     <Firewalls> 
     <Firewall> 
      <issues> 
      <issue id="1" Category="2"> 
       <Data mode="table"> 
       <Row> 
        <column>ACL</columnumn> 
        <column>Rule</column> 
        <column>Source</column> 
        <column>Dest</column> 
        <column>Service</column> 
        <column>Log</column> 
       </Row> 
       <Row> 
        <column>inside_access_in</column> 
        <column>1</column> 
        <column>10.10.10.1</column> 
        <column>192.168.1.2</column> 
        <column>SMTP</column> 
        <column>YES</column> 
       </Row> 
       <Row> 
        <column>inside_access_in</column> 
        <column>2</column> 
        <column>172.16.2.1</column> 
        <column>192.168.100.10</column> 
        <column>HTTP</column> 
        <column>NO</column> 
       </Row> 
       <Row> 
        <column>inside_access_in</column> 
        <column>3</column> 
        <column>172.16.2.200</column> 
        <column>10.10.60.1</column> 
        <column>TELNET</column> 
        <column>NO</column> 
       </Row> 
       </Data> 
      </issue> 
      </issues> 
     </Firewall> 
     </Firewalls> 
    <Firewalls> 
     <Firewall> 
      <issues> 
      <issue id="2" Category="2"> 
       <Data mode="table"> 
       <Row> 
        <column>ACL</columnumn> 
        <column>Rule</column> 
        <column>Source</column> 
        <column>Dest</column> 
        <column>Service</column> 
        <column>Log</column> 
       </Row> 
       <Row> 
        <column>outside_access_in</column> 
        <column>8</column> 
        <column>195.92.195.92</column> 
        <column>192.168.1.2</column> 
        <column>SYSLOG</column> 
        <column>YES</column> 
       </Row> 
       <Row> 
        <column>outside_access_in</column> 
        <column>9</column> 
        <column>8.8.8.8</column> 
        <column>192.168.100.10</column> 
        <column>SSH</column> 
        <column>NO</column> 
       </Row> 
       <Row> 
        <column>outside_access_in</column> 
        <column>10</column> 
        <column>172.16.3.200</column> 
        <column>10.10.90.1</column> 
        <column>PROXY</column> 
        <column>NO</column> 
       </Row> 
       </Data> 
      </issue> 
      </issues> 
     </Firewall> 
     </Firewalls> 
    </Report> 

을하지만, 중첩 루프 내가 너무 많은 반복 각의/반복 '을 결국 의미있다 문제 ', 세 가지로 정확하게

rule_array1 = [ 
    {:id => '1', :aclname => 'inside_access_in', :Rule => '1', :Source => '10.10.10.1', :Destination => '192.168.1.2', :port => 'SMTP', :Log => 'YES'}, 
    {:id => '1', :aclname => 'inside_access_in', :Rule => '2', :Source => '172.16.2.1', :Destination => '192.168.100.10', :port => 'HTTP', :Log => 'NO'}, 
    {:id => '1', :aclname => 'inside_access_in', :Rule => '3', :Source => '172.16.2.200', :Destination => '10.10.60.1',  :port => 'TELNET', :Log => 'NO'} 
] 

rule_array2 = [ 
    {:id => '2', :aclname => 'outside_access_in', :Rule => '8', :Source => '195.92.195.92', :Destination => '192.168.1.2', :port => 'SYSLOG', :Log => 'YES'}, 
    {:id => '2', :aclname => 'outside_access_in', :Rule => '9', :Source => '8.8.8.8', :Destination => '192.168.100.10', :port => 'SSH', :Log => 'NO'}, 
    {:id => '2', :aclname => 'outside_access_in', :Rule => '10', :Source => '172.16.3.200', :Destination => '10.10.90.1',  :port => 'PROXY', :Log => 'NO'} 
] 

array_of_arrays = rule_array1, rule_array2 

builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml| 
    xml.Report('Tool' => 'FirewallParserv1') { 
    array_of_arrays.each do |outer| 
     outer.each do |rule| 
      xml.Firewalls { 
      xml.Firewall { 
       xml.issues { 
       xml.issue('id' => rule[:id], 'Category' => '2') { 
        xml.Data('mode' => "table") { 
        xml.Row { 
         xml.column("ACL") 
         xml.column("Rule") 
         xml.column("Source") 
         xml.column("Dest") 
         xml.column("Service") 
         xml.column("Log") 
        } 
        outer.each do |rule| 
         xml.Row { 
         xml.column(rule[:aclname]) 
         xml.column(rule[:Rule]) 
         xml.column(rule[:Source]) 
         xml.column(rule[:Destination]) 
         xml.column(rule[:port]) 
         xml.column(rule[:Log]) 
         } 
        end 
        } 
       } 
       } 
      }  
      } 
     end  
    end 
    } 
end 

puts builder.to_xml 

루프 내에서 루프를 만들고 올바른 '문제'수만 반환합니까? 각각 XML 규칙에 따라 중첩 된 해시 배열 중 하나에서 가져온 규칙이 세 개가있는 두 개가 있어야합니다.

나는이 질문이 현재 명확 해 졌음을 알고 원본의 혼란에 사과한다.

업데이트 : 내가 접근하지 않는 한, 해시에서 id 값 : 나는 접근 포기했다,

issue_id = 1 
builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml| 
    xml.Report('Tool' => 'FirewallParserv1') { 
     xml.Firewalls { 
     xml.Firewall { 
      array_of_arrays.each do |outer| 
      xml.issues { 
       xml.issue('id' => issue_id, 'Category' => '2') { 
       xml.Data('mode' => "table") { 
        xml.Row { 
        xml.column("ACL") 
        xml.column("Rule") 
        xml.column("Source") 
        xml.column("Dest") 
        xml.column("Service") 
        xml.column("Log") 
        } 
        outer.each do |rule| 
        xml.Row {  
         xml.column(rule[:aclname]) 
         xml.column(rule[:Rule]) 
         xml.column(rule[:Source]) 
         xml.column(rule[:Destination]) 
         xml.column(rule[:port]) 
         xml.column(rule[:Log]) 
        } 
        end 
       } 
       } 
      } 
      issue_id +=1 
      end  
     } 
     } 
    } 
end 


puts builder.to_xml 

그래도 거기에 도착하려면, 그래서 내가 원하는 함께 기본적으로 어떤 해킹 관리 outer.each do |rule| 비트가 시작될 때까지 해당 해시. 임시 보금 자리로 나는 단지 issue_id에 값을 할당하고 각 루프마다 값을 증가시킵니다. 해시를 반복하기 전에 : id 값을 얻는 방법이 있습니까? 아니면 내 논리가 결함이있는거야?

편집 33 : 그것은 작품 아래와 같이 ID 값을 할당하는 것 같다 :

xml.issue('id' => outer[0][:id], 'Category' => '2') { 
+0

"[mcve]", 특히 페이지 하단의 링크를 읽으십시오. 코드를 단순화하고 필요한 최소 출력을 보여줍니다. 그렇게하면 디버깅하고 시도하는 데 도움이되며 문제가 더 쉽게 이해 될 수 있습니다. –

답변

2

규칙 하나를 제대로 들여 쓰기를 유지한다. 글을 쓸 때 들여 쓰기/들여 쓰기 또는 포맷터를 실행함으로써 많은 훌륭한 코드 편집기가 도움이 될 것입니다. 이렇게하면 루프 및 블록의 문제를보다 쉽게 ​​볼 수 있습니다.

원하는 코드 예제는 다음과 같습니다시키는 정력이 그것을 reindent

builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml| 
    rule_array.each do |rule| 
    xml.Report('Tool' => 'FirewallParserv1') { 
    xml.Firewalls { 
     xml.Firewall { 
     xml.issues { 
      xml.issue('id' => rule[:id], 'Category' => '2') { 
      end 
      xml.Data('mode' => "table") { 
       xml.Row { 
       xml.columnumn("ACL") 
       xml.column("Rule") 
       xml.column("Source") 
       xml.column("Dest") 
       xml.column("Service") 
       xml.column("Log") 
       } 
       rule_array.each do |rule| 
       xml.Row { 
       xml.column(rule[:aclname]) 
       xml.column(rule[:Rule]) 
       xml.column(rule[:Source]) 
       xml.column(rule[:Destination]) 
       xml.column(rule[:port]) 
       xml.column(rule[:Log]) 
       } 
      end 
      } 
      } 
     } 
     } 
    } 
    } 
end 

후 내가 가진 : 문제가 즉시 표시

builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml| 
    rule_array.each do |rule| 
    xml.Report('Tool' => 'FirewallParserv1') { 
     xml.Firewalls { 
     xml.Firewall { 
      xml.issues { 
      xml.issue('id' => rule[:id], 'Category' => '2') { 
    end 
    xml.Data('mode' => "table") { 
    xml.Row { 
     xml.columnumn("ACL") 
     xml.column("Rule") 
     xml.column("Source") 
     xml.column("Dest") 
     xml.column("Service") 
     xml.column("Log") 
    } 
    rule_array.each do |rule| 
     xml.Row { 
     xml.column(rule[:aclname]) 
     xml.column(rule[:Rule]) 
     xml.column(rule[:Source]) 
     xml.column(rule[:Destination]) 
     xml.column(rule[:port]) 
     xml.column(rule[:Log]) 
     } 
    end 
    } 
      } 
      } 
     } 
     } 
    } 
end 
puts builder.to_xml 

의 XML과 같은 XML 생성 코드를 출력 할 수 있기 때문에 올바르게 중첩해야합니다.

는 XML 루트를 조정

rule_array와 관련된 end는 그래서 그들은 둥지 제대로 결과 :

builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml| 
    xml.Report('Tool' => 'FirewallParserv1') { 
    rule_array.each do |rule| 
     xml.Firewalls { 
     xml.Firewall { 
      xml.issues { 
      xml.issue('id' => rule[:id], 'Category' => '2') { 
       xml.Data('mode' => "table") { 
       xml.Row { 
        xml.columnumn("ACL") 
        xml.column("Rule") 
        xml.column("Source") 
        xml.column("Dest") 
        xml.column("Service") 
        xml.column("Log") 
       } 
       rule_array.each do |rule| 
        xml.Row { 
        xml.column(rule[:aclname]) 
        xml.column(rule[:Rule]) 
        xml.column(rule[:Source]) 
        xml.column(rule[:Destination]) 
        xml.column(rule[:port]) 
        xml.column(rule[:Log]) 
        } 
       end 
       } 
      } 
      } 
     } 
     } 
    end 
    } 
end 

그러나 그것은 매우 효율적이 아니다.약간의 조정으로 내가 사용하는 것 :

#!/usr/bin/env ruby 

require 'nokogiri' 

HEADERS = %w(ACL Rule Source Dest Service Log) 
FIELDS = %i(aclname Rule Source Destination port Log) 

rule_array = [ 
    {:id => '1', :aclname => 'inside_access_in', :Rule => '1', :Source => '10.10.10.1', :Destination => '192.168.1.2', :port => 'SMTP', :Log => 'YES'}, 
    {:id => '2', :aclname => 'inside_access_in', :Rule => '2', :Source => '172.16.2.1', :Destination => '192.168.100.10', :port => 'HTTP', :Log => 'NO'}, 
    {:id => '3', :aclname => 'inside_access_in', :Rule => '3', :Source => '172.16.2.200', :Destination => '10.10.60.1',  :port => 'TELNET', :Log => 'NO'} 
] 

builder = Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do |xml| 
    xml.Report('Tool' => 'FirewallParserv1') { 
    rule_array.each do |rule| 
     xml.Firewalls { 
     xml.Firewall { 
      xml.issues { 
      xml.issue('id' => rule[:id], 'Category' => '2') { 
       xml.Data('mode' => "table") { 
       xml.Row { 
        HEADERS.each do |h| 
        xml.column(h) 
        end 
       } 
       xml.Row { 
        rule.values_at(*FIELDS).each do |f| 
        xml.column(f) 
        end 
       } 
       } 
      } 
      } 
     } 
     } 
    end 
    } 
end 
puts builder.to_xml 

어떤, 실행, 출력 :

# >> <?xml version="1.0" encoding="UTF-8"?> 
# >> <Report Tool="FirewallParserv1"> 
# >> <Firewalls> 
# >>  <Firewall> 
# >>  <issues> 
# >>   <issue id="1" Category="2"> 
# >>   <Data mode="table"> 
# >>    <Row> 
# >>    <column>ACL</column> 
# >>    <column>Rule</column> 
# >>    <column>Source</column> 
# >>    <column>Dest</column> 
# >>    <column>Service</column> 
# >>    <column>Log</column> 
# >>    </Row> 
# >>    <Row> 
# >>    <column>inside_access_in</column> 
# >>    <column>1</column> 
# >>    <column>10.10.10.1</column> 
# >>    <column>192.168.1.2</column> 
# >>    <column>SMTP</column> 
# >>    <column>YES</column> 
# >>    </Row> 
# >>   </Data> 
# >>   </issue> 
# >>  </issues> 
# >>  </Firewall> 
# >> </Firewalls> 
# >> <Firewalls> 
# >>  <Firewall> 
# >>  <issues> 
# >>   <issue id="2" Category="2"> 
# >>   <Data mode="table"> 
# >>    <Row> 
# >>    <column>ACL</column> 
# >>    <column>Rule</column> 
# >>    <column>Source</column> 
# >>    <column>Dest</column> 
# >>    <column>Service</column> 
# >>    <column>Log</column> 
# >>    </Row> 
# >>    <Row> 
# >>    <column>inside_access_in</column> 
# >>    <column>2</column> 
# >>    <column>172.16.2.1</column> 
# >>    <column>192.168.100.10</column> 
# >>    <column>HTTP</column> 
# >>    <column>NO</column> 
# >>    </Row> 
# >>   </Data> 
# >>   </issue> 
# >>  </issues> 
# >>  </Firewall> 
# >> </Firewalls> 
# >> <Firewalls> 
# >>  <Firewall> 
# >>  <issues> 
# >>   <issue id="3" Category="2"> 
# >>   <Data mode="table"> 
# >>    <Row> 
# >>    <column>ACL</column> 
# >>    <column>Rule</column> 
# >>    <column>Source</column> 
# >>    <column>Dest</column> 
# >>    <column>Service</column> 
# >>    <column>Log</column> 
# >>    </Row> 
# >>    <Row> 
# >>    <column>inside_access_in</column> 
# >>    <column>3</column> 
# >>    <column>172.16.2.200</column> 
# >>    <column>10.10.60.1</column> 
# >>    <column>TELNET</column> 
# >>    <column>NO</column> 
# >>    </Row> 
# >>   </Data> 
# >>   </issue> 
# >>  </issues> 
# >>  </Firewall> 
# >> </Firewalls> 
# >> </Report> 
그것은 매우 효율적 XML이 아니다하지만, 좀 재치있는 모습

,하지만하지 않고 누락, 아직 OH- 그렇게 중요한 출력을 얻으려면 충분해야합니다.

Nokogiri는 해시 정의의 시각적 노이즈를 줄이기 위해 해시에서 Ruby 심볼 키를 가져옵니다.

+0

Tin Man 주석에게 많은 감사를드립니다. 해시 정의는 전적으로 예제에 대한 입력 데이터를 게시 할 수 있었지만이를 정의하는 더 좋은 방법을 알게되어 기쁩니다! 귀하의 예를 들어 설명하지 못하면 예상되는 XML 형식을 게시 할 것입니다. – hatlord