Aby to zrobić w PHP musisz najpierw przekonwertować dokument w DOMDocument tak, że można zająć się węzły, które chcesz normalizować białe znaki w prawidłowo poprzez DOMXPath. (Xpath in) SimpleXMLElement jest zbyt ograniczony, aby uzyskać dostęp do węzłów tekstowych na tyle precyzyjnie, jak byłby potrzebny w tej operacji.
XPath-query dostęp do wszystkich tekstowych węzły, które są w zasięgu liści elementów i wszystkie atrybuty to:
//*[not(*)]/text() | //@*
Zważywszy, że $xml
jest SimpleXMLElement można zrobić white-space normalizację jak w Poniższy przykład:
$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), ' ');
}
można to może rozciągnąć na wszystkie węzły tekstowe (as suggested in related Q&A), ale może to wymagać dokumentów normalizację pod okoliczności. Ponieważ text()
w Xpath nie różni się między węzłami tekstowymi i Cdata, możesz pominąć te typy węzłów (DOMCdataSection) lub rozwinąć je do węzłów tekstowych podczas ładowania dokumentu (użyj do tego celu the LIBXML_NOCDATA
option), aby uzyskać bardziej przydatne wyniki.
również nie wydaje się być dane ciąg, muszę dołączyć (string) przed każdą zmienną. Czemu?
Bo to obiekt typu SimpleXMLElement, jeśli chcesz wartość ciągu takiego obiektu (element), trzeba oddać go do łańcucha.Patrz także następujące pytanie Numer referencyjny:
I last but not least: nie ufaj print_r
lub var_dump
podczas używania go na SimpleXMLElement: to nie wykazujące prawda. Na przykład. można zastąpić __toString()
który może również rozwiązać problem:
class TrimXMLElement extends SimpleXMLElement
{
public function __toString()
{
return trim(preg_replace('~\s+~u', ' ', parent::__toString()), ' ');
}
}
$xml = simplexml_load_string($buffer, 'TrimXMLElement');
print_r($xml);
Nawet odlewania ciąg normalnie stosuje się (na przykład z echo
), wyjście print_r
nadal nie odzwierciedlać te zmiany. Lepiej nie polegać na tym, nigdy nie może pokazać całego obrazu.
Pełny przykład kodu do tej odpowiedzi (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();
zobacz moją odpowiedź na http://stackoverflow.com/questions/8200582/remove-newline-from-xml-element- value/8200664 # 8200664 dla możliwego rozwiązania – Gordon