3 Stimmen

XML-Sammlung (von Pivotal Tracker-Stories) in Ruby-Hash/Objekt umwandeln

Ich habe eine Sammlung von Geschichten in einem XML-Format. Ich möchte die Datei analysieren und jede Geschichte entweder als Hash oder Ruby-Objekt zurückgeben, so dass ich die Daten in einem Ruby-Skript weiter bearbeiten kann.

Hat Nokogiri unterstützen, oder gibt es ein besseres Werkzeug/eine bessere Bibliothek, die man verwenden kann?

Das XML-Dokument hat die folgende Struktur und wird über Die Web-API von Pivotal Tracker :

<?xml version="1.0" encoding="UTF-8"?>
<stories type="array" count="145" total="145">
  <story>
    <id type="integer">16376</id>
    <story_type>feature</story_type>
    <url>http://www.pivotaltracker.com/story/show/16376</url>
    <estimate type="integer">2</estimate>
    <current_state>accepted</current_state>
    <description>A description</description>
    <name>Receivable index listing will allow selection viewing</name>
    <requested_by>Tony Superman</requested_by>
    <owned_by>Tony Superman</owned_by>
    <created_at type="datetime">2009/11/04 15:49:43 WST</created_at>
    <accepted_at type="datetime">2009/11/10 11:06:16 WST</accepted_at>
    <labels>index ui,receivables</labels>
  </story>
  <story>
    <id type="integer">17427</id>
    <story_type>feature</story_type>
    <url>http://www.pivotaltracker.com/story/show/17427</url>
    <estimate type="integer">3</estimate>
    <current_state>unscheduled</current_state>
    <description></description>
    <name>Validations in wizards based on direction</name>
    <requested_by>Matthew McBoggle</requested_by>
    <created_at type="datetime">2009/11/17 15:52:06 WST</created_at>
  </story>
  <story>
    <id type="integer">17426</id>
    <story_type>feature</story_type>
    <url>http://www.pivotaltracker.com/story/show/17426</url>
    <estimate type="integer">2</estimate>
    <current_state>unscheduled</current_state>
    <description>Manual payment needs a description field.</description>
    <name>Add description to manual payment</name>
    <requested_by>Tony Superman</requested_by>
    <created_at type="datetime">2009/11/17 15:10:41 WST</created_at>
    <labels>payment process</labels>
  </story>
  <story>
    <id type="integer">17636</id>
    <story_type>feature</story_type>
    <url>http://www.pivotaltracker.com/story/show/17636</url>
    <estimate type="integer">3</estimate>
    <current_state>unscheduled</current_state>
    <description>The SMS and email templates needs to be editable by merchants.</description>
    <name>Notifications are editable by the merchant</name>
    <requested_by>Matthew McBoggle</requested_by>
    <created_at type="datetime">2009/11/19 16:44:08 WST</created_at>
  </story>
</stories>

6voto

Nicholas C Punkte 1083

Sie können die Hash-Erweiterungen in ActiveSupport nutzen. Dann müssen Sie Ihr Dokument nur noch in Nokogiri parsen und das Nodeset-Ergebnis in einen Hash umwandeln. Bei dieser Methode bleibt die Typisierung der Attribute (z. B. Ganzzahlen, Daten, Arrays) erhalten. (Wenn Sie Rails verwenden, müssen Sie natürlich keine aktive Unterstützung oder Nokogiri voraussetzen/einschließen, wenn Sie es in Ihrer Umgebung haben. Ich gehe hier von einer reinen Ruby-Implementierung aus).

require 'rubygems'
require 'nokogiri'
require 'activesupport'

include ActiveSupport::CoreExtensions::Hash

doc = Nokogiri::XML.parse(File.read('yourdoc.xml'))
my_hash = doc.search('//story').map{ |e| Hash.from_xml(e.to_xml)['story'] }

Dies erzeugt ein Array von Hashes (einen für jeden Story-Knoten) und bewahrt die Typisierung auf der Grundlage der Attribute, wie unten gezeigt:

my_hash.first['name']
=> "Receivable index listing will allow selection viewing"

my_hash.first['id']
=> 16376

my_hash.first['id'].class
=> Fixnum

my_hash.first['created_at'].class
=> Time

2voto

Mladen Jablanović Punkte 42360

Eine Art Ein-Linien-Lösung wäre etwa so:

# str_xml contains your xml
xml = Nokogiri::XML.parse(str_xml)
xml.search('//story').to_a.map{|node| node.children.inject({}){|a,c| a[c.name] = c.text if c.class == Nokogiri::XML::Element; a}}

die ein Array von Hashes zurückgibt:

>> xml.search('//story').to_a.map{|node| node.children.inject({}){|a,c| a[c.name] = c.text if c.class == Nokogiri::XML::Element; a}}
=> [{"id"=>"16376", "story_type"=>"feature", "url"=>"http://www.pivotaltracker.com/story/show/16376", "estimate"=>"2", "current_state"=>"accepted", "description"=>"A description", "name"=>"Receivable index listing will allow selection viewing", "requested_by"=>"Tony Superman", "owned_by"=>"Tony Superman", "created_at"=>"2009/11/04 15:49:43 WST", "accepted_at"=>"2009/11/10 11:06:16 WST", "labels"=>"index ui,receivables"}, {"id"=>"17427", "story_type"=>"feature", "url"=>"http://www.pivotaltracker.com/story/show/17427", "estimate"=>"3", "current_state"=>"unscheduled", "description"=>"", "name"=>"Validations in wizards based on direction", "requested_by"=>"Matthew McBoggle", "created_at"=>"2009/11/17 15:52:06 WST"}, {"id"=>"17426", "story_type"=>"feature", "url"=>"http://www.pivotaltracker.com/story/show/17426", "estimate"=>"2", "current_state"=>"unscheduled", "description"=>"Manual payment needs a description field.", "name"=>"Add description to manual payment", "requested_by"=>"Tony Superman", "created_at"=>"2009/11/17 15:10:41 WST", "labels"=>"payment process"}, {"id"=>"17636", "story_type"=>"feature", "url"=>"http://www.pivotaltracker.com/story/show/17636", "estimate"=>"3", "current_state"=>"unscheduled", "description"=>"The SMS and email templates needs to be editable by merchants.", "name"=>"Notifications are editable by the merchant", "requested_by"=>"Matthew McBoggle", "created_at"=>"2009/11/19 16:44:08 WST"}]

Allerdings werden dabei alle XML-Attribute ignoriert, aber Sie haben ja auch nicht gesagt, was Sie mit ihnen machen wollen... ;)

1voto

khelll Punkte 22794

Ich denke, Sie können sich an diese Antwort.

Eine einfachere Variante findet sich unter aquí .

1voto

Paul McMahon Punkte 1260

Diese XML-Datei wird von der ActiveRecord#to_xml-Methode von Rails erzeugt. Wenn Sie Rails verwenden, sollten Sie in der Lage sein, Hash#from_xml zu verwenden, um es zu parsen.

0voto

Jakub Punkte 735

Vielleicht ist eine Ruby-Schnittstelle zu Pivotal API eine bessere Lösung für Ihre Aufgabe, siehe https://github.com/jsmestad/pivotal-tracker ... dann können Sie Geschichten als einfache Ruby-Objekte wie (von docs):

@a_project = PivotalTracker::Project.find(84739)                              
@a_project.stories.all(:label => 'overdue', :story_type => ['bug', 'chore'])

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X