要做到這一點在PHP中,你首先必須將文檔轉換爲的DOMDocument,這樣就可以解決你想通過DOMXPath正常化內適當的空白節點。 (xpath in)SimpleXMLElement太有限,無法精確地訪問文本節點,因爲它需要執行此操作。
一個XPath查詢訪問所有文本節點是葉元素內的所有屬性是:
//*[not(*)]/text() | //@*
鑑於$xml
是的SimpleXMLElement,你可以做空白正常化像下面的例子:
$doc = dom_import_simplexml($xml)->ownerDocument;
$xpath = new DOMXPath($doc);
foreach ($xpath->query('//*[not(*)]/text()|//@*') as $node) {
/** @var $node DOMText|DOMAttr */
$node->nodeValue = trim(preg_replace('~\s+~u', ' ', $node->nodeValue), ' ');
}
也許你可以舒展這所有文本節點(as suggested in related Q&A),但是這可能需要根據情況的文件正常化。由於Xpath中的text()
在文本節點和Cdata節之間沒有區別,因此在加載文檔時可能需要跳過這些類型的節點(DOMCdataSection)或將它們展開到文本節點中(爲此使用the LIBXML_NOCDATA
option)以實現更有用結果。
另外的數據不顯示爲字符串,我需要每個變量之前要追加(字符串)。爲什麼?
因爲它是類型的SimpleXMLElement的對象,如果你想這樣的對象(元素)的字符串值,則需要將其轉換爲字符串。見還有以下參考問題:
最後但並非最不重要的:當您使用它在的SimpleXMLElement不信任print_r
或var_dump
:它沒有顯示真相。例如。你可以覆蓋__toString()
這也可以解決您的問題:
class TrimXMLElement extends SimpleXMLElement
{
public function __toString()
{
return trim(preg_replace('~\s+~u', ' ', parent::__toString()), ' ');
}
}
$xml = simplexml_load_string($buffer, 'TrimXMLElement');
print_r($xml);
即使轉換爲String通常會應用(例如用echo
)的print_r
輸出仍然不會反映這些變化。所以最好不要依賴它,它永遠不能顯示整個圖像。
完整的示例代碼,這個答案(Online Demo):
<?php
/**
* Remove starting and ending spaces from XML elements
*
* @link https://stackoverflow.com/a/31793566/367456
*/
$buffer = <<<XML
<data version="2.0">
<field>
1
</field>
<field something=" some attribute here... ">
2 <![CDATA[ 34 ]]>
</field>
</data>
XML;
class TrimXMLElement extends SimpleXMLElement implements JsonSerializable
{
public function __toString()
{
return trim(preg_replace('~\s+~u', ' ', parent::__toString()), ' ');
}
function jsonSerialize()
{
$array = (array) $this;
array_walk_recursive($array, function(&$value) {
if (is_string($value)) {
$value = trim(preg_replace('~\s+~u', ' ', $value), ' ');
}
});
return $array;
}
}
$xml = simplexml_load_string($buffer, 'TrimXMLElement', LIBXML_NOCDATA);
print_r($xml);
echo json_encode($xml);
$xml = simplexml_load_string($buffer, null, LIBXML_NOCDATA);
$doc = dom_import_simplexml($xml)->ownerDocument;
$doc->normalizeDocument();
$doc->normalize();
$xpath = new DOMXPath($doc);
foreach ($xpath->query('//*[not(*)]/text()|//@*') as $node) {
/** @var $node DOMText|DOMAttr|DOMCdataSection */
if ($node instanceof DOMCdataSection) {
continue;
}
$node->nodeValue = trim(preg_replace('~\s+~u', ' ', $node->nodeValue), ' ');
}
echo $xml->asXML();
請參閱我的答案在http://stackoverflow.com/questions/8200582/remove-newline-from-xml-element-值/ 8200664#8200664可能的解決方案 – Gordon