假设我有这个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();
答案 0 :(得分:1)
你可以用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();
在此处查看原始解决方案: Remove empty tags from a XML with PHP
答案 1 :(得分:0)
另一个答案中的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>