Forzar un objeto SimpleXML a una cadena, independientemente del contexto


78

Digamos que tengo un XML como este

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

El siguiente código hace lo que quiero, ya que genera el título como una cadena

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

Este es mi problema. El siguiente código no trata el título como una cadena en ese contexto, por lo 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 esto así

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

pero eso parece feo.

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


Envié varias solicitudes a 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 obliga a los elementos que / podrían / ​​contener 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 SOAP de .NET para los que el WSDL (por los valores predeterminados "mágicos" de .NET) hizo un prototipo de cada cadena como mixto o una matriz de cadenas. En lugar de current () 'ing o encasillado, el bit simplemente devuelve una cadena
conrad10781

Respuestas:


151

Escriba el objeto SimpleXMLO en una cadena:

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

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


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

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

3
$ foo = (cadena) $ xml-> canal-> elemento-> título; es lo que estaba buscando, ya que no necesito una matriz. Gracias.
Drazisil

1
+100 ¡acabas de hacer mi noche! Soy nuevo en SimpleXMLObject, las vars que había extraído de él estaban 'imprimiendo' bien en la pantalla pero fallando mi consulta de base de datos ... ¡suspiro! ¿Desde cuándo PHP se escribió estrictamente? ;-)
megaSteve4

1
@ megaSteve4 "¿Desde cuándo PHP se escribió estrictamente?" - es precisamente porque no es necesario que esto suceda: la mayoría de las funciones no tienen un contexto de tipo definido, por lo que no se pueden convertir implícitamente a ese tipo. Por supuesto, pueden emitir explícitamente sus parámetros de entrada, por lo que substret al funcionan. Sin embargo, es más seguro realizar la transmisión lo antes posible, para que sepa que todas las funciones verán los datos que esperan.
IMSoP

22

Puedes usar la función PHP

strval();

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


3
@Mark Biek: Sí funciona en objetos que se han __toString()implementado y sobre todo en este caso de preguntas en concreto, funciona muy bien con objetos de tipoSimpleXMLElement . Puede compararlo con el stringelenco en la respuesta aceptada. strval()es una función de devolución de llamada práctico a menudo en conjunción con array_map()y iterator_to_array($simpleXMLElement, false)o SimpleXMLElement::xpath().
hakre

9

Existe el método SimpleXML nativo SimpleXMLElement :: asXML Dependiendo del parámetro, escribe SimpleXMLElement en un archivo xml 1.0 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

Recibo una llamada a una función indefinida como XML, así que supongo que esto ya no está actualizado.
Eoin

1
@Eoin Hmm ... Acabo de probar mi ejemplo, todavía funciona bien con la instalación nativa de php 7.3
Caso mixto

Debo haber tenido un problema diferente con ellos. Mis disculpas. Solucioné mi problema ahora :)
Eoin

3

Otra forma fea de hacerlo:

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

Funciona, pero no es bonito.


3

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

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

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


2

Para obtener datos XML en una matriz php, haga 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>";

Para tener el hijo de un niño, simplemente haga esto:

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

Puede expandir $ xml-> a través de cada nivel hasta obtener lo que desea. También puede poner todos los nodos en una matriz sin los niveles o casi de cualquier otra forma que desee.



0

No estoy seguro de si cambiaron la visibilidad del __toString()método desde que se escribió la respuesta aceptada, pero en este momento funciona bien para mí:

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

SALIDA:

string(15) "This is title 1"

0

Existe un método nativo SimpleXML SimpleXMLElement :: asXML Dependiendo del parámetro, escribe SimpleXMLElement en un archivo xml 1.0, Sí

$get_file= read file from path;
$itrate1=$get_file->node;
$html  = $itrate1->richcontent->html;


echo  $itrate1->richcontent->html->body->asXML();
 print_r((string) $itrate1->richcontent->html->body->asXML());

0

Solo ponga el ''. antes de cualquier variable, se convertirá en cadena.

$ foo = array (''. $ xml-> canal-> elemento-> título);


-1

La siguiente es una función recursiva que encasillará todos los elementos de un solo hijo a 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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.