简体   繁体   中英

Embed Ruby in xpath/Nokogiri

Probably a pretty easy question:

I'm using Mechanize, Nokogori, and Xpath to parse through some html as such:

category = a.page.at("//li//a[text()='Test']")

Now, I want the term that I'm searching for in text()= to be dynamic...ie I want to create a local variable:

term = 'Test'

and embed that local ruby variable in the Xpath, if that makes sense.

Any ideas how?

My intuition was to treat this like string concatenation, but that doesn't work out:

term = 'Test'
category = a.page.at("//li//a[text()=" + term + "]")

When you use category = a.page.at("//li//a[text()=" + term + "]") . The final result to method is //li//a[text()=Test] where test is not in quotes. So to put quotes around string you need to use escape character \\ .

   term = 'Test'
   category = a.page.at("//li//a[text()=\"#{term}\"]")

or

   category = a.page.at("//li//a[text()='" + term + "']")

or

   category = a.page.at("//li//a[text()='#{term}']")

For example:

>> a="In quotes" #=> "In quotes"

>> puts "This string is \"#{a}\""  #=> This string is "In quotes"
>> puts "This string is '#{a}'"    #=> This string is 'In quotes'
>> puts "This string is '"+a+"'"   #=> This string is 'In quotes'

A little-used feature that might be relevant to your question is Nokogiri's ability to call a ruby callback while evaluating an XPath expression.

You can read more about this feature at http://nokogiri.org under the method docs for Node#xpath ( http://nokogiri.org/Nokogiri/XML/Node.html#method-i-xpath ), but here's an example addressing your question:

#! /usr/bin/env ruby

require 'nokogiri'

xml = <<-EOXML
<root>
  <a n='1'>foo</a>
  <a n='2'>bar</a>
  <a n='3'>baz</a>
</root>
EOXML
doc = Nokogiri::XML xml

dynamic_query = Class.new do
  def text_matching node_set, string
    node_set.select { |node| node.inner_text == string }
  end
end

puts doc.at_xpath("//a[text_matching(., 'bar')]", dynamic_query.new)
# => <a n="2">bar</a>
puts doc.at_xpath("//a[text_matching(., 'foo')]", dynamic_query.new)
# => <a n="1">foo</a>

HTH.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM