首先让我们定义"终端元素"(用于本问题的特定目的)。
我所说的"终端元素"是指内部不包含其他元素的元件。
元素参考:http://www.w3schools.com/xml/xml_elements.asp
如何使用PHP从XML文档/节点中删除"终端元素"之外的所有空白(换行符、回车符、制表符和空格)?
规则:只有PHP本机XML解析器(没有正则表达式)。
"终端元素"(叶元素节点)外的所有空白都在文本节点内(因为所有文本都在文本结点内)。因此,如果获得了终端元素之外的所有文本节点,就可以从这些节点中删除所有空白字符。这已经是答案了。
让我们简单地从XML文档中的一个文本节点中删除空白开始。
由于PHP使用UTF-8作为XML解析器的字符编码(在本例中我使用DOMDocument),preg_replace
在这里很方便,因为它知道UTF-8和空白字符是什么:
/** @var DomText $text */
$text->nodeValue = preg_replace('~'s+~u', '', $text->textContent);
这将删除文本节点中的所有空白。这是一个演示:
$doc = new DOMDocument();
$doc->loadXML('<root> Very Simple Demo </root>');
$text = $doc->documentElement->childNodes->item(0);
/** @var DomText $text */
$text->nodeValue = preg_replace('~'s+~u', '', $text->textContent);
$doc->save('php://output');
输出:
<?xml version="1.0"?>
<root>VerySimpleDemo</root>
正如您所看到的,空格字符将从该文档中唯一的文本节点中删除。
有了更大的文档和"终端元素",这自然会更有趣,但工作原理基本相同。唯一的区别是获取所有不属于叶元素节点的文本节点。这最好使用xpath查询来完成:
//*[*]/text()
内容如下:所有文本节点都是包含其他元素的元素的子节点。让我们使用以下XML(文件content.xml
)作为示例:
<?xml version="1.0"?>
<content>
<parent>
<child id="1">
<title>child 1</title>
<child id="1">
<title>
child 1.1 with whitespace
</title>
</child>
</child>
</parent>
</content>
它既包含这样的叶元素,也包含具有子元素的其他元素。它还很好地显示了用于元素缩进的空白。
加载后:
$file = __DIR__ . '/content.xml';
$doc = new DOMDocument();
$doc->load($file);
执行xpath查询需要一个DOMXPath:
$xp = new DOMXPath($doc);
$texts = $xp->query('//*[*]/text()');
剩下的就是迭代所有这些文本节点,并应用上面的空白删除:
foreach ($texts as $text) {
/** @var DomText $text */
$text->nodeValue = preg_replace('~'s+~u', '', $text->textContent);
}
结果是:
<?xml version="1.0"?>
<content><parent><child id="1"><title>child 1</title><child id="1"><title>
child 1.1 with whitespace
</title></child></child></parent></content>
这应该能回答问题。但是,如果没有更多的细节或一点"但是…",它就不会是XML
请注意,xpath中的"text()
"表示所有类型的文本节点,包括CDATA部分。如果CDATA部分仅包含空白,则上面的代码会在输出中呈现一个空的CDATA部分("<![CDATA[]]>
")。一种处理方法是从文档中删除空节点:
/** @var DomText $text */
$text->nodeValue = preg_replace('~'s+~u', '', $text->textContent);
if (!$text->length) {
$text->parentNode->removeChild($text);
}
然后,这将从文档中删除所有清空的文本节点。保持文档树的整洁。希望这能有所帮助。
DOMDocument::normalizeDocument可以满足您的需求。
如果要规范化单个元素,可以调用DOMNode::normalize