XPath查询多个选择器

4

我希望能够从选择器中获取值和属性,然后根据查询获取其子元素的属性和值。

让我举个例子。

这是结构:

<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选择器的方法,就像我在示例中所做的那样?以避免重复查询并节省一些CPU。

查询方法返回一个DOMNodeList。遍历该DOMNodeList将会得到DOMNode子类型。它们中的任何一个都不能使用ArrayAccess访问,因此您展示的代码在常规DOM功能下是不可能实现的。 - Gordon
2个回答

8

使用联合运算符(|)在单个表达式中进行如下操作:

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

请注意,这将返回一个扁平的结果集。换句话说,您无法像示例中显示的那样按组访问三个元素。相反,您将迭代表达式匹配的所有内容(按文档顺序)。因此,更明智的做法可能是简单地迭代由//div[@class="message"]返回的节点,并使用DOM方法访问它们的子元素(对于其他元素)。

3

用途:

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

这个语句选择位于文档中的 class 属性字符串值为 "message" 的第 $k 个 div 元素及其后代的所有三个属性。

您可以评估 N 个这样的 XPath 表达式,其中 N//div[@class='message'] 的总数目,$k 的取值范围是从 1 到 N

基于 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

 ================

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接