2011-12-19 16 views
7

Potrzebuję zwrócić obiekt SimpleXML przekonwertowany jako obiekt JSON do pracy z nim w JavaScript. Problem polega na tym, że nie ma żadnych atrybutów na żadnym obiekcie z wartością.Znikające atrybuty w PHP SimpleXML Object?

Jako przykład:

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

staje się w obiekcie SimpleXML:

"customer":"69236" 

Gdy obiektem @attributes?

Odpowiedz

-1

Oto kod do iterowania atrybutów i konstruowania JSON. Jeśli obsługuje, jeden lub wielu klientów.

Jeśli XML wygląda następująco (lub tylko jednego klienta)

<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> 

iterację tym tak.

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/>"; 
} 

celu wytworzenia struktury JSON jak ten

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

Wreszcie, w skrypcie, dostęp do atrybutu jak to

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

Powodzenia

7

ten prowadził mnie do szału przy kilku okazjach. Kiedy SimpleXML napotka na węzeł, który ma tylko wartość tekstową, odrzuca wszystkie atrybuty. Moim rozwiązaniem było zmodyfikowanie kodu XML przed analizą za pomocą SimpleXML. W przypadku niektórych wyrażeń regularnych można utworzyć węzeł podrzędny zawierający rzeczywistą wartość tekstową. Na przykład w danej sytuacji można zmienić XML do:

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

jakiś przykład kodu, zakładając, że ciąg XML był w $ str:

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

To by zachować atrybuty i gniazdem wartość tekstową w węźle podrzędnym.

+1

ten nie działa, jeśli nie jest na przykład blok CDATA w elemencie, tak jak poniżej:

+0

Dla mnie rozwiązaniem było jawne wywołanie '-> children()' podczas zapętlania obiektu xml. Jeśli nie, atrybuty zniknęły. –

3

Zdaję sobie sprawę, że jest to stary post, ale w przypadku, gdy okaże się przydatny. Poniżej znajduje się rozszerzenie rozwiązania @ ryanmcdonnell do pracy na dowolnych tagach zamiast na sztywno zakodowanym znaczniku. Mam nadzieję, że to komuś pomaga.

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

Głównym inna jest to, że zastępuje /<customer z /<([^ ]+), a następnie </customer> z </\\1>

który mówi mu, aby dopasować tę część poszukiwania przeciw pierwszego elementu w strukturze.

Następnie dostosowuje symbole zastępcze ($1, $2, $3) w celu uwzględnienia faktu, że obecnie istnieją trzy sub-dopasowania zamiast dwóch.

+1

To również nie działa, jeśli w elemencie jest na przykład blok CDATA, na przykład:

0

To stare pytanie, ale znalazłem coś, co działa zgrabnie - parsuj je w obiekcie DOMNode.

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

ukaże się:

string 'numeric'