Nokogiri:NoMethodError(未定义的方法`inner_html'对于nil:NilClass)

时间:2016-11-17 20:21:47

标签: ruby-on-rails ruby xml xml-parsing nokogiri

我尝试使用 nokogiri 解析一个简单的XML数据。 这是我的XML:

POST /.... HTTP/1.1
Host: ....
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://...."

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="...." xmlns:xsd="...." xmlns:soap="....">
  <soap:Body>
    <WS_QueryOnSec xmlns="......">
      <type>string</type>
      <ID>string</ID>
    </WS_QueryOnSec>
  </soap:Body>
</soap:Envelope>

这是我的同意请求:

require "nokogiri"
@doc = Nokogiri::XML(request.body.read)
@something = @doc.at('type').inner_html

但是Nokogiri找不到Type或ID节点。 当我将数据更改为此内容时,每件事情都可以正常工作:

  <soap:Body>
      <type>string</type>
      <ID>string</ID>
  </soap:Body>

问题似乎是上面的原始文本数据和点头与xmlns或其他属性! 您建议如何解决此问题?

1 个答案:

答案 0 :(得分:1)

第一个“XML”不是XML。它是包含XML的文本。将标题信息删除到空白行并再次尝试。

我认为它可以帮助您阅读XML spec或阅读有关创建XML的一些教程,这些教程将帮助您了解它的定义方式。 XML是一个严格的规范,不允许任何偏差。语法非常灵活,但您必须遵守其规则。

请考虑以下示例:

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
foo

<root>
  <node />
</root>
EOT

doc.errors # => [#<Nokogiri::XML::SyntaxError: Start tag expected, '<' not found>]

删除根标记之外的文本会导致正确的解析:

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<root>
  <node />
</root>
EOT

doc.errors # => []

<root>不一定是“root”节点的名称,它只是最外面的标记:

doc = Nokogiri::XML(<<EOT)
<foo>
  <node />
</foo>
EOT

doc.errors # => []

仍然会产生文档的有效DOM /内部表示:

puts doc.to_html 

# >> <foo>
# >>   <node></node>
# >> </foo>

您的XML示例正在使用命名空间,这在某种程度上使问题复杂化。 Nokogiri documentation讨论了如何处理它们,因此您需要了解解析XML的那部分因为您将再次遇到它。这是与他们合作的简单方法:

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<?xml version="1.0" encoding="utf-8"?>
<Envelope xmlns:xsi="...." xmlns:xsd="...." xmlns:soap="....">
  <Body>
    <WS_QueryOnSec xmlns="......">
      <type>string</type>
      <ID>string</ID>
    </WS_QueryOnSec>
  </Body>
</Envelope>
EOT

namespaces = doc.collect_namespaces

doc.at('type', namespaces).text # => "string"