PHP конвертирует XML в JSON

Я пытаюсь преобразовать xml в json в php. Если я делаю простой конвертировать, используя простые xml и json_encode, ни один из атрибутов в xml-шоу.

$xml = simplexml_load_file("states.xml"); echo json_encode($xml); 

Поэтому я пытаюсь вручную разобрать его так.

 foreach($xml->children() as $state) { $states[]= array('state' => $state->name); } echo json_encode($states); 

и вывод для состояния: {"state":{"0":"Alabama"}} а не {"state":"Alabama"}

Что я делаю не так?

XML:

 <?xml version="1.0" ?> <states> <state id="AL"> <name>Alabama</name> </state> <state id="AK"> <name>Alaska</name> </state> </states> 

Вывод:

 [{"state":{"0":"Alabama"}},{"state":{"0":"Alaska"} 

var dump:

 object(SimpleXMLElement)#1 (1) { ["state"]=> array(2) { [0]=> object(SimpleXMLElement)#3 (2) { ["@attributes"]=> array(1) { ["id"]=> string(2) "AL" } ["name"]=> string(7) "Alabama" } [1]=> object(SimpleXMLElement)#2 (2) { ["@attributes"]=> array(1) { ["id"]=> string(2) "AK" } ["name"]=> string(6) "Alaska" } } } 

Json & Array из XML в трех строках:

 $xml = simplexml_load_string($xml_string); $json = json_encode($xml); $array = json_decode($json,TRUE); 

Та да!

Извините за ответ на старое сообщение, но в этой статье описывается подход, который является относительно коротким, кратким и легким в обслуживании. Я сам тестировал и работал очень хорошо.

http://lostechies.com/seanbiefeld/2011/10/21/simple-xml-to-json-with-php/

 <?php class XmlToJson { public function Parse ($url) { $fileContents= file_get_contents($url); $fileContents = str_replace(array("\n", "\r", "\t"), '', $fileContents); $fileContents = trim(str_replace('"', "'", $fileContents)); $simpleXml = simplexml_load_string($fileContents); $json = json_encode($simpleXml); return $json; } } ?> 

Я понял. json_encode обрабатывает объекты по-разному, чем строки. Я бросаю объект в строку, и теперь он работает.

 foreach($xml->children() as $state) { $states[]= array('state' => (string)$state->name); } echo json_encode($states); 

Наверное, я немного опаздываю на вечеринку, но я написал небольшую функцию для выполнения этой задачи. Он также заботится об атрибутах, текстовом содержимом и даже если несколько узлов с одним и тем же именем узла являются братьями и сестрами.

Отказ от ответственности: я не являюсь уроженцем PHP, поэтому, пожалуйста, примите простые ошибки.

 function xml2js($xmlnode) { $root = (func_num_args() > 1 ? false : true); $jsnode = array(); if (!$root) { if (count($xmlnode->attributes()) > 0){ $jsnode["$"] = array(); foreach($xmlnode->attributes() as $key => $value) $jsnode["$"][$key] = (string)$value; } $textcontent = trim((string)$xmlnode); if (count($textcontent) > 0) $jsnode["_"] = $textcontent; foreach ($xmlnode->children() as $childxmlnode) { $childname = $childxmlnode->getName(); if (!array_key_exists($childname, $jsnode)) $jsnode[$childname] = array(); array_push($jsnode[$childname], xml2js($childxmlnode, true)); } return $jsnode; } else { $nodename = $xmlnode->getName(); $jsnode[$nodename] = array(); array_push($jsnode[$nodename], xml2js($xmlnode, true)); return json_encode($jsnode); } } 

Пример использования:

 $xml = simplexml_load_file("myfile.xml"); echo xml2js($xml); 

Пример ввода (myfile.xml):

 <family name="Johnson"> <child name="John" age="5"> <toy status="old">Trooper</toy> <toy status="old">Ultrablock</toy> <toy status="new">Bike</toy> </child> </family> 

Пример вывода:

 {"family":[{"$":{"name":"Johnson"},"child":[{"$":{"name":"John","age":"5"},"toy":[{"$":{"status":"old"},"_":"Trooper"},{"$":{"status":"old"},"_":"Ultrablock"},{"$":{"status":"new"},"_":"Bike"}]}]}]} 

Довольно напечатанный:

 { "family" : [{ "$" : { "name" : "Johnson" }, "child" : [{ "$" : { "name" : "John", "age" : "5" }, "toy" : [{ "$" : { "status" : "old" }, "_" : "Trooper" }, { "$" : { "status" : "old" }, "_" : "Ultrablock" }, { "$" : { "status" : "new" }, "_" : "Bike" } ] } ] } ] } 

Привычки иметь в виду: несколько тегов с одним и тем же тэгом могут быть братьями и сестрами. Другие решения, скорее всего, оставят всех, кроме последнего брата. Чтобы избежать этого, каждый узел, даже если он имеет только один дочерний элемент, представляет собой массив, который содержит объект для каждого экземпляра тэга. (См. Несколько примеров элементов в примере)

Даже корневой элемент, из которого только один должен существовать в действительном XML-документе, хранится в виде массива с объектом экземпляра, просто чтобы иметь согласованную структуру данных.

Чтобы иметь возможность различать содержимое узла XML и атрибуты XML, атрибуты каждого объекта хранятся в «$» и содержании в «_» дочернем.

Изменить: я забыл показать результат для ваших входных данных примера

 { "states" : [{ "state" : [{ "$" : { "id" : "AL" }, "name" : [{ "_" : "Alabama" } ] }, { "$" : { "id" : "AK" }, "name" : [{ "_" : "Alaska" } ] } ] } ] } 

Попытайтесь использовать это

 $xml = ... // Xml file data // first approach $Json = json_encode(simplexml_load_string($xml)); ---------------- OR ----------------------- // second approach $Json = json_encode(simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA)); echo $Json; 

Или

Вы можете использовать эту библиотеку: https://github.com/rentpost/xml2array

Общей ошибкой является то, что json_encode() не учитывает элементы с текстовым значением и атрибутами. Он выберет один из них, что означает dataloss. Функция ниже решает эту проблему. Если вы решите пойти на путь json_encode / decode , рекомендуется использовать следующую функцию.

 function json_prepare_xml($domNode) { foreach($domNode->childNodes as $node) { if($node->hasChildNodes()) { json_prepare_xml($node); } else { if($domNode->hasAttributes() && strlen($domNode->nodeValue)){ $domNode->setAttribute("nodeValue", $node->textContent); $node->nodeValue = ""; } } } } $dom = new DOMDocument(); $dom->loadXML( file_get_contents($xmlfile) ); json_prepare_xml($dom); $sxml = simplexml_load_string( $dom->saveXML() ); $json = json_decode( json_encode( $sxml ) ); 

сделав это, <foo bar="3">Lorem</foo> не будет выглядеть как {"foo":"Lorem"} в вашем JSON.

Для этой цели я использовал TypeConverter Miles Johnson. Его можно установить с помощью Composer .

Вы можете написать что-то вроде этого, используя это:

 <?php require 'vendor/autoload.php'; use mjohnson\utility\TypeConverter; $xml = file_get_contents("file.xml"); $arr = TypeConverter::xmlToArray($xml, TypeConverter::XML_GROUP); echo json_encode($arr); 

Оптимизация ответа Антонио Макс:

 $xmlfile = 'yourfile.xml'; $xmlparser = xml_parser_create(); // open a file and read data $fp = fopen($xmlfile, 'r'); //9999999 is the length which fread stops to read. $xmldata = fread($fp, 9999999); // converting to XML $xml = simplexml_load_string($xmldata, "SimpleXMLElement", LIBXML_NOCDATA); // converting to JSON $json = json_encode($xml); $array = json_decode($json,TRUE); 

Если вы хотите преобразовать определенную часть XML в JSON, вы можете использовать XPath для извлечения этого и конвертировать его в JSON.

 <?php $file = @file_get_contents($xml_File, FILE_TEXT); $xml = new SimpleXMLElement($file); $xml_Excerpt = @$xml->xpath('/states/state[@id="AL"]')[0]; // [0] gets the node echo json_encode($xml_Excerpt); ?> 

Обратите внимание, что если вы ошиблись в Xpath, это будет умирать с ошибкой. Поэтому, если вы отлаживаете это через вызовы AJAX, я рекомендую вам также регистрировать тела ответа.

Это усовершенствование наиболее употребимого решения Antonio Max, которое также работает с XML, который имеет пространства имен (путем замены двоеточия на подчеркивание). Он также имеет некоторые дополнительные опции (и правильно выполняет синтаксический анализ <person my-attribute='name'>John</person> ).

 function parse_xml_into_array($xml_string, $options = array()) { /* DESCRIPTION: - parse an XML string into an array INPUT: - $xml_string - $options : associative array with any of these keys: - 'flatten_cdata' : set to true to flatten CDATA elements - 'use_objects' : set to true to parse into objects instead of associative arrays - 'convert_booleans' : set to true to cast string values 'true' and 'false' into booleans OUTPUT: - associative array */ // Remove namespaces by replacing ":" with "_" if (preg_match_all("|</([\\w\\-]+):([\\w\\-]+)>|", $xml_string, $matches, PREG_SET_ORDER)) { foreach ($matches as $match) { $xml_string = str_replace('<'. $match[1] .':'. $match[2], '<'. $match[1] .'_'. $match[2], $xml_string); $xml_string = str_replace('</'. $match[1] .':'. $match[2], '</'. $match[1] .'_'. $match[2], $xml_string); } } $output = json_decode(json_encode(@simplexml_load_string($xml_string, 'SimpleXMLElement', ($options['flatten_cdata'] ? LIBXML_NOCDATA : 0))), ($options['use_objects'] ? false : true)); // Cast string values "true" and "false" to booleans if ($options['convert_booleans']) { $bool = function(&$item, $key) { if (in_array($item, array('true', 'TRUE', 'True'), true)) { $item = true; } elseif (in_array($item, array('false', 'FALSE', 'False'), true)) { $item = false; } }; array_walk_recursive($output, $bool); } return $output; } 

Похоже, что переменная $state->name содержит массив. Вы можете использовать

 var_dump($state) 

внутри foreach чтобы проверить это.

Если это так, вы можете изменить строку внутри foreach на

 $states[]= array('state' => array_shift($state->name)); 

чтобы исправить это.

Вопрос не говорит об этом, но обычно PHP возвращает JSON на веб-страницу.

Мне гораздо проще преобразовать XML в JSON в браузер / страницу через JS lib, например:

 https://code.google.com/p/x2js/downloads/detail?name=x2js-v1.1.3.zip 

У всех решений есть проблемы!

… Когда представление нуждается в совершенной интерпретации XML (без проблем с атрибутами) и воспроизвести весь текст-тег-текст-тег-текст -… и порядок тегов. Также хорошо помните, что объект JSON «является неупорядоченным множеством» (не повторяйте ключи, а ключи не могут иметь предопределенный порядок) … Даже xml2json от ZF неверен (!), Потому что не сохраняет точно структуру XML.

Все решения здесь имеют проблемы с этим простым XML,

  <states xx='1'> <state y="123">Alabama</state> My name is <b>John</b> Doe <state>Alaska</state> </states> 

… @FTav-решение кажется лучше, чем 3-строчное решение, но также имеет небольшую ошибку при тестировании с помощью этого XML.

Старое решение является лучшим (для представления без потерь)

Решение, известное сегодня как jsonML , используется проектом Zorba и другими, и впервые было представлено в ~ 2006 или в 2007 году (отдельно) Стивеном МакКамеем и Джоном Снелсоном .

 // the core algorithm is the XSLT of the "jsonML conventions" // see https://github.com/mckamey/jsonml $xslt = 'https://raw.githubusercontent.com/mckamey/jsonml/master/jsonml.xslt'; $dom = new DOMDocument; $dom->loadXML(' <states xx=\'1\'> <state y="123">Alabama</state> My name is <b>John</b> Doe <state>Alaska</state> </states> '); if (!$dom) die("\nERROR!"); $xslDoc = new DOMDocument(); $xslDoc->load($xslt); $proc = new XSLTProcessor(); $proc->importStylesheet($xslDoc); echo $proc->transformToXML($dom); 

Производить

 ["states",{"xx":"1"}, "\n\t ", ["state",{"y":"123"},"Alabama"], "\n\t\tMy name is ", ["b","John"], " Doe\n\t ", ["state","Alaska"], "\n\t" ] 

См. http://jsonML.org или github.com/mckamey/jsonml . Производственные правила этого JSON основаны на элементе JSON-analog,

введите описание изображения здесь

Этот синтаксис – это определение элемента и его повторение, с
element-list ::= element ',' element-list | element element-list ::= element ',' element-list | element .

 $templateData = $_POST['data']; // initializing or creating array $template_info = $templateData; // creating object of SimpleXMLElement $xml_template_info = new SimpleXMLElement("<?xml version=\"1.0\"?><template></template>"); // function call to convert array to xml array_to_xml($template_info,$xml_template_info); //saving generated xml file $xml_template_info->asXML(dirname(__FILE__)."/manifest.xml") ; // function defination to convert array to xml function array_to_xml($template_info, &$xml_template_info) { foreach($template_info as $key => $value) { if(is_array($value)) { if(!is_numeric($key)){ $subnode = $xml_template_info->addChild($key); if(is_array($value)){ $cont = 0; foreach(array_keys($value) as $k){ if(is_numeric($k)) $cont++; } } if($cont>0){ for($i=0; $i < $cont; $i++){ $subnode = $xml_body_info->addChild($key); array_to_xml($value[$i], $subnode); } }else{ $subnode = $xml_body_info->addChild($key); array_to_xml($value, $subnode); } } else{ array_to_xml($value, $xml_template_info); } } else { $xml_template_info->addChild($key,$value); } } }