XPath获得一个级别的子节点

时间:2010-01-01 00:36:20

标签: php xpath domxpath

使用DOMXPath :: query是否可以只获得一个级别的childNodes?

例如,如果我有一个类似的文件:

<div>
    <span>
        <cite>
        </cite>
    </span>
    <span>
        <cite>
        </cite>
    </span>
</div>

我希望NodeList只包含跨度而不是引用。

还应该提到它并不总是相同的元素(div,span等)。我需要它来处理任何类型的元素。

这是我尝试过的,似乎没有用:

//*[not(ancestor::div)]

2 个答案:

答案 0 :(得分:3)

如果您使用

/div/*

然后你会得到这个元素中所有直接孩子的列表,但这些孩子包含他们的孩子。我认为你不能删除孩子的孩子

使用默认轴,称为child::。该轴仅返回当前节点

下1级的元素

*匹配所有元素但属性和text()

您必须指定节点的路径并注意//node,因为它意味着descendant::node并且它会在此树中返回此名称的所有节点

答案 1 :(得分:2)

您的问题有点不明确,因此有几种方法可以解释它。如果您想要当前元素的所有直接子元素(包含其所有子元素),请使用

*/*

对于您的示例,这将为您提供

<span>
    <cite>
    </cite>
</span>

<span>
    <cite>
    </cite>
</span>

如果您想要所有子节点,请使用node()代替*

*/node()

对于您的示例,这将为您提供上述两个子元素,以及newline / indentation text()节点。

但是,如果您想要子节点而不是他们的子节点(即只有span元素,但没有子元素),则必须使用两个表达式:

  1. 通过*/*
  2. 选择直接子元素
  3. 处理这些子元素,并通过text()
  4. 仅选择文本节点而不是孙子元素

    我的PHP有点生疏,但应该有点像这样:

    $doc = new DOMDocument;
    // set up $doc
    $xpath = new DOMXPath($doc);
    
    // perform step #1
    $childElements = $xpath->query('*/*');
    
    $directChildren = array();
    foreach ($childElements as $child) {
      // perform step #2
      $textChildren = $xpath->query('text()', $child);
      foreach ($textChildren as $text) {
        $directChildren[] = $text;
      }
    }
    // now, $directChildren contains all text nodes