XPath для запроса нескольких селекторов - PullRequest
4 голосов
/ 29 января 2012

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

позвольте мне привести пример.

это структура

<div class='message'>
   <div>
   <a href='http://www.whatever.com'>Text</a>
   </div>

   <div>
    <img src='image_link.jpg' />
   </div>

</div>

<div class='message'>
   <div>
   <a href='http://www.whatever2.com'>Text2</a>
   </div>

   <div>
    <img src='image_link2.jpg' />
   </div>

</div>

Итак, я хотел бы сделать запрос, чтобы соответствовать всем этим разам.

Примерно так:

 //$dom is the DomDocument() set up after loaded HTML with $dom->loadHTML($html);
$dom_xpath = new DOMXpath($dom);
$elements = $dom_xpath->query('//div[@class="message"], //div[@class="message"] //a, //div[@class="message"] //img');

foreach($elements as $ele){
   echo $ele[0]->getAttribute('class'); //it should return 'message'
   echo $ele[1]->getAttribute('href'); //it should return 'http://www.whatever.com' in the 1st loop, and 'http://www.whatever2.com' in the second loop
   echo $ele[2]->getAttribute('src'); //it should return image_link.jpg in the 1st loop and 'image_link2.jpg' in the second loop
}

Есть ли способ сделать этоиспользуя несколько селекторов xpath, как я сделал в примере?чтобы не делать запросы постоянно и сэкономить процессор.

Ответы [ 2 ]

6 голосов
/ 29 января 2012

Используйте оператор объединения (|) в одном выражении, например:

//div[@class="message"]|//div[@class="message"]//a|//div[@class="message"]//img

Обратите внимание, что это вернет плоский набор результатов (так сказать). Другими словами, вы не получите доступ к элементам в группах по три, как показано в примере. Вместо этого вы просто итерируете все совпадающие выражения (в порядке документа). По этой причине может быть даже разумнее просто выполнить итерацию узлов, возвращаемых //div[@class="message"], и использовать методы DOM для доступа к своим дочерним элементам (для других элементов).

3 голосов
/ 30 января 2012

Используйте

(//div[@class='message'])[$k]//@*

При этом выбираются все три атрибута, которые принадлежат $ k-й div (и любым его потомкам) в документе, атрибут class которого имеет строковое значение "message"

Вы можете оценить N таких выражений XPath - для $k от 1 до N, где N - это общее число //div[@class='message']

Проверка на основе 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:for-each select="//div[@class='message']">
    <xsl:variable name="vPos" select="position()"/>

    <xsl:apply-templates select=
    "(//div[@class='message'])[0+$vPos]//@*"/>
 ================
  </xsl:for-each>
 </xsl:template>

 <xsl:template match="@*">
  <xsl:value-of select=
  "concat('name = ', name(), ' value = ', ., '&#xA;')"/>
 </xsl:template>
</xsl:stylesheet>

когда это преобразование применяется к предоставленному документу XML (обернутым в один верхний элемент, чтобы стать правильно сформированным):

<html>
    <div class='message'>
        <div>
            <a href='http://www.whatever.com'>Text</a>
        </div>
        <div>
            <img src='image_link.jpg' />
        </div>
    </div>
    <div class='message'>
        <div>
            <a href='http://www.whatever2.com'>Text2</a>
        </div>
        <div>
            <img src='image_link2.jpg' />
        </div>
    </div>
</html>

Выражение XPath вычисляется дважды, а выбранные атрибуты форматируются и выводятся :

name = class value = message
name = href value = http://www.whatever.com
name = src value = image_link.jpg

 ================
name = class value = message
name = href value = http://www.whatever2.com
name = src value = image_link2.jpg

 ================
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...