ruby-on-rails - 将 XML 文档导入 Rails 数据库?

标签 ruby-on-rails xml sqlite

我一直在阅读一个接一个的教程,但似乎没有什么适合我的。目标是获取包含元素和属性的 XML 文档并将数据插入数据库。每个元素/属性都是数据库中的一列,每个条目都是一行。这是我一直在使用的虚构的 XML 文档:

<?xml version="1.0"?>
<library>
  <NAME><![CDATA[Favorite Books]]></NAME>
  <book ISBN="11342343">
    <title>To Kill A Mockingbird</title>
    <description><![CDATA[Description#1]]></description>
    <author>Harper Lee</author>
  </book>
  <book ISBN="989894781234">
    <title>Catcher in the Rye</title>
    <description><![CDATA[This is an extremely intense description.]]></description>
    <author>J. D. Salinger</author>
  </book>
  <book ISBN="123456789">
    <title>Murphy's Gambit</title>
    <description><![CDATA[Daughter finds her dad!]]></description>
    <author>Syne Mitchell</author>
  </book>
</library>

所以我想要一个包含 2 个条目的表,每个条目都有一个 ISBN、标题、描述和作者。这是基础知识。 (我想 CDATA 是完全可选的。如果那是我的问题的一部分,无论如何让我们摆脱它......)

最终目标有点复杂。拥有多本书的多个图书馆。数据库之间有关系,所以我可以从我的 Book 数据库中引用 Library 数据库,反之亦然。我完全迷路了,绝对是个菜鸟,但我有很好的计算机知识,愿意测试和尝试。

我使用的是 Rails 3.2.6 和默认的 SQLite3 数据库 (3.6.20)。我已经安装了 REXML、ROXML、LibXML 等,并通读了 API 和演练,但就是没有效果。必须有一种简单的方法将 XML 文档转换为具有 Book 对象(具有 .title、.author、.isbn 和 .description 方法)的 Library 对象(使用 .name 方法)。

非常感谢任何帮助!

更新!

好的,下一个问题。我一直在胡思乱想这背后的逻辑,想知道执行以下操作的最佳方法......

假设我有这个新的和改进的 XML 文件。

<?xml version="1.0"?>
<RandomTag>
  <library name='Favorite Books'>
    <book ISBN="11342343">
      <title>TKAM</title>
      <description>Desc1</description>
      <author>H Lee</author>
    </book>
    <book ISBN="989894781234">
      <title>Catcher in the Rye</title>
      <description>Desc2</description>
      <author>JD S</author>
    </book>
  </library>
  <library name='Other Books'>
    <book ISBN="123456789">
      <title>Murphy\'s Gambit</title>
      <description>Desc3</description>
      <author>Syne M</author>
    </book>
  </library>
</RandomTag>

现在我们有两个图书馆,第一个名为“最喜欢的书”,有 2 本书,第二个名为“其他书籍”,只有一本书。

让每本书知道它属于哪个图书馆的最佳方式是什么?最初,我创建了一个 Library 数据库和一个 Book 数据库。每个 Book 对象都有一个 library_id 字段,它引用了正确的图书馆。因此,每个数据库都可以使用类似“@library.books.each do |b| b.title”的语法正确填写。然而,这仅在我有一个图书馆时有效。

我尝试将您给我的 Book 循环嵌套在一个类似的 Library 循环中,但是 .css 方法找到了每一个匹配项,无论它位于何处。是否有 .css 方法可以找到 UNTIL 特定点?

换句话说,我希望能够将每本书导入其各自的图书馆。我无法向 XML 文件添加任何字段。

再次感谢。

最佳答案

我使用 Nokogiri 库做了类似的事情。

doc = Nokogiri::XML(xml_data)

doc.css('book').each do |node|
  children = node.children

  Book.create(
    :isbn => node['ISBN'],
    :title => children.css('title').inner_text,
    :description => children.css('description').inner_text,
    :author => children.css('author').inner_text
  )
end

更新

您可以通过这样做来创建一个快速测试:

首先安装 nokogiri gem:

gem install nokogiri

然后创建一个名为 text_xml.rb 的文件,内容为:

require 'nokogiri'

doc = Nokogiri::XML('<?xml version="1.0"?>
  <library>
    <NAME><![CDATA[Favorite Books]]></NAME>
    <book ISBN="11342343">
      <title>To Kill A Mockingbird</title>
      <description><![CDATA[Description#1]]></description>
      <author>Harper Lee</author>
    </book>
    <book ISBN="989894781234">
      <title>Catcher in the Rye</title>
      <description><![CDATA[This is an extremely intense description.]]></description>
      <author>J. D. Salinger</author>
    </book>
    <book ISBN="123456789">
      <title>Murphy\'s Gambit</title>
      <description><![CDATA[Daughter finds her dad!]]></description>
      <author>Syne Mitchell</author>
    </book>
  </library>')

doc.css('book').each do |node|
  children = node.children

  book = {
    "isbn" => node['ISBN'], 
    "title" => children.css('title').inner_text, 
    "description" => children.css('description').inner_text, 
    "author" => children.css('author').inner_text
  }

  puts book
end

最后运行:

ruby test_xml.rb

我怀疑您在粘贴 xml 时没有转义 Murphy's Gambit 中的单引号。

关于ruby-on-rails - 将 XML 文档导入 Rails 数据库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11369911/

相关文章:

ruby-on-rails - Rails 按字符串的一部分查找

ruby-on-rails - Assets 管道未在本地服务器上编译

java - 这是什么文档格式?

xml - 与 xmlstarlet 作斗争

mysql - Flask-Admin+SQLAlchemy 图像上传在 MySQL 生产环境中有效,但在 SQLite 测试用例 : InterfaceError 中无效

ruby-on-rails - 评估类的案例陈述未按预期工作

ruby-on-rails - Bundler - 找不到 gem 的兼容版本

java - ObjectInputStream 中的 StreamCorruptedException

angular - 函数从 pouchDB 获取委托(delegate),插入一些调试数据并返回一个 promise

ios - 在 iOS 中使用 FMDB 在 sqlite 中查询 BLOB 数据太慢