Почему xpath снова находит исключенные узлы?

Рассмотрим эту страницу:

<n1 class="a">
  1
</n1>
<n1 class="b">
  <b>bold</b>
  2
</n1>

Если я сначала выберу первый n1 с помощью class="a", я должен исключить второй n1, и это действительно выглядит так:

library(rvest)
b_nodes = read_html('<n1 class="a">1</n1>
<n1 class="b"><b>bold</b>2</n1>') %>% 
  html_nodes(xpath = '//n1[@class="b"]')
b_nodes
# {xml_nodeset (1)}
# [1] <n1 class="b"><b>bold</b>2</n1>

Однако, если мы теперь используем эту «подмножественную» страницу:

b_nodes %>% html_nodes(xpath = '//n1')
# {xml_nodeset (2)}
# [1] <n1 class="a">1</n1>
# [2] <n1 class="b"><b>bold</b>2</n1>

Как узел 1 был «открыт заново»??

Примечание. Я знаю, как получить то, что я хочу, с двумя отдельными xpath. Это концептуальный вопрос о том, почему «подмножество» не сработало должным образом. Насколько я понял, b_nodes должен был полностью исключить первый узел — объект b_nodes не должен был даже знать, что узел существует.


person MichaelChirico    schedule 10.02.2017    source источник
comment
Более простая иллюстрация: b_nodes %>% html_nodes(xpath = '//n1'). Похоже, он не предназначен для привязки / последовательно указывает на исходный объект.   -  person Frank    schedule 10.02.2017
comment
@ Фрэнк, хорошая мысль, я думал, что пробовал это, и это не сработало. я отредактирую в   -  person MichaelChirico    schedule 10.02.2017


Ответы (2)


html_nodes(xpath = '//n1')

// — это сокращение от /descendant-or-self::n1, текущий узел — это весь документ.

измените его на .//n1, . означает, что текущий узел - это то, что вы выбрали раньше

person 宏杰李    schedule 10.02.2017
comment
@MichaelChirico, когда вы используете //, вы запрашиваете весь документ, независимо от того, какой у вас подузел. - person 宏杰李; 10.02.2017
comment
Я все еще нахожу странным, что другие узлы не были удалены первым выражением. то есть весь документ для меня должен быть только <n1 class="b">...</n1>, что отображается из b_nodes. - person MichaelChirico; 11.02.2017

Я не уверен, что вы пытаетесь сделать, но почему бы вам не попытаться пройти по узлам с помощью foreach? Я имею в виду:

$XML = read_html('
<n1s>
<n1 class="a">1</n1>
<n1 class="b"><b>bold</b>2</n1></n1s>') %>%


$valueA = '';
$valueB = '';    
foreach ($XML->xpath('//n1') as $n1) {
        switch ((string)$n1['class']){
              case 'a':
                    $valueA = $XML->n1;
                     break;
              case 'b':
                    $valueB = $XML->n1;
                     break;
        }
    }

Я надеюсь это тебе поможет. С Уважением!

person Carlos M Gomez    schedule 10.02.2017
comment
См. редактирование, это не вопрос того, как что-то сделать - person MichaelChirico; 10.02.2017