2011-05-17 4 views
0

Donc, j'utilise une API qui arrive à ne renvoyer que du XML, ça craint. Ce que je veux faire est de créer une entrée de base de données pour chaque enregistrement qui est retourné à partir de l'API, mais je ne sais pas comment.Réponse API XML à JSON, ou hachage?

Le code XML qui est renvoyé est énorme et contient beaucoup de caractères blancs ... est-ce normal? Voici un exemple de XML.

<!-- ... --> 
     <attribute name="item_date">May 17, 2011</attribute> 
     <attribute name="external_url">http://missionlocal.org/2011/05/rain-camioneta-part-i/</attribute> 
      <attribute name="source" id="2478">Mission [email protected]</attribute> 
      <attribute name="excerpt"></attribute> 
    </attributes> 
</newsitem> 

<newsitem 
    id="5185807" 
    title="Lost Chrome messenger PBR bag and contents (marina/cow hollow)" 
    url="http://sf.everyblock.com/lost-and-found/by-date/2011/5/17/5185807/" 
    location_name="Van Ness and Filbert" 
    schema="lost-and-found" 
    schema_id="7" 
    pub_date="May 17, 2011, 12:15 p.m." 
    longitude="-122.424129925" 
    latitude="37.7995100578" 
> 
    <attributes> 
     <attribute name="item_date">May 17, 2011</attribute> 
     <attribute name="external_url">http://sfbay.craigslist.org/sfc/laf/2386709187.html</attribute> 
    </attributes> 
</newsitem> 

<newsitem 
    id="5185808" 
    title="Plywood Update: Dumplings &amp; Buns Aims To Be &quot;Beard Papa Of Chinese Buns&quot;" 
    url="http://sf.everyblock.com/news-articles/by-date/2011/5/17/5185808/" 
    location_name="2411 California Street" 
    schema="news-articles" 
    schema_id="5" 
    pub_date="May 17, 2011, 12:15 p.m." 
    longitude="-122.434000442" 
    latitude="37.7888985667" 
> 
    <attributes> 
     <attribute name="item_date">May 17, 2011</attribute> 
     <attribute name="external_url">http://sf.eater.com/archives/2011/05/17/dumplings_buns_aims_to_be_beard_papa_of_chinese_buns.php</attribute> 
      <attribute name="source" id="2155">Eater SF</attribute> 
      <attribute name="excerpt"></attribute> 
    </attributes> 
</newsitem> 

<newsitem 
    id="5185809" 
    title="Freebies: This week, Piazza D&#39;Angelo (22 Miller..." 
    url="http://sf.everyblock.com/news-articles/by-date/2011/5/17/5185809/" 
    location_name="22 Miller" 
    schema="news-articles" 
    schema_id="5" 
    pub_date="May 17, 2011, 12:15 p.m." 
    longitude="-122.408894997" 
    latitude="37.7931966922" 
> 
    <attributes> 
     <attribute name="item_date">May 17, 2011</attribute> 
     <attribute name="external_url">http://sf.eater.com/archives/2011/05/17/freebies_24.php</attribute> 
      <attribute name="source" id="2155">Eater F</attribute> 
      <attribute name="excerpt"></attribute> 
<!-- ... --> 

Des idées?

+0

Hey Ken merci pour l'aide au reformatage et au nettoyage, cependant une partie du problème est que la sortie est si malpropre et non formatée. Peut-être que l'envoyer à un parseur XML atténue cela, mais je ne sais pas comment l'analyser partie par partie et l'insérer dans la base de données. –

Répondre

1

Ce n'est pas tout à fait valide XML. C'est une sorte de représentation en chaîne à échappement de XML, peut-être une sortie de console. Cela ne semble pas non plus complet. A part ça, c'est du XML assez normal. Voici un petit extrait, et mis en forme non échappée:

<newsitem 
    id="5185807" 
    title="Lost Chrome messenger PBR bag and contents (marina/cow hollow)" 
    url="http://sf.everyblock.com/lost-and-found/by-date/2011/5/17/5185807/" 
    location_name="Van Ness and Filbert" 
    schema="lost-and-found" 
    schema_id="7" 
    pub_date="May 17, 2011, 12:15 p.m." 
    longitude="-122.424129925" 
    latitude="37.7995100578"> 
    <attributes> 
     <attribute name="item_date">May 17, 2011</attribute> 
     <attribute name="external_url">http://sfbay.craigslist.org/sfc/laf/2386709187.html</attribute> 
    </attributes> 
</newsitem> 

Vous aurez juste besoin de déterminer ce que vous voulez extraire et mettre dans la base de données, et laisser que conduire votre décision de conception de DB. Avez-vous besoin de plusieurs modèles avec des relations intactes, ou êtes-vous juste concerné par un sous-ensemble des données?

+0

Je suppose que j'ai besoin des relations intactes, donc ce sera quelques modèles différents, je suis en train d'utiliser mongo, donc je peux gérer tout ça, sauf si vous avez une bonne solution en tête :) La plus grande préoccupation que j'ai est En fait, quelles méthodes je peux passer le corps de ma réponse pour obtenir une sorte d'objets que je peux gérer de manière plus fiable avec ruby. –

0

XML peut avoir des espaces et ne pas affecter la qualité des données qu'il contient. Un bon analyseur, qui est la manière dont vous devriez traiter le XML, ne s'en souciera pas et vous donnera accès aux données, qu'il y ait ou non des espaces.

Nokogiri est un favori pour moi, et semble être le standard de facto pour Ruby aujourd'hui. C'est très facile à utiliser, mais vous devrez apprendre à lui dire quels nœuds vous voulez.

Pour vous aider à aller, voici quelques-unes de la terminologie:

  • nœud est le terme utilisé pour une étiquette après qu'il a été analysé.
  • Les nœuds ont des attributs, auxquels vous pouvez accéder en utilisant node_var['attribute'].
  • Le texte du nœud est accessible en utilisant node_var.text ou node_var.content ou node_var.inner_text. NodeSet est essentiellement un tableau de nœuds.
  • at renvoie le premier nœud correspondant à l'accesseur que vous donnez à l'analyseur. % est un alias.
  • search renvoie un NodeSet de nœuds correspondant à l'accesseur que vous attribuez à l'analyseur. / est un alias.

Voilà comment nous pouvons analyser l'extrait de XML:

require 'nokogiri' 

xml =<<EOT 
<newsitem 
    id="5185807" 
    title="Lost Chrome messenger PBR bag and contents (marina/cow hollow)" 
    url="http://sf.everyblock.com/lost-and-found/by-date/2011/5/17/5185807/" 
    location_name="Van Ness and Filbert" 
    schema="lost-and-found" 
    schema_id="7" 
    pub_date="May 17, 2011, 12:15 p.m." 
    longitude="-122.424129925" 
    latitude="37.7995100578"> 
    <attributes> 
     <attribute name="item_date">May 17, 2011</attribute> 
     <attribute name="external_url">http://sfbay.craigslist.org/sfc/laf/2386709187.html</attribute> 
    </attributes> 
</newsitem> 
EOT 

doc = Nokogiri::XML(xml) 
doc.at('newsitem').text # => "\n \n  May 17, 2011\n  http://sfbay.craigslist.org/sfc/laf/2386709187.html\n \n" 
(doc % 'attribute').content # => "May 17, 2011" 
doc.at('attribute[name="external_url"]').inner_text # => "http://sfbay.craigslist.org/sfc/laf/2386709187.html" 

doc.at('newsitem')['id'] # => "5185807" 

newsitem = doc.at('newsitem') 
newsitem['title'] # => "Lost Chrome messenger PBR bag and contents (marina/cow hollow)" 

attributes = doc.search('attribute').map{ |n| n.text } 
attributes # => ["May 17, 2011", "http://sfbay.craigslist.org/sfc/laf/2386709187.html"] 

attributes = (doc/'attribute').map{ |n| n.text } 
attributes # => ["May 17, 2011", "http://sfbay.craigslist.org/sfc/laf/2386709187.html"] 

Tous les accès utilisent CSS, comme vous utiliseriez lors de l'écriture des pages Web. C'est plus simple, et généralement plus clair, mais Nokogiri supporte aussi XPath, qui est très puissant et qui vous permet de décharger beaucoup de traitement sur la librairie libXML2 sous-jacente, qui fonctionnera très rapidement.

Nokogiri fonctionne très bien avec Ruby Open-URI, donc si vous récupérez le code XML à partir d'un site Web, vous pouvez le faire comme ceci:

require 'open-uri' 
require 'nokogiri' 

doc = Nokogiri::HTML(open('http://www.example.com')) 
doc.to_html.size # => 2825 

C'est l'analyse syntaxique HTML, qui Nokogiri excelle aussi, mais la le processus est le même pour XML, il suffit de remplacer Nokogiri::HTML par Nokogiri::XML.

Voir aussi "How to avoid joining all text from Nodes when scraping".