2011-12-19 23 views
7

Necesito devolver un objeto SimpleXML convertido como un objeto JSON para trabajar con él en JavaScript. El problema es que no hay atributos en ningún objeto con un valor.Atributos de desaparición en PHP Objeto SimpleXML?

A modo de ejemplo:

<customer editable="true" maxChars="9" valueType="numeric">69236</customer> 

se convierte en el objeto SimpleXML:

"customer":"69236" 

¿Dónde está el objeto @attributes?

Respuesta

-1

Aquí hay algunos códigos para recorrer los atributos y construir JSON. Si es compatible, uno o muchos clientes.

Si eres XML es el siguiente (o un solo cliente)

<xml> 
<customer editable="true" maxChars="9" valueType="numeric">69236</customer> 
<customer editable="true" maxChars="9" valueType="numeric">12345</customer> 
<customer editable="true" maxChars="9" valueType="numeric">67890</customer> 
</xml> 

Iterar a través de él de esta manera.

try { 
    $xml = simplexml_load_file("customer.xml"); 

    // Find the customer 
    $result = $xml->xpath('/xml/customer'); 

    $bFirstElement = true; 
    echo  "var customers = {\r\n"; 
    while(list(, $node) = each($result)) { 
     if($bFirstElement) { 
      echo "'". $node."':{\r\n"; 
      $bFirstElement = false; 
     } else { 
      echo ",\r\n'". $node."':{\r\n"; 
     } 

     $bFirstAtt = true; 
     foreach($node->attributes() as $a => $b) { 
      if($bFirstAtt) { 
       echo "\t".$a.":'".$b."'"; 
       $bFirstAtt = false; 
      } else { 
       echo ",\r\n\t".$a.":'".$b."'"; 
      } 
     } 
     echo "}"; 
    } 
    echo "\r\n};\r\n"; 
} catch(Exception $e) { 
    echo "Exception on line ".$e->getLine()." of file ".$e->getFile()." : ".$e->getMessage()."<br/>"; 
} 

para producir una estructura JSON como esto

var customers = { 
'69236':{ 
    editable:'true', 
    maxChars:'9', 
    valueType:'numeric'}, 
'12345':{ 
    editable:'true', 
    maxChars:'9', 
    valueType:'numeric'}, 
'67890':{ 
    editable:'true', 
    maxChars:'9', 
    valueType:'numeric'} 
}; 

Por último, en el script, acceder al atributo como esto

WScript.Echo(customers["12345"].editable); 

Buena suerte

7

Esto me ha vuelto loco en varias ocasiones. Cuando SimpleXML encuentra un nodo que solo tiene un valor de texto, descarta todos los atributos. Mi solución ha sido modificar el XML antes de analizar con SimpleXML. Con un poco de expresiones regulares, puede crear un nodo secundario que contenga el valor de texto real. Por ejemplo, en su situación puede cambiar el XML para:

<customer editable="true" maxChars="9" valueType="numeric"><value>69236<value></customer> 

un código de ejemplo, suponiendo que su cadena XML estaba en $ str:

$str = preg_replace('/<customer ([^>]*)>([^<>]*)<\/customer>/i', '<customer $1><value>$2</value></customer>', $str); 
$xml = @simplexml_load_string($str); 

que preservaría los atributos y anidar el valor de texto en un nodo hijo.

+1

Esta falla si hay por ejemplo un bloque CDATA en el elemento, así:

+0

Para mí, la solución fue llamar explícitamente a '-> niños()' al buclear el objeto xml. Si no lo hice, los atributos desaparecieron. –

3

Me doy cuenta de que esta es una publicación anterior, pero en caso de que resulte útil. A continuación se extiende la solución de @ryanmcdonnell para trabajar en cualquier etiqueta en lugar de en una etiqueta con código fijo. Espero que ayude a alguien.

$str = preg_replace('/<([^ ]+) ([^>]*)>([^<>]*)<\/\\1>/i', '<$1 $2><value>$3</value></$1>', $result); 

La principal es diferente al que reemplaza /<customer con /<([^ ]+), y luego </customer> con </\\1>

que cuenta para que coincida con parte de la búsqueda contra el primer elemento en el patrón.

Luego, simplemente ajusta los marcadores de posición ($1, $2, $3) para dar cuenta del hecho de que ahora hay tres subclases en lugar de dos.

+1

Esto también falla si hay, por ejemplo, un bloque CDATA en el elemento, como lo siguiente:

0

Es una vieja pregunta, pero encontré algo que funciona bien: analizarlo en un objeto DOMNode.

// $customer contains the SimpleXMLElement 
$customerDom = dom_import_simplexml($customer); 
var_dump($customerDom->getAttribute('numeric')); 

mostrará:

string 'numeric' 
Cuestiones relacionadas