3

我对 Ruby 很陌生,并试图用 REXML 解析一个 XML 文档,该文档以前已经漂亮地打印(由 REXML),结果有些不稳定。

一些 CDATA 部分在开始 XML 标记之后但在 CDATA 块开始之前有一个换行符,在这些情况下,REXML 将标记的文本解析为空。

  • 知道我是否可以让 REXML 阅读这些行吗?
  • 如果没有,我可以用正则表达式或其他东西重新编写它们吗?
  • 这甚至是有效的 XML 吗?

这是一个示例 XML 文档(删节很多):

<?xml version="1.0" encoding="utf-8"?>
<root-tag>
    <content type="base64"><![CDATA[V2VsbCBkb25lISBJdCB3b3JrcyA6KQ==]]></content>
    <content type="base64">
        <![CDATA[VGhpcyB3b250IHdvcms=]]></content>

    <content><![CDATA[This will work]]></content>
    <content>
        <![CDATA[This will not appear]]></content>

    <content>
        Seems happy</content>
    <content>Obviously no problem</content>
</root-tag>

这是我的 Ruby 脚本(精简为一个最小示例):

require 'rexml/document'
require 'base64'
include REXML

module RexmlSpike
  file = File.new("ex.xml")
  doc = Document.new file
  doc.elements.each("root-tag/content") do |contentElement|
    if contentElement.attributes["type"] == "base64"
      puts "decoded: " << Base64.decode64(contentElement.text)
    else
      puts "raw: " << contentElement.text
    end
  end
  puts "Finished."
end

我得到的输出是:

>> ruby spike.rb
  decoded: Well done! It works :)
  decoded:
  raw: This will work
  raw:

  raw:
          Seems happy
  raw: Obviously no problem
  Finished.

我在 OSX Lion 上使用 Ruby 1.9.3p392。练习的目标最终是将一些 BlogML 中的评论解析为 Disqus 使用的自定义导入 XML。

4

3 回答 3

4

为什么

在覆盖之前拥有任何东西. 从字母到换行符(就像您发现的那样)或单个空格的任何内容。这是有道理的,因为您的示例正在获取元素,并且空格算作文本。在您可以访问的示例中,这是因为 text 为 nil。<![CDATA[]]><![CDATA[]]>text<![CDATA[]]>


解决方案

如果您查看Element 的文档,您会发现它有一个名为的函数cdatas()

获取所有 CData 子项的数组。不可变的。

因此,在您的示例中,如果您执行内部循环,contentElement.cdatas()您将看到所有丢失标签的内容。

于 2013-08-09T14:14:00.200 回答
3

我建议使用Nokogiri,它是 Ruby 的事实上的 XML/HTML 解析器。使用它来访问<content>标签的内容,我得到:

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<?xml version="1.0" encoding="utf-8"?>
<root-tag>
    <content type="base64"><![CDATA[V2VsbCBkb25lISBJdCB3b3JrcyA6KQ==]]></content>
    <content type="base64">
        <![CDATA[VGhpcyB3b250IHdvcms=]]></content>

    <content><![CDATA[This will work]]></content>
    <content>
        <![CDATA[This will not appear]]></content>

    <content>
        Seems happy</content>
    <content>Obviously no problem</content>
</root-tag>
EOT

doc.search('content').each do |n|
  puts n.content
end

哪个输出:

V2VsbCBkb25lISBJdCB3b3JrcyA6KQ==

        VGhpcyB3b250IHdvcms=
This will work

        This will not appear

        Seems happy
Obviously no problem
于 2013-08-01T22:48:01.297 回答
2

正如@lightswitch05 指出的那样,您的 xml 是有效的,但不是您期望的方式。您可以使用w3c xml 验证器

如果您使用来自狂野网络的 XML,那么使用 nokogiri 是一个好主意,因为它通常按您认为应该的那样工作,而不是真正应该的。

旁注:这正是我避免使用 XML 而使用 JSON 的原因:XML 有一个正确的定义,但似乎没有人使用它。

于 2013-08-11T00:49:48.440 回答