2009-01-06 8 views
66

Digamos que tengo un poco de XML como estoForzar a un objeto SimpleXML en una cadena, independientemente del contexto

<channel> 
    <item> 
    <title>This is title 1</title> 
    </item> 
</channel> 

El código siguiente hace lo que yo quiero en la que se emite el título como una cadena

$xml = simplexml_load_string($xmlstring); 
echo $xml->channel->item->title; 

Aquí está mi problema. El código siguiente no trata el título como una cadena en ese contexto, así que termino con un objeto SimpleXML en la matriz en lugar de una cadena.

$foo = array($xml->channel->item->title); 

He estado trabajando alrededor de él como esto

$foo = array(sprintf("%s",$xml->channel->item->title)); 

pero que parece fea.

¿Cuál es la mejor manera de forzar un objeto SimpleXML a una cadena, independientemente del contexto?

+0

He presentado varias solicitudes de PHP para implementar algo similar a SOAP_SINGLE_ELEMENT_ARRAYS para esto, y animaría a otros a hacer lo mismo. SOAP_SINGLE_ELEMENT_ARRAYS fuerza a los elementos que/podrían/​​mantienen más de una cadena a analizarse siempre como solo cadenas. Por supuesto, como otros mencionaron, necesita saber lo que está recibiendo, pero una y otra vez me he encontrado con problemas con los servidores .NET SOAP que el WSDL (por defecto "mágico" de .NET) prototiparon cada cadena como mezclado o una variedad de cadenas. En lugar de current() 'ing o typecasting, el bit simplemente devuelve una cadena – conrad10781

Respuesta

134

Typecast la SimpleXMLObject en una cadena:

$foo = array((string) $xml->channel->item->title); 

El código anterior llama internamente __toString() en el SimpleXMLObject. Este método no está disponible públicamente, ya que interfiere con el esquema de asignación de SimpleXMLObject, pero aún se puede invocar de la manera anterior.

+0

Eso es más limpio que usar un sprintf. Me gusta –

+5

Tenga en cuenta que el uso de una función que acepte argumentos de cadena automáticamente hará este tipo de conversión (por ejemplo, echo, str_replace, substr). – Ross

+0

Gracias Aron, pensé que una forma de hacer el tictac era la forma de hacerlo, pero no me parecía bien. Ahora que sé que el método _toString es privado, tiene sentido. –

15

Usted puede utilizar la función de PHP

strval(); 

Esta función devuelve los valores de cadena del parámetro que se le pasa.

+1

Desafortunadamente strval() no funciona en matrices u objetos. –

+3

@Mark Biek: Funciona en objetos que tienen '__toString()' implementado y especialmente en este caso de preguntas en específico, funciona muy bien con objetos de tipo 'SimpleXMLElement'. Puedes compararlo con el molde de 'cadena' en la respuesta aceptada. 'strval()' es una función de devolución de llamada útil a menudo junto con ['array_map()'] (http://php.net/array_map) y ['iterator_to_array ($ simpleXMLElement, false)'] (http: // php .net/iterator_to_array) o 'SimpleXMLElement :: xpath()'. – hakre

2

para obtener los datos XML en una matriz de php hacer esto:

// this gets all the outer levels into an associative php array 
$header = array(); 
foreach($xml->children() as $child) 
{ 
    $header[$child->getName()] = sprintf("%s", $child); 
} 
echo "<pre>\n"; 
print_r($header); 
echo "</pre>"; 

conseguir a un niño del niño luego simplemente hacer esto:

$data = array(); 
foreach($xml->data->children() as $child) 
{ 
    $header[$child->getName()] = sprintf("%s", $child); 
} 
echo "<pre>\n"; 
print_r($data); 
echo "</pre>"; 

pueden ampliar $ xml-> través de cada nivel hasta que obtenga lo que quiere También puede poner todos los nodos en una matriz sin los niveles o casi de cualquier otra forma que desee.

3

Otra forma fea de hacerlo:

$foo = array($xml->channel->item->title.""); 

Funciona, pero no es bastante.

9

Hay método SimpleXML nativa SimpleXMLElement::asXML En función del parámetro que escribe SimpleXMLElement a XML 1.0 archivo o simplemente en una cadena:

$xml = new SimpleXMLElement($string); 
$validfilename = '/temp/mylist.xml'; 
$xml->asXML($validfilename); // to a file 
echo $xml->asXML();    // to a string 
1

La respuesta aceptada en realidad devuelve una matriz que contiene una cadena, que no es exactamente qué OP solicitó (una cadena). Para ampliar esa respuesta, utilice:

$foo = [ (string) $xml->channel->item->title ][0]; 

que devuelve el único elemento de la matriz, una cadena.

1

strval Try ($ xml-> canal-> Item-> título)

0

La siguiente es una función recursiva que encasillado todos los elementos de un solo niño a un String:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
// FUNCTION - CLEAN SIMPLE XML OBJECT 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
function cleanSimpleXML($xmlObject = ''){ 

    // LOOP CHILDREN 
    foreach ($xmlObject->children() as $child) { 

     // IF CONTAINS MULTIPLE CHILDREN 
     if(count($child->children()) > 1){ 

      // RECURSE 
      $child = cleanSimpleXML($child); 

     }else{ 

      // CAST 
      $child = (string)$child; 

     } 

    } 

    // RETURN CLEAN OBJECT 
    return $xmlObject; 

} // END FUNCTION 
0
No

Seguro si cambiaron la visibilidad del método __toString() ya que la respuesta aceptada fue escrito, pero en este momento funciona bien para mí:

var_dump($xml->channel->item->title->__toString()); 

SALIDA:

string(15) "This is title 1" 
Cuestiones relacionadas