2011-09-07 58 views
5

¿Cómo puedo eliminar todos los caracteres de espaciado antes y después de un campo XML?Eliminar espacios iniciales y finales de los elementos XML

<data version="2.0"> 

    <field> 

    1 

    </field>   

    <field something=" some attribute here... "> 

    2 

    </field> 

</data> 

Tenga en cuenta que el espaciado antes de 1 y 2 y 'algún atributo aquí ...', quiero eliminar eso con PHP.

if(($xml = simplexml_load_file($file)) === false) die(); 

print_r($xml); 

Además, los datos no parecen ser cadenas, tengo que anexar (cadenas) antes de cada variable. ¿Por qué?

+1

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

Respuesta

1

Desde simplexml_load_file() lee los datos en una matriz, se podría hacer algo como esto:

function TrimArray($input){ 

    if (!is_array($input)) 
     return trim($input); 

    return array_map('TrimArray', $input); 
} 
+0

No, no lee datos en una matriz, pero crea un ** SimpleXMLElement ** fuera de ella. Y ese objeto puede ser mayúscula y minúscula (que es lo que sucede cuando llamas 'trim' sobre él). – hakre

1

Es posible que desee usar algo como esto:

$str = file_get_contents($file); 
$str = preg_replace('~\s*(<([^>]*)>[^<]*</\2>|<[^>]*>)\s*~','$1',$str); 
$xml = simplexml_load_string($xml,'SimpleXMLElement', LIBXML_NOCDATA); 

No he probado esto, pero Puede encontrar más sobre esto en http://www.lonhosford.com/lonblog/2011/01/07/php-simplexml-load-xml-file-preserve-cdata-remove-whitespace-between-nodes-and-return-json/.

Tenga en cuenta que los espacios entre los paréntesis de apertura y cierre (<x> _space_ </x>) y los atributos (<x attr=" _space_ ">) son en realidad parte de los datos del documento XML (en contraste con los espacios entre <x> _space_ <y>), lo que sugiere que la fuente que utiliza debería ser un poco menos complicado con espacios.

0

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(); 
Cuestiones relacionadas