2017-02-05 1 views
0

Der ursprüngliche Beitrag war ein Chaos, hoffe, dass diese Bearbeitung klarer ist !.Wie generiert man XML mit Builder, um die Strukturen innerhalb von XML zu durchlaufen

Ich bin auf der Suche nach XML aus Hashes, verschachtelte innerhalb Arrays. Ich habe versucht, Nokogiri Builder zu benutzen und kann es nicht richtig hinkriegen. Dank einiger Hilfe von Tin Man bin ich jetzt ein wenig näher dran, aber mein Beispiel war bei weitem nicht klar genug, um entschlüsselt zu werden. Ich habe auch einige wichtige Informationen verpasst.

Dies ist die XML, die wir generieren müssen:

<?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> 

Bisher habe ich in der Nähe mit dem folgenden Code bekommen, aber die verschachtelten Schleifen Sinn ich mit zu vielen Wiederholungen/Wiederholung jedem am Ende ' Ausgabe ", drei um genau zu sein.

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 

Wie schleife ich innerhalb der Schleife und gebe nur die korrekte Anzahl von 'Problemen' zurück? Es sollten zwei sein, jede mit drei Regeln, die jeweils aus einem der verschachtelten Arrays von Hashes gemäß dem XML-Beispiel stammen.

Ich hoffe, die Frage ist jetzt klarer und Entschuldigung für das Durcheinander im Original.

Update: So konnte ich zusammen im Grunde hacken, was ich wollte:

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 

dort zwar zu erhalten, ich hatte das verlassen Zugriff auf: id-Wert aus dem Hash, da ich keinen Zugriff tun diesen Hash, bis ich das outer.each do |rule| Bit starte. Als temporärer "bodge" weise ich der issue_id einfach einen Wert zu und inkrementiere ihn mit jeder Schleife. Gibt es eine Möglichkeit, den: ID-Wert zu erhalten, bevor ich über die Hashes iteriere? Oder ist meine Logik hier fehlerhaft?

bearbeiten 33: Es scheint die Zuordnung der ID-Wert, wie unten Werke:

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

Bitte lesen Sie "[mcve]", insbesondere den Link am Ende der Seite. Vereinfachen Sie Ihren Code und zeigen Sie die minimal benötigte Ausgabe an, die Sie benötigen. Dies hilft Ihnen beim Debuggen und Ausprobieren, und es wird Ihre Frage für uns verständlicher machen. –

Antwort

2

Regel: Pflegen Sie Ihre Vertiefung richtig. Es gibt viele gute Code-Editoren, die Ihnen helfen, entweder indem Sie während des Schreibens ein- und ausrücken, oder indem Sie einen Formatierer ausführen lassen. Dadurch können Sie Probleme in Schleifen und Blöcken leichter erkennen.

Ihr gewünschtes Codebeispiel ist:

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 

Nach lassen vim es reindent ich habe:

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 

, die sofort zeigt es Probleme geben, weil XML Code generiert, wie die XML-Ausgabe zu sein , muss korrekt verschachteln.

die XML-Root-Einstellung und die end im Zusammenhang mit rule_array so sie nisten richtig ergeben:

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 

Aber das ist nicht sehr effizient.Mit ein wenig Zwicken würde ich verwenden:

#!/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 

die, wenn sie ausgeführt werden, Ausgänge:

# >> <?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> 

, die irgendwie vernünftig aussieht, obwohl es nicht sehr effizient XML ist, aber ohne die fehlt, noch oh- so wichtige gewünschte Ausgabe, es muss ausreichen.

Beachten Sie, dass Nokogiri die Ruby-Symboltasten in den Hashes verwendet, um das visuelle Rauschen in den Hash-Definitionen zu reduzieren.

+0

Vielen Dank für den Kommentar Tin Man. Die Hash-Definitionen waren rein, so dass ich einige Eingabedaten für das Beispiel veröffentlichen konnte, aber ich bin froh, eine bessere Definition zu kennen! Ich werde das erwartete XML-Format veröffentlichen, wenn ich es nicht mit Ihrem Beispiel herausfinden kann. – hatlord

Verwandte Themen