XML api对json或hash的响应?

时间:2011-05-17 23:33:58

标签: ruby xml nokogiri

所以,我正在使用一个恰好只返回XML的API,这很糟糕。我想要做的是为从API返回的每条记录创建一个数据库条目,但我不确定如何。

返回的XML很庞大,里面有很多空格字符......这是正常的吗?以下是一些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 Loc@l</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>
<!-- ... -->

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

这不是非常有效的XML。这是XML的某种转义字符串表示,可能是控制台输出。它似乎也不完整。除此之外,它是相当普通的XML。这是一个较小的摘录,未转义和格式化:

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

您只需要确定要提取的内容并将其放入数据库中,然后让它驱动您的数据库设计决策。您是否需要具有完整关系的多个模型,或者您只关心数据的子集?

答案 1 :(得分:0)

XML可以包含空格,而不会影响其包含的数据的质量。一个好的解析器,就是你应该如何处理XML,它不关心,并且无论是否有空格都可以访问数据。

Nokogiri对我来说很受欢迎,现在似乎是Ruby事实上的标准。它非常易于使用,但您必须学习如何告诉它您想要的节点。

为了帮助你,这里有一些术语:

  • Node是解析后的标记术语。
  • 节点具有属性,可以使用node_var['attribute']
  • 进行访问
  • 可以使用node_var.textnode_var.contentnode_var.inner_text访问节点文字。
  • NodeSet基本上是一个节点数组。
  • at返回与您为解析器提供的访问者匹配的第一个节点。 %是别名。
  • search返回与您为解析器提供的访问者匹配的节点的NodeSet。 /是别名。

以下是我们解析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"]

所有访问都使用CSS,就像您在编写网页时使用的一样。它更简单,而且通常更清晰,但Nokogiri也支持XPath,它非常强大,可以让你将大量处理工作卸载到底层的libXML2库,它将运行得非常快。

Nokogiri与Ruby的Open-URI非常合作,所以如果你从网站上检索XML,你可以这样做:

require 'open-uri'
require 'nokogiri'

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

这是解析HTML,Nokogiri也很擅长,但是XML的流程是相同的,只需用Nokogiri::HTML替换Nokogiri::XML

另请参阅“How to avoid joining all text from Nodes when scraping”。