PHP конвертировать XML в JSON

158

Я пытаюсь конвертировать 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"
}
}
}
Брайан Хэдлок
источник
Пожалуйста, включите фрагмент XML и окончательную структуру массива, которую вы получите после анализа. (А var_dumpотлично работает.)
nikc.org
добавлен ввод, вывод и var_dump
Брайан Хэдлок
Некоторым приложениям нужна «совершенная карта XML-JSON» , то есть jsonML , решение см. Здесь .
Питер Краусс

Ответы:

473

Json & Array из XML в 3 строки:

$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
Антонио Макс
источник
59
Это решение не безупречно. Он полностью отбрасывает атрибуты XML. Так <person my-attribute='name'>John</person>интерпретируется как <person>John</person>.
Джейк Уилсон
13
$ xml = simplexml_load_string ($ xml_string, 'SimpleXMLElement', LIBXML_NOCDATA); чтобы сгладить элементы cdata.
txyoji
28
@JakeWilson, может быть, прошло 2 года и исправлены различные версии, но в PHP 5.6.30 этот метод производит ВСЕ данные. Атрибуты хранятся в массиве под @attributesключом, поэтому он работает абсолютно безупречно и красиво. 3 короткие строки кода прекрасно решают мою проблему.
AlexanderMP
1
Это не работает, если у вас есть несколько пространств имен, вы можете выбрать только одно, которое перейдет в $ json_string: '(
jirislav
1
Имейте в виду, что в этом решении, когда может быть несколько узлов с одинаковым именем, один узел приведет к тому, что ключ будет просто указывать на элемент, а несколько узлов приведут к ключу, указывающему на массив элементов: <list><item><a>123</a><a>456</a></item><item><a>123</a></item></list>-> {"item":[{"a":["123","456"]},{"a":"123"}]}. Решение на php.net от ratfactor решает эту проблему, всегда сохраняя элементы в массиве.
Клесун
37

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

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;
    }
}
?>
Coreus
источник
4
Это не будет работать, если у вас есть несколько экземпляров одного и того же тега в вашем XML, json_encode будет только сериализовать последний экземпляр тега.
этри
35

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

foreach($xml->children() as $state)
{
    $states[]= array('state' => (string)$state->name); 
}       
echo json_encode($states);
Брайан Хэдлок
источник
19

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

Отказ от ответственности: я не 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"
                        }
                    ]
                }
            ]
        }
    ]
}
FTav
источник
Может ли он анализировать большие данные XML?
Volatil3
2
Это решение лучше, потому что не отбрасывает атрибуты XML. Также посмотрите, почему эта сложная структура лучше, чем упрощенная, по адресу xml.com/lpt/a/1658 (см. « Полуструктурированный XML») .... Упс, для CDATA, как @txyoji предложил сгладить элементы CDATA $xml = simplexml_load_file("myfile.xml",'SimpleXMLElement',LIBXML_‌​NOCDATA);.
Питер Краусс
Большое спасибо за пользовательскую функцию! Это делает настройку довольно простой. Кстати, добавили отредактированную версию вашей функции, которая анализирует XML способом JS: каждая запись имеет свой собственный объект (записи не сохраняются в одном массиве, если они имеют одинаковые тэги), таким образом, порядок сохраняется.
lucifer63
1
Ошибка Fatal error: Uncaught Error: Call to a member function getName() on bool.. Я думаю, что версия PHP провал :-( .. Пожалуйста, помогите!
KingRider
10

Распространенная ловушка - забывать, что json_encode()не учитываются элементы с текстовым значением и атрибутом (ами). Он выберет один из них, что означает потерю данных. Функция ниже решает эту проблему. Если кто-то решит пойти по пути 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.

Кодер Спасения
источник
Не компилирует и не выдает описанный вывод, если синтаксические ошибки исправлены.
Ричард Кифер
Что такое $dom? Откуда это пришло?
Джейк Уилсон
$ dom = новый DOMDocument (); вот откуда это приходит
Скотт
1
Последняя строка кода: $ json = json_decode (json_encode ($ sxml))); должно быть: $ json = json_decode (json_encode ($ sxml));
Чарли Смит
6

Попробуйте использовать это

$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

Аджай Кумар
источник
3

Для этой цели я использовал TypeConverter от Майлза Джонсона . Это можно установить с помощью 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);
хриплый
источник
3

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

$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);
Марко Леути
источник
4
Я использовал этот подход, но JSON пуст. XML действителен.
рябенко-про
2

Если вы хотите преобразовать только определенную часть 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, я рекомендую вам также регистрировать тела ответов.

ChrisR
источник
2
This is better solution

$fileContents= file_get_contents("https://www.feedforall.com/sample.xml");
$fileContents = str_replace(array("\n", "\r", "\t"), '', $fileContents);
$fileContents = trim(str_replace('"', "'", $fileContents));
$simpleXml = simplexml_load_string($fileContents);
$json = json_encode($simpleXml);
$array = json_decode($json,TRUE);
return $array;
Рашикул Рони
источник
2

Лучшее решение, которое работает как шарм

$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); // Remove // if you want to store the result in $json variable

echo '<pre>'.json_encode($simpleXml,JSON_PRETTY_PRINT).'</pre>';

Источник

Альфа
источник
1

Это улучшение наиболее одобренного решения Антонио Макса, которое также работает с 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;
}
TheStoryCoder
источник
2
Один не использует Regex для разбора XML, если это не простой XML с тривиальной структурой и очень предсказуемыми данными. Я не могу не подчеркнуть, насколько плохо это решение. Это ломает данные. Не говоря уже о том, что он невероятно медленный (вы анализируете с помощью регулярных выражений, а затем снова анализируете?) И не обрабатывает самозакрывающиеся теги.
AlexanderMP
Я не думаю, что вы действительно посмотрели на функцию. Он не использует регулярные выражения для выполнения фактического анализа, только в качестве простого исправления для работы с пространствами имен - который работал для всех моих случаев xml - и то, что он работает, является наиболее важным, а не "политически корректным". Вы можете улучшить его, если хотите!
TheStoryCoder
2
Тот факт, что это сработало для вас, не означает, что это правильно. Именно такой код генерирует ошибки, которые чрезвычайно трудно диагностировать, и генерирует эксплойты. Я имею в виду, что даже поверхностный просмотр спецификаций XML на сайтах, подобных этому, w3schools.com/xml/xml_elements.asp показывает множество причин, по которым это решение не будет работать. Как я уже сказал, он не может обнаружить самозакрывающиеся теги, такие как <element/>, не может адресовать элементы, которые начинаются с символов подчеркивания или содержат их, что разрешено в XML. Не в состоянии обнаружить CDATA. И как я уже сказал, это МЕДЛЕННО. Это сложность O (n ^ 2) из-за внутреннего разбора.
AlexanderMP
1
Дело в том, что здесь даже не спрашивали о пространствах имен, и существуют ПРОБНЫЕ способы работы с пространствами имен. Пространства имен существуют как полезная конструкция, НЕ предназначенная для такого анализа и превращенная в мерзость, которая не будет обработана каким-либо разумным анализатором. И все, что вам нужно для этого сделать, - это не создать претендента на приз «самый медленный алгоритм 2016 года», а немного поискать, чтобы найти множество реальных решений, таких как stackoverflow.com/ Вопросы / 16412047 /… И назвать это улучшением? Вот это да.
AlexanderMP
0

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

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

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

    <states x-x='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 x-x=\'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",{"x-x":"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-аналог,

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

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

Питер Краусс
источник
2
Очень необычная структура XML, в которой, я сомневаюсь, есть реальные варианты использования.
TheStoryCoder
0

Изучив немного все ответы, я нашел решение, которое прекрасно работало с моими функциями JavaScript в разных браузерах (включая консоли / инструменты разработки):

<?php

 // PHP Version 7.2.1 (Windows 10 x86)

 function json2xml( $domNode ) {
  foreach( $domNode -> childNodes as $node) {
   if ( $node -> hasChildNodes() ) { json2xml( $node ); }
   else {
    if ( $domNode -> hasAttributes() && strlen( $domNode -> nodeValue ) ) {
     $domNode -> setAttribute( "nodeValue", $node -> textContent );
     $node -> nodeValue = "";
    }
   }
  }
 }

 function jsonOut( $file ) {
  $dom = new DOMDocument();
  $dom -> loadXML( file_get_contents( $file ) );
  json2xml( $dom );
  header( 'Content-Type: application/json' );
  return str_replace( "@", "", json_encode( simplexml_load_string( $dom -> saveXML() ), JSON_PRETTY_PRINT ) );
 }

 $output = jsonOut( 'https://boxelizer.com/assets/a1e10642e9294f39/b6f30987f0b66103.xml' );

 echo( $output );

 /*
  Or simply 
  echo( jsonOut( 'https://boxelizer.com/assets/a1e10642e9294f39/b6f30987f0b66103.xml' ) );
 */

?>

Он в основном создает новый DOMDocument, загружает и XML-файл в него и проходит через каждый из узлов и дочерних элементов, получая данные / параметры и экспортируя их в JSON без раздражающих знаков «@».

Ссылка на файл XML .

Xedret
источник
0

Это решение обрабатывает пространства имен, атрибуты и выдает согласованный результат с повторяющимися элементами (всегда в массиве, даже если есть только одно вхождение). Вдохновлено sxiToArray от ratfactor () .

/**
 * <root><a>5</a><b>6</b><b>8</b></root> -> {"root":[{"a":["5"],"b":["6","8"]}]}
 * <root a="5"><b>6</b><b>8</b></root> -> {"root":[{"a":"5","b":["6","8"]}]}
 * <root xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"><a>123</a><wsp:b>456</wsp:b></root> 
 *   -> {"root":[{"xmlns:wsp":"http://schemas.xmlsoap.org/ws/2004/09/policy","a":["123"],"wsp:b":["456"]}]}
 */
function domNodesToArray(array $tags, \DOMXPath $xpath)
{
    $tagNameToArr = [];
    foreach ($tags as $tag) {
        $tagData = [];
        $attrs = $tag->attributes ? iterator_to_array($tag->attributes) : [];
        $subTags = $tag->childNodes ? iterator_to_array($tag->childNodes) : [];
        foreach ($xpath->query('namespace::*', $tag) as $nsNode) {
            // the only way to get xmlns:*, see https://stackoverflow.com/a/2470433/2750743
            if ($tag->hasAttribute($nsNode->nodeName)) {
                $attrs[] = $nsNode;
            }
        }

        foreach ($attrs as $attr) {
            $tagData[$attr->nodeName] = $attr->nodeValue;
        }
        if (count($subTags) === 1 && $subTags[0] instanceof \DOMText) {
            $text = $subTags[0]->nodeValue;
        } elseif (count($subTags) === 0) {
            $text = '';
        } else {
            // ignore whitespace (and any other text if any) between nodes
            $isNotDomText = function($node){return !($node instanceof \DOMText);};
            $realNodes = array_filter($subTags, $isNotDomText);
            $subTagNameToArr = domNodesToArray($realNodes, $xpath);
            $tagData = array_merge($tagData, $subTagNameToArr);
            $text = null;
        }
        if (!is_null($text)) {
            if ($attrs) {
                if ($text) {
                    $tagData['_'] = $text;
                }
            } else {
                $tagData = $text;
            }
        }
        $keyName = $tag->nodeName;
        $tagNameToArr[$keyName][] = $tagData;
    }
    return $tagNameToArr;
}

function xmlToArr(string $xml)
{
    $doc = new \DOMDocument();
    $doc->loadXML($xml);
    $xpath = new \DOMXPath($doc);
    $tags = $doc->childNodes ? iterator_to_array($doc->childNodes) : [];
    return domNodesToArray($tags, $xpath);
}

Пример:

php > print(json_encode(xmlToArr('<root a="5"><b>6</b></root>')));
{"root":[{"a":"5","b":["6"]}]}
Klesun
источник
это на самом деле работает для случаев с несколькими пространствами имен, лучше, чем другие решения, почему получил отрицательный голос ...
Аарон
0

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

function xml2js($xmlnode) {
    $jsnode = array();
    $nodename = $xmlnode->getName();
    $current_object = array();

    if (count($xmlnode->attributes()) > 0) {
        foreach($xmlnode->attributes() as $key => $value) {
            $current_object[$key] = (string)$value;
        }
    }

    $textcontent = trim((string)$xmlnode);
    if (strlen($textcontent) > 0) {
        $current_object["content"] = $textcontent;
    }

    if (count($xmlnode->children()) > 0) {
        $current_object['children'] = array();
        foreach ($xmlnode->children() as $childxmlnode) {
            $childname = $childxmlnode->getName();
            array_push($current_object['children'], xml2js($childxmlnode, true));
        }
    }

    $jsnode[ $nodename ] = $current_object;
    return $jsnode;
}

Вот как это работает. Исходная структура XML:

<some-tag some-attribute="value of some attribute">
  <another-tag>With text</another-tag>
  <surprise></surprise>
  <another-tag>The last one</another-tag>
</some-tag>

Результат JSON:

{
    "some-tag": {
        "some-attribute": "value of some attribute",
        "children": [
            {
                "another-tag": {
                    "content": "With text"
                }
            },
            {
                "surprise": []
            },
            {
                "another-tag": {
                    "content": "The last one"
                }
            }
        ]
    }
}
lucifer63
источник
-1

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

var_dump($state)

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

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

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

исправить это.

Майкл Фенвик
источник
похоже, что атрибуты - это массивы, но не $ state-> name
Брайан Хэдлок
-1
$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);
        }
    }
}
Октавио Перес Гальегос
источник
Это небольшое и универсальное решение, основанное на массиве данных, может быть преобразовано в JSON json_decode ... повезло
Октавио Перес Галлегос
2
Как это отвечает на первоначальный вопрос? Ваш ответ кажется более сложным, чем первоначальный вопрос, и, похоже, нигде не упоминает JSON.
Дан Р
-1

Если вы пользователь Ubuntu, установите xml reader (у меня есть php 5.6. Если у вас есть другие, пожалуйста, найдите пакет и установите)

sudo apt-get install php5.6-xml
service apache2 restart

$fileContents = file_get_contents('myDirPath/filename.xml');
$fileContents = str_replace(array("\n", "\r", "\t"), '', $fileContents);
$fileContents = trim(str_replace('"', "'", $fileContents));
$oldXml = $fileContents;
$simpleXml = simplexml_load_string($fileContents);
$json = json_encode($simpleXml);
Атул Балдания
источник