Nokogiri - 检查xpath的值是否存在且在Ruby中是否为空

时间:2016-08-17 16:02:49

标签: ruby xml xpath nokogiri

我有一个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?

2 个答案:

答案 0 :(得分:0)

您正在创建这样的实例:

gdsn_doc = GDSNDoc.new(xml_file)

然后像这样使用它:

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

@gdsn_docgdsn_doc是Ruby中的两个不同的东西 - 尝试使用不带@的版本:

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

答案 1 :(得分:0)

基本测试是使用:

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在正确解析文档时工作正常。

  

我收到错误“nil的未定义方法'xpath':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自动关闭文件,则首选{p> 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,那么它也是确保内容实际存在的一种不错的方法。