PHP DomXPath不选择空文本节点

时间:2015-03-24 19:23:05

标签: php xml xpath domxpath

我正在尝试选择不包含任何文本的节点。这段PHP代码跳过示例xml中的空节点。但是,当我尝试在线测试仪(如http://freeformatter.com/xpath-tester.html)时,它没有任何问题。

这是PHP的东西吗?

我的PHP代码:

    $path = "//RecipeSteps/RecipeStep[not(text())]";
    $stepsQuery = $this->xpath->query($path);
    $numResults = $stepsQuery->length;

我的样本xml:

<?xml version="1.0" encoding="utf-8"?>
<Recipes>
    <RecipeSteps>
      <RecipeStep number="1">Dummy content</RecipeStep>
      <RecipeStep number="2">Dummy content</RecipeStep>
      <RecipeStep number="3">Dummy content</RecipeStep>
      <RecipeStep number="4">Dummy content</RecipeStep>
      <RecipeStep number="5">Dummy content</RecipeStep>
      <RecipeStep number="6"></RecipeStep>
      <RecipeStep number="7">Variations</RecipeStep>
      <RecipeStep number="8">Some variation content..</RecipeStep>
    </RecipeSteps>
</Recipes>

3 个答案:

答案 0 :(得分:1)

如果您正在寻找XPATH解决方案,请使用//RecipeSteps/(RecipeStep[string-length() = 0])。 e.g

$path = "//RecipeSteps/(RecipeStep[string-length() = 0])";
$stepsQuery = $this->xpath->query($path);
$numResults = $stepsQuery->length;

答案 1 :(得分:0)

选择完整路径时,它可以工作:

$xmlString = '<?xml version="1.0" encoding="utf-8"?>
<Recipes>
    <RecipeSteps>
      <RecipeStep number="1">Dummy content</RecipeStep>
      <RecipeStep number="2">Dummy content</RecipeStep>
      <RecipeStep number="3">Dummy content</RecipeStep>
      <RecipeStep number="4">Dummy content</RecipeStep>
      <RecipeStep number="5">Dummy content</RecipeStep>
      <RecipeStep number="6"></RecipeStep>
      <RecipeStep number="7">Variations</RecipeStep>
      <RecipeStep number="8">Some variation content..</RecipeStep>
    </RecipeSteps>
</Recipes>';

$dom = new DOMDocument();
$dom->loadXML($xmlString);
$xpath = new DOMXpath($dom);
# it works also well: //RecipeSteps/RecipeStep[not(text())]
$query = $xpath->query('//Recipes/RecipeSteps/RecipeStep[not(text())]');
//returns "6"
print 'RecipeStep number: ' . $query->item(0)->getAttribute('number');

另外,选择“//RecipeSteps/RecipeStep[not(text())]”也很有魅力。所以很可能你做错了什么。

答案 2 :(得分:0)

路径表达式//RecipeStep[not(text())]//RecipeStep[string-length() = 0]并不一样,但是将您展示的文档作为输入,它们会返回完全相同的。在这两种情况下,都会选择一个RecipeStep节点作为结果:

<RecipeStep number="6"/>

//RecipeStep[not(text())]表示简单的英语:

  

在文档中的任何位置选择名为RecipeStep的元素节点,但前提是它们没有任何直接的子文本节点。

另一方面,//RecipeStep[string-length() = 0]表示

  

在文档中的任何位置选择名为RecipeStep的元素节点,但前提是它们的字符串值(所有后代文本节点的串联)的长度等于0。

只有当配方步骤6实际上看起来像

时才会出现差异
<RecipeStep number="6"><child>text</child></RecipeStep>

然后,//RecipeStep[not(text())]仍会选择此节点,而//RecipeStep[string-length() = 0]则不会返回任何内容。

(并且只是为了说清楚:我省略的前导//RecipeSteps不会改变任何东西。)

因此,您的原始XPath表达式是正确的 - 并且接受的答案与原始答案完全相同。 XPath在这里没有错。