xml — PHP 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>

0

Решение

Если вы ищете решение XPATH, используйте //RecipeSteps/(RecipeStep[string-length() = 0]),
например

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

Другие решения

При выборе полного пути это работает:

$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())]«работает как шарм также хорошо. Так что, скорее всего, вы делаете что-то не так.

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 здесь не виноват.

0
По вопросам рекламы [email protected]