Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

XPath queries in fragments do not properly find root nodes #572

Open
Phrogz opened this Issue · 3 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!

Mike Dalessio
Owner

I've folded issues #454, #370, and #213 into this one -- they're all reporting the same underlying issue.

Note that I've committed tests that reproduce the issue to branch issue-572-tests-for-xpath-bug-on-fragment-roots. There are some deep issues here that we should re-examine.

Mike Dalessio flavorjones changed the title from XPath .//foo|//foo cannot find nodes at the root of a DocumentFragment to XPath queries in fragments do not properly find root nodes
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.