XPath выбрать потомка родительского брата

Этот html находится на моей странице:

<tr>
    <td class="padded2" bgcolor="#103A74"><font color="White">Refine by Vehicle Types</font></td>
    </tr><tr>
        <td class="padded2" bgcolor="White"><div>
            <table border="0">
                <tr>
                    <td class="padded2"><font color="#103A74"><ul><li><a class="padded2"> Cars</a></li><li><a class="padded2">Marine Engines</a></li><li><a class="padded2">Trucks</a></li></ul></font></td>
                </tr>
            </table>
        </div></td>
</tr>

Я хочу очистить «Автомобили» и «Грузовики», основываясь на том факте, что они после «Уточнить по типу транспортного средства». Я пробовал много разных способов, и это настолько близко, насколько я могу, но возвращает NULL.

$Nodes = $xPath->query("//tr/td/font[text()[contains(., 'Refine by Vehicle Type')]]/following-sibling::tr/td/div/table/tr/td/font/ul/li/a")->item(0)->nodeValue;

Что мне не хватает?


person Lictor    schedule 02.10.2011    source источник
comment
Вы сами создаете этот html? Использование классов в одном месте и тегов <font> в другом очень уродливо.   -  person Marc B    schedule 02.10.2011
comment
Я соскребаю с другого сайта, поэтому не могу контролировать html, это также динамическая страница, поэтому я не могу просто соскребать только на основе структуры.   -  person Lictor    schedule 02.10.2011


Ответы (1)


Ваша ошибка здесь:

...font[...]/following-sibling::tr/...

Легко видеть, что в представленном XML-фрагменте элемент <font> не имеет родственных элементов.

Вот одно правильное выражение XPath:

  tr[td[contains(., 'Refine by Vehicle Types')]]
      /following-sibling::tr
        /td/div/table
                 /tr/td/font
                         /ul/li/a

При сравнении со следующим XML-документом (предоставленный вами фрагмент заключен в <table>):

<table>
    <tr>
        <td class="padded2" bgcolor="#103A74">
            <font color="White">Refine by Vehicle Types</font>
        </td>
    </tr>
    <tr>
        <td class="padded2" bgcolor="White">
            <div>
                <table border="0">
                    <tr>
                        <td class="padded2">
                            <font color="#103A74">
                                <ul>
                                    <li>
                                        <a class="padded2"> Cars</a>
                                    </li>
                                    <li>
                                        <a class="padded2">Marine Engines</a>
                                    </li>
                                    <li>
                                        <a class="padded2">Trucks</a>
                                    </li>
                                </ul>
                            </font>
                        </td>
                    </tr>
                </table>
            </div>
        </td>
    </tr>
</table>

выбраны следующие элементы:

<a class="padded2"> Cars</a>
<a class="padded2">Marine Engines</a>
<a class="padded2">Trucks</a>

Проверка на основе XSLT:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/*">
  <xsl:copy-of select=
  "tr[td[contains(., 'Refine by Vehicle Types')]]
      /following-sibling::tr
        /td/div/table
                 /tr/td/font
                         /ul/li/a
  "/>
 </xsl:template>
</xsl:stylesheet>

когда это преобразование применяется к документу XML выше, выбранные элементы выводятся:

<a class="padded2"> Cars</a>
<a class="padded2">Marine Engines</a>
<a class="padded2">Trucks</a>

Я бы рекомендовал использовать визуализатор XPath для быстро научиться писать правильные и элегантные выражения XPath.

person Dimitre Novatchev    schedule 02.10.2011
comment
Фактический HTML-код также содержит дубликат этой HTML-структуры с заголовком «Уточнить по категориям». Этот xPath очищает ссылки от всего документа до конца. Как я могу ограничить результаты только этим узлом? - person Lictor; 02.10.2011
comment
@Lictor: Не могли бы вы уточнить свой вопрос? Ограничить только каким узлом? - person Dimitre Novatchev; 02.10.2011
comment
Гм, я имею в виду возвращаемые совпадения ТОЛЬКО из html, который я разместил, а не все совпадения, которые происходят после него. - person Lictor; 02.10.2011
comment
@Ликтор: используйте: (//tr[td[contains(., 'Refine by Vehicle Types')]])[1] /following-sibling::tr /td/div/table /tr/td/font /ul/li/a - person Dimitre Novatchev; 02.10.2011
comment
хм, это ничего не возвращает... вот фактическая структура html, с которой я работаю: <tr><td><font color="White">Refine by Vehicle Types</font></td> </tr><tr><td><div> <table> <tr> <td><font><ul><li><a> Automobile/Light Trucks</a></li></ul></font></td> </tr> </table> </div></td> </tr><tr> <td></td> </tr><tr> <td><font>Refine by Category</font></td> </tr><tr> <td><div> <table> <tr> <td><font><ul><li><a>Agricultural</a></li></ul></font></td></tr> - person Lictor; 03.10.2011
comment
@Lictor: Вы должны предоставить полный, но минимальный XML-документ, чтобы можно было определить, выбирает ли данное выражение нужные узлы - в противном случае даже концепция требуемых узлов не определена. Лучше задайте новый вопрос и на этот раз сформулируйте его точнее! - person Dimitre Novatchev; 03.10.2011