Удалить пустые элементы из XML в Stack Overflow

Скажем, у меня есть этот XML, и мне нужно удалить пустые элементы (элементы, которые вообще не содержат данных), такие как:

...
<date>
<!-- keep oneDay -->
<oneDay>
<startDate>1450288800000</startDate>
<endDate>1449086400000</endDate>
</oneDay>
<!-- remove range entirely -->
<range>
<startDate/>
<endDate/>
</range>
<!-- remove deadline entirely -->
<deadline>
<date/>
</deadline>
<data>
...

Вывод тогда должен быть

...
<oneDay>
<startDate>1450288800000</startDate>
<endDate>1449086400000</endDate>
</oneDay>
...

Я ищу динамическое решение, которое будет работать в любых случаях, как это, независимо от буквального имени элемента.

РЕШЕНИЕ (ОБНОВЛЕНО)

Оказывается, используя //*[not(normalize-space())] возвращается все элементы без непустого текстового содержимого (нет необходимости в рекурсии).

foreach($xpath->query('//*[not(normalize-space())]') as $node ) {
$node->parentNode->removeChild($node);
}

Проверять, выписываться Решение @ har07 Больше подробностей

РЕШЕНИЕ

Подход xPath, предоставляемый @manuelbc, работает, но только для дочерних элементов (это означает, что дочерние элементы исчезнут, но их родительские узлы также останутся … пустыми).

Однако это будет работать рекурсивно, пока в XML-документе нет пустых узлов.

$doc = new DOMDocument;
$doc->preserveWhiteSpace = false;
$doc->loadxml('<XML STRING GOES HERE>');

$xpath = new DOMXPath($doc);

while (($notNodes = $xpath->query('//*[not(node())]')) && ($notNodes->length)) {
foreach($notNodes as $node) {
$node->parentNode->removeChild($node);
}
}

$doc->formatOutput = true;
echo $doc->saveXML();

2

Решение

XPath в другом ответе только возвращает пустые элементы в том смысле, что элемент не имеет никакого дочернего узла (нет узла элемента, нет текстового узла, ничего). Чтобы получить все пустые элементы согласно вашему определению, это элемент без непустого текстового содержимого, попробуйте вместо этого использовать следующий XPath:

//*[not(normalize-space())]

eval.in demo

выход :

<?xml version="1.0"?>
<data>
<!-- keep oneDay -->
<oneDay>
<startDate>1450288800000</startDate>
<endDate>1449086400000</endDate>
</oneDay>
<!-- remove range entirely -->
<!-- remove deadline entirely -->
</data>
0

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

Вы можете сделать это с XPath

<?php
$doc = new DOMDocument;
$doc->preserveWhiteSpace = false;
$doc->loadxml('<date>
<!-- keep oneDay -->
<oneDay>
<startDate>1450288800000</startDate>
<endDate>1449086400000</endDate>
</oneDay>
<!-- remove range entirely -->
<range>
<startDate/>
<endDate/>
</range>
<!-- remove deadline entirely -->
<deadline>
<date/>
</deadline>
<data>');

$xpath = new DOMXPath($doc);

foreach( $xpath->query('//*[not(node())]') as $node ) {
$node->parentNode->removeChild($node);
}

$doc->formatOutput = true;
echo $doc->savexml();

Смотрите оригинальное решение здесь:
Удалить пустые теги из XML с помощью PHP

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector