Para hacer esto en PHP primero hay que convertir el documento en un DOMDocument para que pueda hacer frente a los nodos que desea normalizar el espacio en blanco dentro adecuadamente a través de DOMXPath. El (xpath in) SimpleXMLElement es demasiado limitado para acceder a los nodos de texto con la precisión necesaria para esta operación.
un XPath-consulta para acceder a todo el texto nodos que están dentro de la hoja-elementos y los atributos es:
//*[not(*)]/text() | //@*
Dado que $xml
es una SimpleXMLElement que podría hacer la normalización de espacios en blanco como en el siguiente ejemplo:
$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), ' ');
}
tal vez podría estirar esto a todos los nodos de texto (as suggested in related Q&A), pero esto podría requerir documento de normalización bajo circunstancia. Como text()
en Xpath no difiere entre los nodos de texto y las secciones Cdata, es posible que desee omitir este tipo de nodos (DOMCdataSection) o expandirlos a nodos de texto al cargar el documento (use the LIBXML_NOCDATA
option para obtener más información) resultados.
también los datos no parece ser una cadena, que necesito para anexar (cadena) antes de cada variable. ¿Por qué?
Debido a que es un objeto de tipo SimpleXMLElement, si desea que el valor de cadena de un (elemento) tal objeto, es necesario convertirlo a cadena.Ver también la siguiente pregunta de referencia:
Y por último pero no menos importante: no confíe en print_r
o var_dump
cuando lo utiliza en un SimpleXMLElement: esto es no mostrar la verdad. P.ej. usted podría anular __toString()
que también podría resolver el problema:
class TrimXMLElement extends SimpleXMLElement
{
public function __toString()
{
return trim(preg_replace('~\s+~u', ' ', parent::__toString()), ' ');
}
}
$xml = simplexml_load_string($buffer, 'TrimXMLElement');
print_r($xml);
A pesar de conversión a String se aplican, (por ejemplo, con echo
), la salida de print_r
TODAVÍA no reflejar estos cambios. Así que mejor no confíes en él, nunca puede mostrar la imagen completa.
completo código de ejemplo a esta respuesta (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();
por favor ver mi respuesta a http://stackoverflow.com/questions/8200582/remove-newline-from-xml-element- valor/8200664 # 8200664 para una posible solución – Gordon