【发布时间】:2015-12-02 21:39:02
【问题描述】:
假设我有这个 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's solution了解更多详情
解决方案
@manuelbc 提供的 xPath 方法有效,但仅适用于子元素(这意味着子元素将消失,但它们的父节点将保持...为空)。
但是,这将递归地工作,直到 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();
【问题讨论】: