#html #xpath
#HTML #xpath
Вопрос:
Работа с DOM
, который имеет один и тот же HTML-цикл более 100 раз, который выглядит следующим образом
<div class="intro">
<div class="header">
<h1 class="product-code"> <span class="code">ZY001</span> <span class="intro">ZY001 Title/Intro</span> </h1>
</div>
<div>
<table>
<tbody>
<tr>
<td>Available</td>
<td> S </td>
<td> M </td>
<td> XL </td>
</tr>
Ранее я использовал этот запрос XPath для возврата ВСЕХ значений узла (все более 100 экземпляров DOM-запроса в связи с переменными nodes, которые могут содержать в Available
//div[@class='intro']/div/table/tbody/tr/td[contains(text(),'Available')]/following-sibling::td
объект (DOMNodeList)[595]
public ‘length’ => int 591
Теперь мне нужно настроить таргетинг на product-code
/ code
специально для извлечения всех td
атрибутов для определенного code
Поскольку div, содержащий уникальный идентификатор (в приведенном выше примере ZY001
), не является прямым предком, я думаю, что мне нужно выполнить обратный запрос XPath
Вот одна из моих попыток:
//h1[@class='product-code']/span[contains(@class, 'code') and text() = 'ZY001']/../../div[@class='intro']/div/table/tbody/tr/td[contains(text(),'Available')]/following-sibling::td
Поскольку я определяю /span[contains(@class, 'code') and text() = 'ZY001']
, а затем пытаюсь дважды обойти dom в обратном направлении, используя /../../
, я надеялся / ожидал получить обратно div[@class=’intro’] с текстом ZY001
непосредственно над ним, или, скорее, public 'length' => int 1
Но все мои попытки до сих пор приводили к 0
результатам. Не false
, указывающий на неправильный XPath, но 0
.
Как я могу изменить свой запрос XPath, чтобы вернуть единственный экземпляр из многих <div class="intro">
, которые содержат <h1 class="product-code">
/ <span class="code">
текстовое значение ZY001
?
Комментарии:
1. Вы хотите получить элементы <td> в <div class=»intro»>, где доступен код us ZY001 и 1st <td>, это правильно?
2. Да, правильно. Моя трудность заключается в том, что он не является прямым потомком.
3. ОК. Взгляните на мой ответ. Могу объяснить больше, если требуется.
Ответ №1:
Используйте
//h1[@class='product-code']/span[contains(@class, 'code') and text() = 'ZY001']/../../../div/table/tbody
вместо
//h1[@class='product-code']/span[contains(@class, 'code') and text() = 'ZY001']/../../div[@class='intro']/div/table/tbody
Комментарии:
1. Спасибо. Я попробую, как только вернусь домой (сейчас на работе и у меня нет доступа к коду)
2. Да, это именно то, к чему я стремился, большое вам спасибо! Более конкретно
//h1[@class='product-code']/span[contains(@class, 'code') and text() = 'ZY001']/../../../div/table/tbody/tr/td[contains(text(),'Available')]/following-sibling::td
Ответ №2:
Для этого вы можете использовать любой из приведенных ниже xpath:
//div[@class='intro' and //h1[@class='product-code']/span[@class='code' and text()='ZY001']]//tbody/tr[td[text()='Available']]/td[2]
//div[@class='intro' and //span[@class='code' and text()='ZY001']]//tbody/tr[td[text()='Available']]/td[2]
//div[@class='intro' and //span[@class='code' and text()='ZY001']]//tr[td[text()='Available']]/td[2]
Измените td[2]
на td[3]
и td[4]
, чтобы получить 3-й и 4-й td
значения соответственно
Комментарии:
1. Спасибо за разнообразие возможностей, они интересны. Единственное, что им мешает, это то, что все они, похоже, обрабатываются намного медленнее, чем запрос XPath @StevenLiang. Однако они разные, и завтра я собираюсь провести с ними еще несколько тестов и выбрать ответ.
2. На самом деле мне это немного любопытно, но причина, по которой это происходит так медленно, заключается в том, что он получает все узлы (в 99% итераций.. — все еще хочу протестировать его, как я уже сказал, чтобы понять, что я делаю.), что
td[2]
означает возврат 100 (что соответствует каждой итерации цикла), что означает, что запрос не является эксклюзивным для уникального идентификатора /ZY001
).. Посмотрю еще раз завтра, но моя правка в ответе ниже вашего работает как ссылка, помимо возвратаNULL
вместоAvailable
(если вернуть всеtd
‘ы вnodeValue
, как это делает ваш — что не имеет особого значения, но ссылка.3. Да, это тоже заставило меня задуматься, я никогда не смотрел на xpath как на то, что было бы быстрее, я привык смотреть на это как на то, что, скорее всего, не изменится. Я также собираюсь провести некоторое исследование. Спасибо, что упомянули об этом
4. Это слишком сильно ломает мне голову, чувак: P .. Так что да, запросы игнорируют инкапсуляцию
text() = 'whatever'
дляdiv
классаintro
или, другими словами,//div[@class='intro' and //h1[@class='product-code']/span[@class='code' and text()='ZY001']]//tbody/tr[td[text()='Available']]
возвращают точно такие же результаты XPath, что и этот запрос//div[@class='intro' and //h1[@class='product-code']/span]//tbody/tr[td[text()='Available']]
. Почему это так, я не уверен. Однако это была интересная стратегия, которая заставила меня задуматься в других направлениях. Что касается ответа, я5. должен согласиться с ответом @StevenLiang, поскольку он работает с
text()
путем, возвращающим связанные td для per .. и работает так, как необходимо для моего приложения. Еще раз спасибо за попытку 🙂