Nokogiri——检查xpath的值是否存在,并且在Ruby中是否为空



我有一个XML文件,在处理它之前,我需要确保某个元素存在并且不为空。

下面是我的代码:

CSV.open("#{csv_dir}/products.csv","w",{:force_quotes => true}) do |out|
out << headers
Dir.glob("#{xml_dir}/*.xml").each do |xml_file|
gdsn_doc = GDSNDoc.new(xml_file)
logger.info("Processing xml file #{xml_file}")
:x
@desc_exists = @gdsn_doc.xpath("//productData/description")
 if !@desc_exists.empty?
  row = []
  headers.each do |col|
  row  << product[col]
end
 out << row
end
end
end

以下代码无法查找"description"元素并检查其是否为空白:

  @desc_exists = @gdsn_doc.xpath("//productData/description")
  if !@desc_exists.empty?

下面是一个XML文件的示例:

<productData>
<description>Chocolate biscuits </description>
<productData>

这是我如何定义类和Nokogiri:

class GDSNDoc
def initialize(xml_file)
   @doc =  File.open(xml_file) {|f| Nokogiri::XML(f)}
   @doc.remove_namespaces!

代码必须移动到更早的阶段,在那里Nokogiri被初始化。它不会得到运行时错误,但它确实允许带有空白描述的XML文件通过,这是不应该的。

class GDSNDoc
 def initialize(xml_file)
   @doc =  File.open(xml_file) {|f| Nokogiri::XML(f)}
   @doc.remove_namespaces!
   desc_exists = @doc.xpath("//productData/descriptions")
   if !desc_exists.empty?

您创建的实例如下:

gdsn_doc = GDSNDoc.new(xml_file)

然后像这样使用:

@desc_exists = @gdsn_doc.xpath("//productData/description")

@gdsn_docgdsn_doc在Ruby中是两个不同的东西-尝试使用没有@:

的版本
@desc_exists = gdsn_doc.xpath("//productData/description")

基本的测试是使用:

require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<productData>
<description>Chocolate biscuits </description>
<productData>
EOT
# using XPath selectors...
doc.xpath('//productData/description').to_html # => "<description>Chocolate biscuits </description>"
doc.xpath('//description').to_html # => "<description>Chocolate biscuits </description>"

xpath工作正常,当文档被正确解析。

我得到一个错误"undefined method 'xpath' for nil:NilClass (NoMethodError)

通常这意味着您没有正确解析文档。在你的例子中,这是因为你没有使用正确的变量:

gdsn_doc = GDSNDoc.new(xml_file)
...
@desc_exists = @gdsn_doc.xpath("//productData/description")

注意gdsn_doc@gdsn_doc不一样。后者似乎没有初始化。


@doc = File.open(xml_file) {|f| Nokogiri::XML(f)}

虽然这应该可以工作,但习惯做法是这样写:

@doc = Nokogiri::XML(File.read(xml_file))
如果您在块内进行处理并希望Ruby自动关闭文件,则首选

File.open(...) do ... end。当您只是简单地读取然后将内容传递给其他东西进行处理时,这是不必要的,因此使用File.read(...)来处理文件。(Slurping不是必要的好习惯,因为它可能有可伸缩性问题,但对于合理大小的XML/HTML,它是可以的,因为使用基于dom的解析比使用SAX更容易。)


如果Nokogiri没有引发异常,它能够解析内容,但这仍然不意味着内容是有效的。检查

是个好主意。
@doc.errors

查看Nokogiri/libXML是否必须对内容进行一些修改才能解析它。修复标记可能会改变DOM,使其不符合您的期望,从而无法根据您对选择器的假设找到标记。您可以使用xmllint或某个XML验证器进行检查,但Nokogiri仍然会感到高兴。

Nokogiri包含一个命令行版本nokogiri,它接受您想要解析的文档的URL:

nokogiri http://example.com

它将打开IRB,内容已加载并准备好让您戳它。在调试和测试时非常方便。如果您正在处理包含动态加载页面部分的DHTML的HTML,那么这也是确保内容实际存在的一种不错的方法。

相关内容

  • 没有找到相关文章

最新更新