PHP& XML:如何删除“终端元素”之外的所有空格

时间:2014-09-05 22:38:21

标签: php xml

首先让我们定义"终端元素" (出于这个问题的特殊目的)。

通过"终端元素"我的意思是元素里面没有其他元素

元素参考:http://www.w3schools.com/xml/xml_elements.asp

如何从XML文档/节点中移除所有空格(换行符,回车符,制表符和空格)以及"终端元素"用PHP?

规则:仅PHP本机XML解析器(无正则表达式)。

2 个答案:

答案 0 :(得分:3)

“终端元素”(叶元素节点)之外的所有空格都在文本节点内(因为所有文本都在文本节点内)。因此,如果您获得了终端元素之外的所有文本节点,则可以从中删除所有空白字符。这已经是答案了。

让我们从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-query需要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);
}
然后,

然后从文档中删除所有清空的文本节点。保持文档树整洁。希望这会有所帮助。

答案 1 :(得分:0)

DOMDocument::normalizeDocument可以做你想要的。

如果要标准化各个元素,可以调用DOMNode::normalize