2017-12-20 1 views
1

Ich bin derzeit versucht, einen Hash aus einem XML-documen zu schaffen, mit Hilfe des Ochsen gemeinen Ruby-Hash erstellen mit dem ‚ox‘ gem

Eingang xml:

<?xml version="1.0"?> 
<expense> 
    <payee>starbucks</payee> 
    <amount>5.75</amount> 
    <date>2017-06-10</date> 
</expense> 

mit folgendem ruby ​​/ ox Code:

doc = Ox.parse(xml) 
plist = doc.root.nodes 

bekomme ich folgende Ausgabe:

=> [#<Ox::Element:0x00007f80d985a668 @value="payee", @attributes={}, @nodes=["starbucks"]>, #<Ox::Element:0x00007f80d9839198 @value="amount", @attributes={}, @nodes=["5.75"]>, #<Ox::Element:0x00007f80d9028788 @value="date", @attributes={}, @nodes=["2017-06-10"]>] 

Der Ausgang ich will, ist ein Hash im Format:

{'payee' => 'Starbucks', 
'amount' => 5.75, 
'date' => '2017-06-10'} 

in meiner SQLLite Datenbank zu speichern.
Wie kann ich das Objekt-Array in einen Hash wie oben transformieren.
Jede Hilfe wird sehr geschätzt.

Antwort

1

Die docs empfehlen Ihnen die folgende verwenden:

require 'ox' 

xml = %{ 
<top name="sample"> 
    <middle name="second"> 
    <bottom name="third">Rock bottom</bottom> 
    </middle> 
</top> 
} 

puts Ox.load(xml, mode: :hash) 
puts Ox.load(xml, mode: :hash_no_attrs) 

#{:top=>[{:name=>"sample"}, {:middle=>[{:name=>"second"}, {:bottom=>[{:name=>"third"}, "Rock bottom"]}]}]} 
#{:top=>{:middle=>{:bottom=>"Rock bottom"}}} 

Ich bin nicht sicher, das ist genau das, was Sie für obwohl suchen.

Andernfalls hängt es wirklich von den Methoden ab, die auf den Instanzen Ox::Element im Array verfügbar sind.

Von the docs, es sieht so aus, als gäbe es hier zwei handliche Methoden: Sie können [] und text verwenden.

Daher würde ich reduce verwenden Sie das Array in die Hash-Format, die Sie suchen zu zwingen, in etwa wie folgt verwendet:

ox_nodes = [#<Ox::Element:0x00007f80d985a668 @value="payee", @attributes={}, @nodes=["starbucks"]>, #<Ox::Element:0x00007f80d9839198 @value="amount", @attributes={}, @nodes=["5.75"]>, #<Ox::Element:0x00007f80d9028788 @value="date", @attributes={}, @nodes=["2017-06-10"]>] 

ox_nodes.reduce({}) do |hash, node| 
    hash[node['@value']] = node.text 
    hash 
end 

Ich bin nicht sicher, ob node['@value'] arbeiten, so dass Sie Vielleicht muss man damit experimentieren - sonst würde vielleicht node.instance_variable_get('@value') es tun.

node.text funktioniert die folgenden, die in etwa richtig klingt:

Gibt das erste String in den Elementen Knoten-Array oder NIL, wenn es keine String-Knoten ist.

N.B. Ich ziehe den reduce Block ein wenig mit tap, so etwas wie die folgenden, ordentlich:

ox_nodes.reduce({}) do |hash, node| 
    hash.tap { |h| h[node['@value']] = node.text } 
end 

Hoffe, das hilft - lassen Sie mich wissen, wie Sie erhalten!

+1

Hey vielen Dank. Alles was du gesagt hast ist richtig und hat mir sehr geholfen. Im zweiten Beispiel muss es node.text anstelle von node.string sein, da ox :: Element nur eine #text-Methode hat.Zu den "Docs" von Ox. Für einen Neuling wie mich, der zwei Monate lang Rubin und Rails lernt, ohne vorherige Kenntnisse in der Informatik, ist es sehr schwer, die Ox-Dokumentation zu lesen. Zum Beispiel, wie bist du auf den Modus gekommen:: Hash-Argument. Ich habe gestern den Ladevorgang den ganzen Tag untersucht, bevor ich hier gepostet habe und es heißt:: mode (: object |: generic |: limited) - Format erwartet –

+0

Ich frage mich, woher Sie wissen, dass Sie Hash als Modus verwenden können. Das zu beantworten würde mir wirklich helfen, nicht tagelang mit der Lektüre von Dokumenten wie dem Ochsen zu arbeiten und immer noch keine Ahnung zu haben, was ich damit anfangen kann. –

+0

Das nächste Problem, das ich mit dem OX-Juwel lösen muss, besteht darin, den resultierenden Hash wieder in ein XML umzuwandeln. Hast du eine Idee, wie ich das machen könnte? –

0

fand ich die Antwort auf die Frage in meinem letzten Kommentar von mir:

def create_xml(expense) 
    Ox.default_options=({:with_xml => false}) 
    doc = Ox::Document.new(:version => '1.0') 
    expense.each do |key, value| 
     e = Ox::Element.new(key) 
     e << value 
     doc << e 
    end 
    Ox.dump(doc) 
end 

Die nächste Frage wäre, wie ich es auf den Wert der Menge Schlüssel aus einem String in einen Integer umwandeln kann befopre Speichern die Datenbank

Verwandte Themen