Я не могу понять, как решить эту проблему.
<div> <p id="p1"> Price is <span>$ 25</span></p> <p id='p2'> But this price is $ <span id="s1">50,23</span> </p> <p id='p3'> This one : $ 14540.12 dollar</p> </div>
То, что я пытаюсь сделать, это найти элемент с ценой в нем, и это самый короткий путь к нему. Это то, что у меня есть.
$elements = $dom->getElementsByTagName('*'); foreach($elements as $child) { if (preg_match("/.$regex./",$child->nodeValue)){ echo $child->getNodePath(). "<br />"; } }
Это приводит к
/html /html/body /html/body/div /html/body/div/p[1] /html/body/div/p[1]/span /html/body/div/p[2] /html/body/div/p[2]/span /html/body/div/p[3]
Это пути к элементам, которые я хочу, так что это нормально в этом тестовом HTML. Но на реальных веб-страницах этот путь очень длинный и подвержен ошибкам. То, что я хотел бы сделать, это найти ближайший элемент с атрибутом идентификатора и обратиться к нему.
Итак, однажды найденный элемент и элемент, сопоставляемый с $ regex, мне нужно пропустить DOM и найти первый элемент с атрибутом ID и создать новый более короткий путь. В приведенном выше примере HTML есть 3 цены, соответствующие $ regex. Цены указаны в:
//p[@id="p1"]/span //p[@id="s1"] //p[@id="p3"]
Вот что я хотел бы вернуть из своей функции. Я также должен избавиться от всех других существующих путей, потому что они не содержат $ regex
Любая помощь по этому поводу?
Вы можете использовать XPath для отслеживания пути предка к первому узлу, содержащему атрибут @id
а затем отключить его путь. Не очистил код, но что-то вроде этого:
// snip $xpath = new DomXPath($doc); foreach($elements as $child) { $textValue = ''; foreach ($xpath->query('text()', $child) as $text) $textValue .= $text->nodeValue; if (preg_match("/.$regex./", $textValue)) { $path = $child->getNodePath(); $id = $xpath->query('ancestor-or-self::*[@id][1]', $child)->item(0); $idpath = ''; if ($id) { $idpath = $id->getNodePath(); $path = '//'.$id->nodeName.'[@id="'.$id->attributes->getNamedItem('id')->value.'"]'.substr($path, strlen($idpath)); } echo $path."\n"; } }
Печатать что-то вроде
/html /html/body /html/body/div //p[@id="p1"] //p[@id="p1"]/span //p[@id="p2"] //span[@id="s1"] //p[@id="p3"]