Обнаружение пустого узла XML с помощью PHP SimpleXML
Позвольте мне начать с того, что я не очень разбираюсь в разборе XML и / или написании PHP. Я изучал и собирал вещи вместе для того, над чем я работаю, но я застрял.
Я пытаюсь создать базовый оператор if/else: если узел не пустой, напишите содержимое узла.
Вот фрагмент XML-кода, который я называю:
<channel>
<item>
<title>This is a test</title>
<link />
<description>Test description</description>
<category>Test category</category>
<guid />
</item>
</channel>
а вот и PHP, который у меня пока есть:
<?php
$alerts = simplexml_load_file('example.xml');
$guid = $alerts->channel->item->guid;
if ($guid->count() == 0) {
print "// No alert";
}
else {
echo "<div class='emergency-alert'>".$guid."</div>";
}
?>
Очевидно, "guid" - это пустой узел, но он возвращает:
<div class="emergency-alert"> </div>
Что я делаю неправильно?:(
PS, я пробовал hasChildren(), и это тоже не сработало.
3 ответа
@Wrikken прав. XPath является предпочтительным способом запроса документов XML. Но, отвечая на ваш вопрос, в вашем простом случае вы можете проверить, является ли значение узла пустым, приведя SimpleXMLElement к строке:
if ( !$guid->__toString() ) {
print "No alert";
}
В PHP элемент SimpleXMLElement, представляющий пустой элемент XML (самозакрывающийся тег или пустую пару тегов открытия / закрытия без содержимого), приводит к логическому значению FALSE
, Это, возможно, немного неожиданно, так как обычно каждый объект в PHP приводится к логическому TRUE
:
var_dump((bool) new SimpleXMLElement("<guid/>")); # bool(false)
var_dump((bool) new SimpleXMLElement("<guid></guid>")); # bool(false)
var_dump((bool) new SimpleXMLElement("<guid> </guid>")); # bool(true)
Это специальное правило задокументировано в руководстве PHP по преобразованию в логическое значение.
Вы можете использовать это, чтобы проверить, действительно ли <guid>
элемент у вас пуст. Однако, здесь важно, вы спрашиваете об элементе конкретно. В вашем существующем коде:
$guid = $alerts->channel->item->guid;
вы не просите конкретный <guid>
элемент, но для всех, которые являются потомками родителя <item>
элемент. Такого рода объекты SimpleXMLElement приводятся к логическому значению true, если они не содержат нулевых элементов (сравните с вашим использованием SimpleXMLElement::count()
).
Отличается от этого, если вы получите первый <guid>
элемент за индексом, вы получите SimpleXMLElement этого индекса или NULL
в случае, если элемент не существует (это означает, что нет <guid>
элемент).
Оба - несуществующий элемент как NULL
или существующий, пустой - приведёт к логическому false
который может быть легко использован в вашем операторе if/else:
$guid = $alerts->channel->item->guid[0];
### zero is the index of the first element
if ((bool) $guid) {
# non-empty, existing <guid> element
} else {
# empty or non-existing
}
Это тогда отвечает на ваш вопрос.
foreach($alerts->xpath("//item/guid[normalize-space(.)!='']") as $guid){
echo "<div class='emergency-alert'>".$guid."</div>";
}
Что оно делает?
- xpath: простой способ запроса XML-документов
- normalize-space: строка аргумента с удаленными начальными, конечными и повторяющимися пробелами (то есть:
<guid> </guid>
это не пустая строка, это' '
, но этот превращает его в''
.
это текстовое содержимое узла