Pregunta

Tengo que analizar provista externamente XML que tiene atributos con saltos de línea en ellos. Usando SimpleXML, los saltos de línea parecen estar perdido. De acuerdo con otra pregunta stackoverflow , saltos de línea debe ser válida ( aunque mucho menos que ideal!) para XML.

¿Por qué se perdieron? [Editar] ¿Y cómo puedo conservarlos? [/ editar]

Este es un script archivo de demostración (tenga en cuenta que cuando los saltos de línea no están en un atributo que se conservan).

archivo PHP con XML incrustado

$xml = <<<XML
<?xml version="1.0" encoding="utf-8"?>
<Rows>
    <data Title='Data Title' Remarks='First line of the row.
Followed by the second line.
Even a third!' />
    <data Title='Full Title' Remarks='None really'>First line of the row.
Followed by the second line.
Even a third!</data>
</Rows>
XML;

$xml = new SimpleXMLElement( $xml );
print '<pre>'; print_r($xml); print '</pre>';

salida de print_r

SimpleXMLElement Object
(
    [data] => Array
        (
            [0] => SimpleXMLElement Object
                (
                    [@attributes] => Array
                        (
                            [Title] => Data Title
                            [Remarks] => First line of the row. Followed by the second line. Even a third!
                        )

                )

            [1] => First line of the row.
Followed by the second line.
Even a third!
        )

)
¿Fue útil?

Solución

La entidad para una nueva línea es &#10;. He jugado con su código hasta que encontré algo que hizo el truco. No es muy elegante, te lo advierto:

//First remove any indentations:
$xml = str_replace("     ","", $xml);
$xml = str_replace("\t","", $xml);

//Next replace unify all new-lines into unix LF:
$xml = str_replace("\r","\n", $xml);
$xml = str_replace("\n\n","\n", $xml);

//Next replace all new lines with the unicode:
$xml = str_replace("\n","&#10;", $xml);

Finally, replace any new line entities between >< with a new line:
$xml = str_replace(">&#10;<",">\n<", $xml);

El supuesto, en función de su ejemplo, es que las nuevas líneas que se producen dentro de un nodo o atributo tendrán más texto en la siguiente línea, no un < para abrir un nuevo elemento.

Por supuesto, esto sería un fracaso si su próxima línea tenía un poco de texto que estaba envuelto en un elemento a nivel de línea.

Otros consejos

  

Usando SimpleXML, los saltos de línea parecen estar perdido.

Sí, que se espera ... de hecho se requiere de cualquier analizador XML conformes que los saltos de línea en los valores de atributos representan espacios simples. Ver normalización valor del atributo en la especificación XML.

Si no se suponía que era un verdadero carácter de nueva línea en el valor de atributo, el XML debería haber incluido una referencia de carácter &#10; en lugar de una nueva línea prima.

Suponiendo $ xmlData es su cadena XML antes de ser enviada al analizador, esto debe reemplazar todos los saltos de línea en los atributos con la entidad correcta. Tuve el problema con XML procedentes de SQL Server.

$parts = explode("<", $xmlData); //split over <
array_shift($parts); //remove the blank array element
$newParts = array(); //create array for storing new parts
foreach($parts as $p)
{
    list($attr,$other) = explode(">", $p, 2); //get attribute data into $attr
    $attr = str_replace("\r\n", "&#10;", $attr); //do the replacement
    $newParts[] = $attr.">".$other; // put parts back together
}
$xmlData = "<".implode("<", $newParts); // put parts back together prefixing with <

Probablemente se puede hacer más simple con una expresión regular, pero eso no es un punto fuerte para mí.

Este es el código para reemplazar las nuevas líneas con el carácter de referencia apropiado en ese fragmento de XML en particular. Ejecutar este código antes de analizar.

$replaceFunction = function ($matches) {
    return str_replace("\n", "&#10;", $matches[0]);
};
$xml = preg_replace_callback(
    "/<data Title='[^']+' Remarks='[^']+'/i",
    $replaceFunction, $xml);

Esto es lo que funcionó para mí:

En primer lugar, obtener el código XML como una cadena:

    $xml = file_get_contents($urlXml);

A continuación, realice la sustitución:

    $xml = str_replace(".\xe2\x80\xa9<as:eol/>",".\n\n<as:eol/>",$xml);

El "" y "" estaban allí porque tenía que añadir saltos en ese caso. Las nuevas líneas "\ n" puede ser reemplazado con lo que quiera.

Después de reemplazar, simplemente carga el xml-cadena como un objeto SimpleXMLElement:

    $xmlo = new SimpleXMLElement( $xml );

Et Voilà

Bueno, esta pregunta es viejo, pero como yo, alguien podría venir a esta página con el tiempo. Tenía enfoque ligeramente diferente y creo que el más elegante de estos mencionados.

Dentro de la xml, poner un poco de palabra única que va a utilizar para la nueva línea.

Cambiar xml para

<data Title='Data Title' Remarks='First line of the row. \n
Followed by the second line. \n
Even a third!' />

Y luego, cuando llegue a la ruta deseada en el nodo SimpleXML en cadena de salida escribir algo como esto:

$findme  = '\n';
$pos = strpos($output, $findme);
if($pos!=0)
{
$output = str_replace("\n","<br/>",$output);

No tiene que ser '\ n, que puede ser cualquier carbón único.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top