Используете XPath с фрагментом HTML или XML? - PullRequest
1 голос
/ 29 сентября 2010

Я новичок в Nokogiri и XPath и пытаюсь получить доступ ко всем комментариям во фрагменте HTML или XML. XPaths .//comment() и //comment() работают, когда я не использую функцию fragment, но они не находят ничего с фрагментом. С тегом вместо комментария он работает с первым XPath.

Методом проб и ошибок я понял, что в этом случае comment() находит только комментарии верхнего уровня, а .//comment(), а некоторые другие находят только внутренние комментарии. Я делаю что-то неправильно? Что мне не хватает? Кто-нибудь может объяснить, что происходит?

Какой XPath я должен использовать, чтобы получить все комментарии в HTML-фрагменте, проанализированном Nokogiri?

Этот пример может помочь понять проблему:

str = "<!-- one --><p><!-- two --></p>"

# this works:
Nokogiri::HTML(str).xpath("//comment()")
=> [#<Nokogiri::XML::Comment:0x3f8535d71d5c " one ">, #<Nokogiri::XML::Comment:0x3f8535d71cf8 " two ">]
Nokogiri::HTML(str).xpath(".//comment()")
=> [#<Nokogiri::XML::Comment:0x3f8535cc7974 " one ">, #<Nokogiri::XML::Comment:0x3f8535cc7884 " two ">]

# with fragment, it does not work:
Nokogiri::HTML.fragment(str).xpath("//comment()")
=> []
Nokogiri::HTML.fragment(str).xpath("comment()")
=> [#<Nokogiri::XML::Comment:0x3f8535d681a8 " one ">]
Nokogiri::HTML.fragment(str).xpath(".//comment()")
=> [#<Nokogiri::XML::Comment:0x3f8535d624d8 " two ">]
Nokogiri::HTML.fragment(str).xpath("*//comment()")
=> [#<Nokogiri::XML::Comment:0x3f8535d5cb8c " two ">]
Nokogiri::HTML.fragment(str).xpath("*/comment()")
=> [#<Nokogiri::XML::Comment:0x3f8535d4e104 " two ">]

# however it does if it is a tag instead of a comment:
str = "<a desc='one'/> <p><a>two</a><a desc='three'/></p>"
Nokogiri::HTML.fragment(str).xpath(".//a")
=> [#<Nokogiri::XML::Element:0x3f8535cb44c8 name="a" attributes=[#<Nokogiri::XML::Attr:0x3f8535cb4194 name="desc" value="one">]>, #<Nokogiri::XML::Element:0x3f8535cb4220 name="a" children=[#<Nokogiri::XML::Text:0x3f8535cb3ba4 "two">]>, #<Nokogiri::XML::Element:0x3f8535cb3a3c name="a" attributes=[#<Nokogiri::XML::Attr:0x3f8535cb3960 name="desc" value="three">]>]

PS: без fragment он делает то, что я хочу, но он также добавляет некоторые вещи, такие как «DOCTYPE», и у меня действительно есть только фрагмент HTML-файла, который я редактирую (удаляя некоторые теги, заменяя другие). 1016 *

Ответы [ 2 ]

7 голосов
/ 29 сентября 2010

//comment() - это краткая форма /descendant-or-self::node()/child::comment()

, при использовании этого xpath с фрагментом игнорируются корневые комментарии (они выбираются /descendant-or-self::node(), но у них нет дочерних элементов).

если вы используете HTML(str), вы создаете узел документа в качестве корня всех других элементов.следовательно, /descendant-or-self::node()/child::comment() не игнорирует комментарии верхнего уровня, потому что они являются дочерними элементами узла документа (который сам выбирается /descendant-or-self::node()).

Я не уверен, почему descendant::comment() работает в любом случаеЯ бы сказал, что это должно быть descendant-or-self::comment(), но не берите в голову.

Надеюсь, это поможет?

3 голосов
/ 29 сентября 2010

"descendant::comment()" и "descendant::sometag" отлично работает в каждом случае, но я до сих пор не понимаю этих различий.

...