【问题标题】:How to save unescaped & in nokogiri xml?如何在 nokogiri xml 中保存未转义的 &?
【发布时间】:2011-10-17 21:56:43
【问题描述】:

如何使用 nokogiri 将& 保存在最终的 xml 文件中?

我的代码是这样的:

require 'rubygems' 
require 'nokogiri'

  file_name = "amp.xml"
    @doc = Nokogiri::XML('<project/>')

    arg = Nokogiri::XML::Node.new "arg", @doc
    arg['line'] = "how to save only &???"
    @doc.root.add_child(arg)

    File.open(file_name, 'w') {|f| f.write(@doc.to_xml) }

输出是这样的

<?xml version="1.0"?>
<project>
  <arg line="how to save only &amp;???"/>
</project>

更新

看起来我可以使用 CDATA,但不确定如何将它与 nokogiri 一起使用。我使用@doc = Nokogiri::XML(File.open(file_name))读取xml文件

【问题讨论】:

标签: ruby xml escaping nokogiri


【解决方案1】:

您不能随意在 XML 中放置未转义的 &amp;。这里来自W3 spec for XML

& 符号 (&) 和左尖括号 (

关于在 Nokogiri 中使用 CDATA,如果您使用 Nokogiri::XML::Builder 来构建 XML,请参考 Nokogiri 网站上的here is info

更新:这是我在 cmets 中提到的示例中的代码。

module Questions
  @source = File.dirname(__FILE__) + '/questions.xml'
  def parse
    if File.exists?(@source)
      File.open(@source, 'r+') do |document|
        q = {}
        text = Nokogiri::XML::Document.parse(document)
        text.xpath('.//question').each do |c|
          parent = c.attribute_nodes[2].to_s
          q[:type] = c.attribute_nodes[1].to_s.to_sym   # => question type
          q[:q_id] = c.attribute_nodes[0].to_s   # => question type
          q[:question] = c.xpath('.//q').first.content   # => question
          q[:answers] = []
          c.xpath('.//a').each { |ans|
            p = ans.attribute_nodes.first.value   # => point value
            a = ans.content   # => answer
            q[:answers] << [a, p]
          }
          if parent == "NA"
            Question.create!(q)
          else
            Question.first(conditions: {q_id: parent}).children << Question.create!(q)
          end
        end
      end
    end
  end

  def write
    builder = Nokogiri::XML::Builder.new do |xml|
      xml.root {
        Question.each do |t|
          xml.question(id: t.id, type: t.type, parent: t.parent) {
            xml.q_ t.q
            t.answers.each { |c|
              xml.a(point: c.p) { xml.text c.a }
            }
          }
        end
      }
    end
    document = builder.to_xml
    File.open(@source, 'w+') do |f|
      f.puts document
    end
  end   # end write

  module_function :parse
  module_function :write
end

--- 还有一个我正在使用的示例。 ---

  <question id="q0000" type="root" parent="NA">
    <q>How do you feel about sports?</q>
    <a point="0">I don't have any interest in sports.</a>
    <a point="q0001">I like to play sports.</a>
    <a point="q0002">I follow college or professional sports.</a>
  </question>

【讨论】:

  • 我不使用生成器。或者,如果我在“更新”中读取 xml 文件,我不知道如何使用构建器。
  • Builder 是我用 Nokogiri 完成 xml 的唯一方法,希望其他人可以帮助您的方法。
  • 不,我相信它只是为了“构建”xml。我使用 XML::Document::parse 以块形式进行解析。如果你愿意,我可以显示一些代码。
  • 我可以按照自己的方式读取文件,然后使用构建器创建新节点,然后将其添加到文件中吗?
  • 是的,在我的用例中,我正在读取数据并创建我拥有的自定义类的对象。然后我会编辑,然后写回文件。我有一种读取方法,然后有一种单独的方法来写回文件。我不确定这是否有助于您的要求。
【解决方案2】:

我最近遇到了类似的问题。您需要使用xml.&lt;&lt; 而不是xml.text https://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/Builder#%3C%3C-instance_method

变化:

            t.answers.each { |c|
              xml.a(point: c.p) { xml.text c.a }
            }

            t.answers.each { |c|
              xml.a(point: c.p) { xml << c.a }
            }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多