Skip to content
This repository

XPath .//foo|//foo cannot find nodes at the root of a DocumentFragment #572

Open
Phrogz opened this Issue November 21, 2011 · 2 comments

2 participants

Gavin Kistner Mike Dalessio
Gavin Kistner

Summary (from conversation below):

  • In a fragment, foo and ./foo match nodes at the top of the fragment, but /foo does not.
  • In a fragment, neither //foo nor .//foo match items at the top of the fragment.
  • In a fragment, //foo does not match any descendant items, but .//foo does.

Original Issue

require 'nokogiri'
xml   = '<?foo?><root/>'
xpath = './/processing-instruction()'
frag  = Nokogiri::XML::DocumentFragment.parse(xml)

# The PI is part of the fragment
p frag.children, frag.to_s
#=> [#<Nokogiri::XML::ProcessingInstruction:0x17550b4 name="foo">,
#=>  #<Nokogiri::XML::Element:0x175509c name="root">]
#=> "<?foo?><root/>"

# ...but cannot be found via XPath
p frag.xpath(xpath)
#=> []

# ...but can be found in a document
p Nokogiri.XML(xml).xpath(xpath)
#=> [#<Nokogiri::XML::ProcessingInstruction:0x190e7ec name="foo">]

The use case here is to remove all PIs from a fragment via:

frag.xpath('.//processing-instruction()').remove

The simple workaround (for PIs only at the root) is to find these nodes using Ruby:

frag.children.select{ |n| n.node_type==Nokogiri::XML::Node::PI_NODE }.each(&:remove)
Mike Dalessio
Owner

Greetings!

Thanks for asking this question. It's not clear to me whether a fragment should have processing instructions, but in any case, this appears to be related to #370

That is, if you search using "./processing-instruction()" you'll get a match. Hope that workaround helps you until we fix the real underlying issue with fragment searches.

Gavin Kistner

Ah, thanks, that helps. It does appear to the same core issue as #370. I've renamed the title to match. In summary:

  • In a fragment, foo and ./foo match nodes at the top of the fragment, but /foo does not.
  • In a fragment, neither //foo nor .//foo match items at the top of the fragment.
  • In a fragment, //foo does not match any descendant items, but .//foo does.

The proper workaround for my case is:

frag.xpath('processing-instruction()|.//processing-instruction()')

If you feel that this is exactly the same as #370, close away!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.