繁体   English   中英

将Nokogiri XML文档转换为字符串数组?

[英]Convert Nokogiri XML Document into Array of Strings?

我正在创建Ruby on Rails应用程序,并使用Nokogiri解析XML文件。 我正在尝试将XML文件解析为可变的字符串,可以操纵这些字符串来创建其他内容。

这是我正在使用的示例XML

<feed xmlns="http://www.w3.org/2005/Atom">
  <entry>
    <title type="html">
      <![CDATA[ First Post! ]]>
    </title>
    <content type="html">
      <![CDATA[
        <p>I&rsquo;m very excited to have finally got my site up and running along with this blog!</p>]]>
    </content>
  </entry>
</feed>

到目前为止,这是我针对自己的问题所做的

在我的控制器中-

def index
    @blog_title, @blog_post = parse_xml
end

private
def parse_xml
    @xml_doc = Nokogiri::XML(open("atom.xml"))
    titles = @xml_doc.css("entry title")
    post = @xml_doc.css("content")
    return titles, post
end

在我看来 -

<% for i in 1..@blog_title.length %>
    <li><%= @blog_title[i-1] %></li>
    <li><%= @blog_post[i-1] %></li>
<% end %>

该视图的示例输出(返回Nokogiri元素)-

<title type="html"><![CDATA[First Post!]]></title>

因此,理想情况下,我想将Nokogiri :: Document内的所有Nokogiri :: Element设置为字符串,或将整个数组设置为String数组。

我尝试遍历每个元素并调用.to_s,但它似乎不起作用。

我还尝试了调用诸如slice之类的Ruby :: String方法,但这种方法不起作用(出于明显的原因)。

我试图获得的最终结果(使用我的视图中的示例输出)是仅返回以下内容,其余均不返回。

First Post!

谁能帮我? 如果我不太清楚,或者如果有人需要查看更多工作,请随时提问!

对于您的情况,您应该只使用.text提取标签的内容。 titles.text这样的东西会起作用。

您正在处理RSS / Atom提要,其中可能包含多个title标签。 您需要遍历所有title节点并分别提取它们的内容,以使您能够跟踪它们的顺序以及它们所附的文章:

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<feed xmlns="http://www.w3.org/2005/Atom">
  <entry>
    <title type="html">
      <![CDATA[ First Post! ]]>
    </title>
    <content type="html">
      <![CDATA[
        <p>I&rsquo;m very excited to have finally got my site up and running along with this blog!</p>]]>
    </content>
  </entry>
</feed>
EOT

doc.search('title').map(&:text)
# => ["\n       First Post! \n    "]

这将返回title节点内的文本数组。 从那里,您可以轻松清理每个字符串,对其进行操作,重新使用它们,无论如何。

doc.search('title').map{ |s| s.text.strip }
# => ["First Post!"]

search返回一个NodeSet,它类似于文档中找到的title节点数组。 如果不对它们进行迭代,则会得到一个包含所有文本的串联字符串,通常不是您想要的:

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<foo>
  <title>this</title>
  <title>is</title>
  <title>what</title>
  <title>you'd</title>
  <title>get</title>
</foo>
EOT

doc.search('title').text
# => "thisiswhatyou'dget"

与:

doc.search('title').map(&:text)
# => ["this", "is", "what", "you'd", "get"]

除非您事先了解文档的结构(通常是不正确的),否则试图将第一个结果拆开是不可能的。 对返回的NodeSet进行迭代将产生非常有用的结果。

为了保持与提要中各种title标签的一致性,您需要遍历条目,然后提取嵌入的标题,这与示例XML和代码显示的内容有些不同:

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<feed xmlns="http://www.w3.org/2005/Atom">
  <entry>
    <title type="html">
      <![CDATA[ First Post! ]]>
    </title>
    <content type="html">
      <![CDATA[
        <p>I&rsquo;m very excited to have finally got my site up and running along with this blog!</p>]]>
    </content>
  </entry>
  <entry>
    <title type="html">
      <![CDATA[ Second Post! ]]>
    </title>
    <content type="html">
      <![CDATA[
        <p>blah</p>]]>
    </content>
  </entry>
</feed>
EOT

titles = doc.search('entry').map { |entry|
  entry.at('title').text.strip
}
titles # => ["First Post!", "Second Post!"]

或更有用:

titles_and_content = doc.search('entry').map { |entry|
  [
    entry.at('title').text.strip,
    entry.at('content').text.strip
  ]
}
titles_and_content 
# => [["First Post!",
#      "<p>I&rsquo;m very excited to have finally got my site up and running along with this blog!</p>"],
#     ["Second Post!", "<p>blah</p>"]]

返回每个条目的标题和内容。 通过此操作,您可以轻松地构建代码以提取文章的链接,发布日期,刷新率,原始网站,您想了解的有关单个文章及其来源的所有信息,然后将其存储在数据库中以供以后使用要求时返流。

有一些宝石和脚本可用于处理RDF,RSS和Atom提要,但是,几年前,当我不得不为提要编写一个大型聚合器时,没有任何东西可以满足我的需求,因此我从头开始编写了一个。 我建议尝试找到一个轮子,而不是重新发明那个轮子,否则,请仔细研究他们的资源并从他们的经验中学习。 要成为一个良好的网络公民,代码中有许多事情要做,这不会淹没服务器并使您被禁止。

另请参见“ 如何避免在刮取时加入节点中的所有文本 ”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM