PHP convert XML to JSON
I am trying to convert xml to json in php. If I do a simple convert using simple xml and json_encode none of the attributes in the xml show.
$xml = simplexml_load_file("states.xml");
echo json_encode($xml);
So I am trying to manually parse it like this.
foreach($xml->children() as $state)
{
$states= array('state' => $state->name);
}
echo json_encode($states);
and the output for state is {"state":{"0":"Alabama"}}
rather than {"state":"Alabama"}
What am I doing wrong?
XML:
<?xml version="1.0" ?>
<states>
<state id="AL">
<name>Alabama</name>
</state>
<state id="AK">
<name>Alaska</name>
</state>
</states>
Output:
[{"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"
}
}
}
php xml json
add a comment |
I am trying to convert xml to json in php. If I do a simple convert using simple xml and json_encode none of the attributes in the xml show.
$xml = simplexml_load_file("states.xml");
echo json_encode($xml);
So I am trying to manually parse it like this.
foreach($xml->children() as $state)
{
$states= array('state' => $state->name);
}
echo json_encode($states);
and the output for state is {"state":{"0":"Alabama"}}
rather than {"state":"Alabama"}
What am I doing wrong?
XML:
<?xml version="1.0" ?>
<states>
<state id="AL">
<name>Alabama</name>
</state>
<state id="AK">
<name>Alaska</name>
</state>
</states>
Output:
[{"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"
}
}
}
php xml json
please post input and output. please var_dump $xml as well.
– David Chan
Jan 12 '12 at 5:39
Please include a snippet of the XML and the final array structure you have after parsing it. (Avar_dump
works fine.)
– nikc.org
Jan 12 '12 at 5:39
added input, output and var_dump
– Bryan Hadlock
Jan 12 '12 at 6:15
Some applications need "perfec XML-to-JSON map", that is jsonML, see solution here.
– Peter Krauss
Oct 6 '16 at 14:19
add a comment |
I am trying to convert xml to json in php. If I do a simple convert using simple xml and json_encode none of the attributes in the xml show.
$xml = simplexml_load_file("states.xml");
echo json_encode($xml);
So I am trying to manually parse it like this.
foreach($xml->children() as $state)
{
$states= array('state' => $state->name);
}
echo json_encode($states);
and the output for state is {"state":{"0":"Alabama"}}
rather than {"state":"Alabama"}
What am I doing wrong?
XML:
<?xml version="1.0" ?>
<states>
<state id="AL">
<name>Alabama</name>
</state>
<state id="AK">
<name>Alaska</name>
</state>
</states>
Output:
[{"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"
}
}
}
php xml json
I am trying to convert xml to json in php. If I do a simple convert using simple xml and json_encode none of the attributes in the xml show.
$xml = simplexml_load_file("states.xml");
echo json_encode($xml);
So I am trying to manually parse it like this.
foreach($xml->children() as $state)
{
$states= array('state' => $state->name);
}
echo json_encode($states);
and the output for state is {"state":{"0":"Alabama"}}
rather than {"state":"Alabama"}
What am I doing wrong?
XML:
<?xml version="1.0" ?>
<states>
<state id="AL">
<name>Alabama</name>
</state>
<state id="AK">
<name>Alaska</name>
</state>
</states>
Output:
[{"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"
}
}
}
php xml json
php xml json
edited Jan 12 '12 at 6:04
asked Jan 12 '12 at 5:36
Bryan Hadlock
1,1862914
1,1862914
please post input and output. please var_dump $xml as well.
– David Chan
Jan 12 '12 at 5:39
Please include a snippet of the XML and the final array structure you have after parsing it. (Avar_dump
works fine.)
– nikc.org
Jan 12 '12 at 5:39
added input, output and var_dump
– Bryan Hadlock
Jan 12 '12 at 6:15
Some applications need "perfec XML-to-JSON map", that is jsonML, see solution here.
– Peter Krauss
Oct 6 '16 at 14:19
add a comment |
please post input and output. please var_dump $xml as well.
– David Chan
Jan 12 '12 at 5:39
Please include a snippet of the XML and the final array structure you have after parsing it. (Avar_dump
works fine.)
– nikc.org
Jan 12 '12 at 5:39
added input, output and var_dump
– Bryan Hadlock
Jan 12 '12 at 6:15
Some applications need "perfec XML-to-JSON map", that is jsonML, see solution here.
– Peter Krauss
Oct 6 '16 at 14:19
please post input and output. please var_dump $xml as well.
– David Chan
Jan 12 '12 at 5:39
please post input and output. please var_dump $xml as well.
– David Chan
Jan 12 '12 at 5:39
Please include a snippet of the XML and the final array structure you have after parsing it. (A
var_dump
works fine.)– nikc.org
Jan 12 '12 at 5:39
Please include a snippet of the XML and the final array structure you have after parsing it. (A
var_dump
works fine.)– nikc.org
Jan 12 '12 at 5:39
added input, output and var_dump
– Bryan Hadlock
Jan 12 '12 at 6:15
added input, output and var_dump
– Bryan Hadlock
Jan 12 '12 at 6:15
Some applications need "perfec XML-to-JSON map", that is jsonML, see solution here.
– Peter Krauss
Oct 6 '16 at 14:19
Some applications need "perfec XML-to-JSON map", that is jsonML, see solution here.
– Peter Krauss
Oct 6 '16 at 14:19
add a comment |
16 Answers
16
active
oldest
votes
Json & Array from XML in 3 lines:
$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
11
Why the downvote? This is works flawlessly with fewer lines than any other example here. No libs, no nothing, just plain PHP!
– Antonio Max
Oct 15 '13 at 22:21
2
This is exactly what I was looking for, however I think the question wanted special parsing. Taking certain sub-elements and moving them up the tree ( a custom parser ), instead of a 1 to 1 conversion.
– Gauthier
Nov 7 '13 at 4:23
41
This solution is not flawless. It completely discards XML attributes. So<person my-attribute='name'>John</person>
is interpreted as<person>John</person>
.
– Jake Wilson
Jan 26 '15 at 19:57
10
$xml = simplexml_load_string($xml_string,'SimpleXMLElement',LIBXML_NOCDATA); to flatten cdata elements.
– txyoji
Jul 14 '15 at 17:29
17
@JakeWilson maybe it's the 2 years that have passed, and various version fixes, but on PHP 5.6.30, this method produces ALL of the data. Attributes are stored in the array under the@attributes
key, so it works absolutely flawlessly, and beautifully. 3 short lines of code solve my problem beautifully.
– AlexanderMP
Feb 7 '17 at 16:12
|
show 7 more comments
Sorry for answering an old post, but this article outlines an approach that is relatively short, concise and easy to maintain. I tested it myself and works pretty well.
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;
}
}
?>
7
You shoud be prude for answering old question not sorry!
– PHPst
May 23 '13 at 6:47
3
This will not work if you have multiple instances of the same tag in your XML, json_encode will end up only serializing the last instance of the tag.
– ethree
Nov 7 '13 at 20:50
3
Also doesn't appear to work for CDATA contents.
– jsleuth
May 7 '14 at 22:59
add a comment |
I figured it out. json_encode handles objects differently than strings. I cast the object to a string and it works now.
foreach($xml->children() as $state)
{
$states= array('state' => (string)$state->name);
}
echo json_encode($states);
add a comment |
I guess I'm a bit late to the party but I have written a small function to accomplish this task. It also takes care of attributes, text content and even if multiple nodes with the same node-name are siblings.
Dislaimer:
I'm not a PHP native, so please bear with simple mistakes.
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);
}
}
Usage example:
$xml = simplexml_load_file("myfile.xml");
echo xml2js($xml);
Example Input (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>
Example output:
{"family":[{"$":{"name":"Johnson"},"child":[{"$":{"name":"John","age":"5"},"toy":[{"$":{"status":"old"},"_":"Trooper"},{"$":{"status":"old"},"_":"Ultrablock"},{"$":{"status":"new"},"_":"Bike"}]}]}]}
Pretty printed:
{
"family" : [{
"$" : {
"name" : "Johnson"
},
"child" : [{
"$" : {
"name" : "John",
"age" : "5"
},
"toy" : [{
"$" : {
"status" : "old"
},
"_" : "Trooper"
}, {
"$" : {
"status" : "old"
},
"_" : "Ultrablock"
}, {
"$" : {
"status" : "new"
},
"_" : "Bike"
}
]
}
]
}
]
}
Quirks to keep in mind:
Several tags with the same tagname can be siblings. Other solutions will most likely drop all but the last sibling. To avoid this each and every single node, even if it only has one child, is an array which hold an object for each instance of the tagname. (See multiple "" elements in example)
Even the root element, of which only one should exist in a valid XML document is stored as array with an object of the instance, just to have a consistent data structure.
To be able to distinguish between XML node content and XML attributes each objects attributes are stored in the "$" and the content in the "_" child.
Edit:
I forgot to show the output for your example input data
{
"states" : [{
"state" : [{
"$" : {
"id" : "AL"
},
"name" : [{
"_" : "Alabama"
}
]
}, {
"$" : {
"id" : "AK"
},
"name" : [{
"_" : "Alaska"
}
]
}
]
}
]
}
Can it parse large XML data?
– Volatil3
Mar 1 '16 at 18:09
This solution is better because not discards XML attributes. See also why this complex structure is better than simplified ones, at xml.com/lpt/a/1658 (see "Semi-Structured XML").... Ops, for CDATA, as @txyoji suggested to flatten CDATA elements$xml = simplexml_load_file("myfile.xml",'SimpleXMLElement',LIBXML_NOCDATA);
.
– Peter Krauss
Oct 6 '16 at 4:27
Oops BUG!!! losting order and grouping tags. Test with<states> <state>Alabama</state> <p>John</p> <state>Alaska</state> </states>
.
– Peter Krauss
Oct 6 '16 at 4:57
add a comment |
A common pitfall is to forget that json_encode()
does not respect elements with a textvalue and attribute(s). It will choose one of those, meaning dataloss.
The function below solves that problem. If one decides to go for the json_encode
/decode
way, the following function is advised.
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 ) );
by doing so, <foo bar="3">Lorem</foo>
will not end up as {"foo":"Lorem"}
in your JSON.
Does not compile and does not produce the described output if syntax-errors are corrected.
– Richard Kiefer
Jan 21 '15 at 10:36
What is$dom
? Where did that come from?
– Jake Wilson
Jan 26 '15 at 20:20
$dom = new DOMDocument(); is where it comes from
– Scott
Nov 25 '15 at 21:28
Last line of code: $json = json_decode( json_encode( $sxml ) ) ); should be : $json = json_decode( json_encode( $sxml ) );
– Charlie Smith
Feb 29 '16 at 2:46
Definite +1 for this - very important point!
– Tom Folk
Apr 18 '16 at 10:09
add a comment |
Try to use this
$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;
Or
You can use this library : https://github.com/rentpost/xml2array
add a comment |
Optimizing Antonio Max answer:
$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);
I used this approach, but JSON is empty. XML is valid.
– ryabenko-pro
Jan 9 '18 at 19:07
add a comment |
I've used Miles Johnson's TypeConverter for this purpose. It's installable using Composer.
You could write something like this using it:
<?php
require 'vendor/autoload.php';
use mjohnsonutilityTypeConverter;
$xml = file_get_contents("file.xml");
$arr = TypeConverter::xmlToArray($xml, TypeConverter::XML_GROUP);
echo json_encode($arr);
add a comment |
This is an improvement of the most upvoted solution by Antonio Max, which also works with XML that has namespaces (by replacing the colon with an underscore). It also has some extra options (and does parse <person my-attribute='name'>John</person>
correctly).
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;
}
One does not use Regex to parse XML, unless it's a simple XML with trivial structure and very predictable data. I can't stress enough how bad this solution is. This BREAKS DATA. Not to mention that it's incredibly slow (you parse with regex, and then you re-parse again?) and doesn't handle self-closing tags.
– AlexanderMP
Feb 7 '17 at 16:19
I don't think you really looked at the function. It doesn't use regex to do the actual parsing, only as a simple fix to deal with namespaces - which has been working for all my xml cases - and that it is working is the most important, rather than being "politically correct". You're welcome to improve it if you want, though!
– TheStoryCoder
Feb 13 '17 at 21:39
The fact that it has worked for you doesn't mean it's right. It's code like this that generates bugs that are immensely hard to diagnose, and generates exploits. I mean even looking superficially at XML specs on sites like this w3schools.com/xml/xml_elements.asp show a lot of reasons why this solution wouldn't work. Like I said, it fails to detect self-closing tags like<element/>
, fails to address elements that start with, or contain underscores, which is allowed in XML. Fails to detect CDATA. And as I've said, it's SLOW. It's an O(n^2) complexity because of inner parsing.
– AlexanderMP
May 9 '17 at 17:41
The thing is that dealing with namespaces wasn't even asked here, and there are PROPER ways to deal with namespaces. Namespaces exist as a helpful construction, NOT to be parsed like that and turned into an abomination that won't be processed by any reasonable parser. And all you needed to do for that is not to create the contender for the prize of "slowest algorithm of 2016", but to do a bit of searching, to come up with a myriad of actual solutions, like this one stackoverflow.com/questions/16412047/… And to call this an improvement? Wow.
– AlexanderMP
May 9 '17 at 17:48
add a comment |
If you would like to only convert a specific part of the XML to JSON, you can use XPath to retrieve this and convert that to 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);
?>
Please note that if you Xpath is incorrect, this will die with an error. So if you're debugging this through AJAX calls I recommend you log the response bodies as well.
add a comment |
Looks like the $state->name
variable is holding an array. You can use
var_dump($state)
inside the foreach
to test that.
If that's the case, you can change the line inside the foreach
to
$states= array('state' => array_shift($state->name));
to correct it.
looks like the attributes are arrays but not $state->name
– Bryan Hadlock
Jan 12 '12 at 6:11
add a comment |
The question doesn't say it, but usually PHP is returning JSON to a web page.
I find it much easier to convert the XML to JSON in the browser/page via a JS lib, for example:
https://code.google.com/p/x2js/downloads/detail?name=x2js-v1.1.3.zip
add a comment |
All solutions here have problems!
... When the representation need perfect XML interpretation (without problems with attributes) and to reproduce all text-tag-text-tag-text-... and order of tags. Also good remember here that JSON object "is an unordered set" (not repeat keys and the keys can't have predefined order)... Even ZF's xml2json is wrong (!) because not preserve exactly the XML structure.
All solutions here have problems with this simple XML,
<states x-x='1'>
<state y="123">Alabama</state>
My name is <b>John</b> Doe
<state>Alaska</state>
</states>
... @FTav solution seems better than 3-line solution, but also have little bug when tested with this XML.
Old solution is the best (for loss-less representation)
The solution, today well-known as jsonML, is used by Zorba project and others, and was first presented in ~2006 or ~2007, by (separately) Stephen McKamey and John Snelson.
// 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);
Produce
["states",{"x-x":"1"},
"nt ",
["state",{"y":"123"},"Alabama"],
"nttMy name is ",
["b","John"],
" Doent ",
["state","Alaska"],
"nt"
]
See http://jsonML.org or github.com/mckamey/jsonml. The production rules of this JSON are based on the element JSON-analog,
This syntax is a element definition and recurrence, with element-list ::= element ',' element-list | element
.
Very unusual xml structure that I doubt would have real life use cases.
– TheStoryCoder
Feb 13 '17 at 21:49
add a comment |
$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
just add those three lines you will get the correct output:-)
add a comment |
After researching a little bit all of the answers, I came up with a solution that worked just fine with my JavaScript functions across browsers (Including consoles / Dev Tools) :
<?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' ) );
*/
?>
It basically creates a new DOMDocument, loads and XML file into it and traverses through each one of the nodes and children getting the data / parameters and exporting it into JSON without the annoying "@" signs.
Link to the XML file.
add a comment |
$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);
}
}
}
It is a small and universal solution based on an array of data can be a JSON transformed json_decode ...lucky
– Octavio Perez Gallegos
Jun 30 '16 at 22:45
1
In what way does this answer the original question? Your answer seems more complicated than the original question, and also doesn't seem to even mention JSON anywhere.
– Dan Roche
Jun 30 '16 at 22:54
Sorry, I uploaded the implementation is to respond to the conversion of XML to any understandable to process a simple PHP json_encode arrangement. Sorry for the lack of clarity
– Octavio Perez Gallegos
Jul 26 '16 at 17:45
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f8830599%2fphp-convert-xml-to-json%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
16 Answers
16
active
oldest
votes
16 Answers
16
active
oldest
votes
active
oldest
votes
active
oldest
votes
Json & Array from XML in 3 lines:
$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
11
Why the downvote? This is works flawlessly with fewer lines than any other example here. No libs, no nothing, just plain PHP!
– Antonio Max
Oct 15 '13 at 22:21
2
This is exactly what I was looking for, however I think the question wanted special parsing. Taking certain sub-elements and moving them up the tree ( a custom parser ), instead of a 1 to 1 conversion.
– Gauthier
Nov 7 '13 at 4:23
41
This solution is not flawless. It completely discards XML attributes. So<person my-attribute='name'>John</person>
is interpreted as<person>John</person>
.
– Jake Wilson
Jan 26 '15 at 19:57
10
$xml = simplexml_load_string($xml_string,'SimpleXMLElement',LIBXML_NOCDATA); to flatten cdata elements.
– txyoji
Jul 14 '15 at 17:29
17
@JakeWilson maybe it's the 2 years that have passed, and various version fixes, but on PHP 5.6.30, this method produces ALL of the data. Attributes are stored in the array under the@attributes
key, so it works absolutely flawlessly, and beautifully. 3 short lines of code solve my problem beautifully.
– AlexanderMP
Feb 7 '17 at 16:12
|
show 7 more comments
Json & Array from XML in 3 lines:
$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
11
Why the downvote? This is works flawlessly with fewer lines than any other example here. No libs, no nothing, just plain PHP!
– Antonio Max
Oct 15 '13 at 22:21
2
This is exactly what I was looking for, however I think the question wanted special parsing. Taking certain sub-elements and moving them up the tree ( a custom parser ), instead of a 1 to 1 conversion.
– Gauthier
Nov 7 '13 at 4:23
41
This solution is not flawless. It completely discards XML attributes. So<person my-attribute='name'>John</person>
is interpreted as<person>John</person>
.
– Jake Wilson
Jan 26 '15 at 19:57
10
$xml = simplexml_load_string($xml_string,'SimpleXMLElement',LIBXML_NOCDATA); to flatten cdata elements.
– txyoji
Jul 14 '15 at 17:29
17
@JakeWilson maybe it's the 2 years that have passed, and various version fixes, but on PHP 5.6.30, this method produces ALL of the data. Attributes are stored in the array under the@attributes
key, so it works absolutely flawlessly, and beautifully. 3 short lines of code solve my problem beautifully.
– AlexanderMP
Feb 7 '17 at 16:12
|
show 7 more comments
Json & Array from XML in 3 lines:
$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
Json & Array from XML in 3 lines:
$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
edited Nov 23 '18 at 2:13
Ali Khaki
7211418
7211418
answered Oct 15 '13 at 21:36
Antonio Max
5,78853639
5,78853639
11
Why the downvote? This is works flawlessly with fewer lines than any other example here. No libs, no nothing, just plain PHP!
– Antonio Max
Oct 15 '13 at 22:21
2
This is exactly what I was looking for, however I think the question wanted special parsing. Taking certain sub-elements and moving them up the tree ( a custom parser ), instead of a 1 to 1 conversion.
– Gauthier
Nov 7 '13 at 4:23
41
This solution is not flawless. It completely discards XML attributes. So<person my-attribute='name'>John</person>
is interpreted as<person>John</person>
.
– Jake Wilson
Jan 26 '15 at 19:57
10
$xml = simplexml_load_string($xml_string,'SimpleXMLElement',LIBXML_NOCDATA); to flatten cdata elements.
– txyoji
Jul 14 '15 at 17:29
17
@JakeWilson maybe it's the 2 years that have passed, and various version fixes, but on PHP 5.6.30, this method produces ALL of the data. Attributes are stored in the array under the@attributes
key, so it works absolutely flawlessly, and beautifully. 3 short lines of code solve my problem beautifully.
– AlexanderMP
Feb 7 '17 at 16:12
|
show 7 more comments
11
Why the downvote? This is works flawlessly with fewer lines than any other example here. No libs, no nothing, just plain PHP!
– Antonio Max
Oct 15 '13 at 22:21
2
This is exactly what I was looking for, however I think the question wanted special parsing. Taking certain sub-elements and moving them up the tree ( a custom parser ), instead of a 1 to 1 conversion.
– Gauthier
Nov 7 '13 at 4:23
41
This solution is not flawless. It completely discards XML attributes. So<person my-attribute='name'>John</person>
is interpreted as<person>John</person>
.
– Jake Wilson
Jan 26 '15 at 19:57
10
$xml = simplexml_load_string($xml_string,'SimpleXMLElement',LIBXML_NOCDATA); to flatten cdata elements.
– txyoji
Jul 14 '15 at 17:29
17
@JakeWilson maybe it's the 2 years that have passed, and various version fixes, but on PHP 5.6.30, this method produces ALL of the data. Attributes are stored in the array under the@attributes
key, so it works absolutely flawlessly, and beautifully. 3 short lines of code solve my problem beautifully.
– AlexanderMP
Feb 7 '17 at 16:12
11
11
Why the downvote? This is works flawlessly with fewer lines than any other example here. No libs, no nothing, just plain PHP!
– Antonio Max
Oct 15 '13 at 22:21
Why the downvote? This is works flawlessly with fewer lines than any other example here. No libs, no nothing, just plain PHP!
– Antonio Max
Oct 15 '13 at 22:21
2
2
This is exactly what I was looking for, however I think the question wanted special parsing. Taking certain sub-elements and moving them up the tree ( a custom parser ), instead of a 1 to 1 conversion.
– Gauthier
Nov 7 '13 at 4:23
This is exactly what I was looking for, however I think the question wanted special parsing. Taking certain sub-elements and moving them up the tree ( a custom parser ), instead of a 1 to 1 conversion.
– Gauthier
Nov 7 '13 at 4:23
41
41
This solution is not flawless. It completely discards XML attributes. So
<person my-attribute='name'>John</person>
is interpreted as <person>John</person>
.– Jake Wilson
Jan 26 '15 at 19:57
This solution is not flawless. It completely discards XML attributes. So
<person my-attribute='name'>John</person>
is interpreted as <person>John</person>
.– Jake Wilson
Jan 26 '15 at 19:57
10
10
$xml = simplexml_load_string($xml_string,'SimpleXMLElement',LIBXML_NOCDATA); to flatten cdata elements.
– txyoji
Jul 14 '15 at 17:29
$xml = simplexml_load_string($xml_string,'SimpleXMLElement',LIBXML_NOCDATA); to flatten cdata elements.
– txyoji
Jul 14 '15 at 17:29
17
17
@JakeWilson maybe it's the 2 years that have passed, and various version fixes, but on PHP 5.6.30, this method produces ALL of the data. Attributes are stored in the array under the
@attributes
key, so it works absolutely flawlessly, and beautifully. 3 short lines of code solve my problem beautifully.– AlexanderMP
Feb 7 '17 at 16:12
@JakeWilson maybe it's the 2 years that have passed, and various version fixes, but on PHP 5.6.30, this method produces ALL of the data. Attributes are stored in the array under the
@attributes
key, so it works absolutely flawlessly, and beautifully. 3 short lines of code solve my problem beautifully.– AlexanderMP
Feb 7 '17 at 16:12
|
show 7 more comments
Sorry for answering an old post, but this article outlines an approach that is relatively short, concise and easy to maintain. I tested it myself and works pretty well.
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;
}
}
?>
7
You shoud be prude for answering old question not sorry!
– PHPst
May 23 '13 at 6:47
3
This will not work if you have multiple instances of the same tag in your XML, json_encode will end up only serializing the last instance of the tag.
– ethree
Nov 7 '13 at 20:50
3
Also doesn't appear to work for CDATA contents.
– jsleuth
May 7 '14 at 22:59
add a comment |
Sorry for answering an old post, but this article outlines an approach that is relatively short, concise and easy to maintain. I tested it myself and works pretty well.
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;
}
}
?>
7
You shoud be prude for answering old question not sorry!
– PHPst
May 23 '13 at 6:47
3
This will not work if you have multiple instances of the same tag in your XML, json_encode will end up only serializing the last instance of the tag.
– ethree
Nov 7 '13 at 20:50
3
Also doesn't appear to work for CDATA contents.
– jsleuth
May 7 '14 at 22:59
add a comment |
Sorry for answering an old post, but this article outlines an approach that is relatively short, concise and easy to maintain. I tested it myself and works pretty well.
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;
}
}
?>
Sorry for answering an old post, but this article outlines an approach that is relatively short, concise and easy to maintain. I tested it myself and works pretty well.
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;
}
}
?>
answered Mar 11 '13 at 9:47
Coreus
3,34122642
3,34122642
7
You shoud be prude for answering old question not sorry!
– PHPst
May 23 '13 at 6:47
3
This will not work if you have multiple instances of the same tag in your XML, json_encode will end up only serializing the last instance of the tag.
– ethree
Nov 7 '13 at 20:50
3
Also doesn't appear to work for CDATA contents.
– jsleuth
May 7 '14 at 22:59
add a comment |
7
You shoud be prude for answering old question not sorry!
– PHPst
May 23 '13 at 6:47
3
This will not work if you have multiple instances of the same tag in your XML, json_encode will end up only serializing the last instance of the tag.
– ethree
Nov 7 '13 at 20:50
3
Also doesn't appear to work for CDATA contents.
– jsleuth
May 7 '14 at 22:59
7
7
You shoud be prude for answering old question not sorry!
– PHPst
May 23 '13 at 6:47
You shoud be prude for answering old question not sorry!
– PHPst
May 23 '13 at 6:47
3
3
This will not work if you have multiple instances of the same tag in your XML, json_encode will end up only serializing the last instance of the tag.
– ethree
Nov 7 '13 at 20:50
This will not work if you have multiple instances of the same tag in your XML, json_encode will end up only serializing the last instance of the tag.
– ethree
Nov 7 '13 at 20:50
3
3
Also doesn't appear to work for CDATA contents.
– jsleuth
May 7 '14 at 22:59
Also doesn't appear to work for CDATA contents.
– jsleuth
May 7 '14 at 22:59
add a comment |
I figured it out. json_encode handles objects differently than strings. I cast the object to a string and it works now.
foreach($xml->children() as $state)
{
$states= array('state' => (string)$state->name);
}
echo json_encode($states);
add a comment |
I figured it out. json_encode handles objects differently than strings. I cast the object to a string and it works now.
foreach($xml->children() as $state)
{
$states= array('state' => (string)$state->name);
}
echo json_encode($states);
add a comment |
I figured it out. json_encode handles objects differently than strings. I cast the object to a string and it works now.
foreach($xml->children() as $state)
{
$states= array('state' => (string)$state->name);
}
echo json_encode($states);
I figured it out. json_encode handles objects differently than strings. I cast the object to a string and it works now.
foreach($xml->children() as $state)
{
$states= array('state' => (string)$state->name);
}
echo json_encode($states);
answered Jan 13 '12 at 3:56
Bryan Hadlock
1,1862914
1,1862914
add a comment |
add a comment |
I guess I'm a bit late to the party but I have written a small function to accomplish this task. It also takes care of attributes, text content and even if multiple nodes with the same node-name are siblings.
Dislaimer:
I'm not a PHP native, so please bear with simple mistakes.
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);
}
}
Usage example:
$xml = simplexml_load_file("myfile.xml");
echo xml2js($xml);
Example Input (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>
Example output:
{"family":[{"$":{"name":"Johnson"},"child":[{"$":{"name":"John","age":"5"},"toy":[{"$":{"status":"old"},"_":"Trooper"},{"$":{"status":"old"},"_":"Ultrablock"},{"$":{"status":"new"},"_":"Bike"}]}]}]}
Pretty printed:
{
"family" : [{
"$" : {
"name" : "Johnson"
},
"child" : [{
"$" : {
"name" : "John",
"age" : "5"
},
"toy" : [{
"$" : {
"status" : "old"
},
"_" : "Trooper"
}, {
"$" : {
"status" : "old"
},
"_" : "Ultrablock"
}, {
"$" : {
"status" : "new"
},
"_" : "Bike"
}
]
}
]
}
]
}
Quirks to keep in mind:
Several tags with the same tagname can be siblings. Other solutions will most likely drop all but the last sibling. To avoid this each and every single node, even if it only has one child, is an array which hold an object for each instance of the tagname. (See multiple "" elements in example)
Even the root element, of which only one should exist in a valid XML document is stored as array with an object of the instance, just to have a consistent data structure.
To be able to distinguish between XML node content and XML attributes each objects attributes are stored in the "$" and the content in the "_" child.
Edit:
I forgot to show the output for your example input data
{
"states" : [{
"state" : [{
"$" : {
"id" : "AL"
},
"name" : [{
"_" : "Alabama"
}
]
}, {
"$" : {
"id" : "AK"
},
"name" : [{
"_" : "Alaska"
}
]
}
]
}
]
}
Can it parse large XML data?
– Volatil3
Mar 1 '16 at 18:09
This solution is better because not discards XML attributes. See also why this complex structure is better than simplified ones, at xml.com/lpt/a/1658 (see "Semi-Structured XML").... Ops, for CDATA, as @txyoji suggested to flatten CDATA elements$xml = simplexml_load_file("myfile.xml",'SimpleXMLElement',LIBXML_NOCDATA);
.
– Peter Krauss
Oct 6 '16 at 4:27
Oops BUG!!! losting order and grouping tags. Test with<states> <state>Alabama</state> <p>John</p> <state>Alaska</state> </states>
.
– Peter Krauss
Oct 6 '16 at 4:57
add a comment |
I guess I'm a bit late to the party but I have written a small function to accomplish this task. It also takes care of attributes, text content and even if multiple nodes with the same node-name are siblings.
Dislaimer:
I'm not a PHP native, so please bear with simple mistakes.
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);
}
}
Usage example:
$xml = simplexml_load_file("myfile.xml");
echo xml2js($xml);
Example Input (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>
Example output:
{"family":[{"$":{"name":"Johnson"},"child":[{"$":{"name":"John","age":"5"},"toy":[{"$":{"status":"old"},"_":"Trooper"},{"$":{"status":"old"},"_":"Ultrablock"},{"$":{"status":"new"},"_":"Bike"}]}]}]}
Pretty printed:
{
"family" : [{
"$" : {
"name" : "Johnson"
},
"child" : [{
"$" : {
"name" : "John",
"age" : "5"
},
"toy" : [{
"$" : {
"status" : "old"
},
"_" : "Trooper"
}, {
"$" : {
"status" : "old"
},
"_" : "Ultrablock"
}, {
"$" : {
"status" : "new"
},
"_" : "Bike"
}
]
}
]
}
]
}
Quirks to keep in mind:
Several tags with the same tagname can be siblings. Other solutions will most likely drop all but the last sibling. To avoid this each and every single node, even if it only has one child, is an array which hold an object for each instance of the tagname. (See multiple "" elements in example)
Even the root element, of which only one should exist in a valid XML document is stored as array with an object of the instance, just to have a consistent data structure.
To be able to distinguish between XML node content and XML attributes each objects attributes are stored in the "$" and the content in the "_" child.
Edit:
I forgot to show the output for your example input data
{
"states" : [{
"state" : [{
"$" : {
"id" : "AL"
},
"name" : [{
"_" : "Alabama"
}
]
}, {
"$" : {
"id" : "AK"
},
"name" : [{
"_" : "Alaska"
}
]
}
]
}
]
}
Can it parse large XML data?
– Volatil3
Mar 1 '16 at 18:09
This solution is better because not discards XML attributes. See also why this complex structure is better than simplified ones, at xml.com/lpt/a/1658 (see "Semi-Structured XML").... Ops, for CDATA, as @txyoji suggested to flatten CDATA elements$xml = simplexml_load_file("myfile.xml",'SimpleXMLElement',LIBXML_NOCDATA);
.
– Peter Krauss
Oct 6 '16 at 4:27
Oops BUG!!! losting order and grouping tags. Test with<states> <state>Alabama</state> <p>John</p> <state>Alaska</state> </states>
.
– Peter Krauss
Oct 6 '16 at 4:57
add a comment |
I guess I'm a bit late to the party but I have written a small function to accomplish this task. It also takes care of attributes, text content and even if multiple nodes with the same node-name are siblings.
Dislaimer:
I'm not a PHP native, so please bear with simple mistakes.
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);
}
}
Usage example:
$xml = simplexml_load_file("myfile.xml");
echo xml2js($xml);
Example Input (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>
Example output:
{"family":[{"$":{"name":"Johnson"},"child":[{"$":{"name":"John","age":"5"},"toy":[{"$":{"status":"old"},"_":"Trooper"},{"$":{"status":"old"},"_":"Ultrablock"},{"$":{"status":"new"},"_":"Bike"}]}]}]}
Pretty printed:
{
"family" : [{
"$" : {
"name" : "Johnson"
},
"child" : [{
"$" : {
"name" : "John",
"age" : "5"
},
"toy" : [{
"$" : {
"status" : "old"
},
"_" : "Trooper"
}, {
"$" : {
"status" : "old"
},
"_" : "Ultrablock"
}, {
"$" : {
"status" : "new"
},
"_" : "Bike"
}
]
}
]
}
]
}
Quirks to keep in mind:
Several tags with the same tagname can be siblings. Other solutions will most likely drop all but the last sibling. To avoid this each and every single node, even if it only has one child, is an array which hold an object for each instance of the tagname. (See multiple "" elements in example)
Even the root element, of which only one should exist in a valid XML document is stored as array with an object of the instance, just to have a consistent data structure.
To be able to distinguish between XML node content and XML attributes each objects attributes are stored in the "$" and the content in the "_" child.
Edit:
I forgot to show the output for your example input data
{
"states" : [{
"state" : [{
"$" : {
"id" : "AL"
},
"name" : [{
"_" : "Alabama"
}
]
}, {
"$" : {
"id" : "AK"
},
"name" : [{
"_" : "Alaska"
}
]
}
]
}
]
}
I guess I'm a bit late to the party but I have written a small function to accomplish this task. It also takes care of attributes, text content and even if multiple nodes with the same node-name are siblings.
Dislaimer:
I'm not a PHP native, so please bear with simple mistakes.
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);
}
}
Usage example:
$xml = simplexml_load_file("myfile.xml");
echo xml2js($xml);
Example Input (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>
Example output:
{"family":[{"$":{"name":"Johnson"},"child":[{"$":{"name":"John","age":"5"},"toy":[{"$":{"status":"old"},"_":"Trooper"},{"$":{"status":"old"},"_":"Ultrablock"},{"$":{"status":"new"},"_":"Bike"}]}]}]}
Pretty printed:
{
"family" : [{
"$" : {
"name" : "Johnson"
},
"child" : [{
"$" : {
"name" : "John",
"age" : "5"
},
"toy" : [{
"$" : {
"status" : "old"
},
"_" : "Trooper"
}, {
"$" : {
"status" : "old"
},
"_" : "Ultrablock"
}, {
"$" : {
"status" : "new"
},
"_" : "Bike"
}
]
}
]
}
]
}
Quirks to keep in mind:
Several tags with the same tagname can be siblings. Other solutions will most likely drop all but the last sibling. To avoid this each and every single node, even if it only has one child, is an array which hold an object for each instance of the tagname. (See multiple "" elements in example)
Even the root element, of which only one should exist in a valid XML document is stored as array with an object of the instance, just to have a consistent data structure.
To be able to distinguish between XML node content and XML attributes each objects attributes are stored in the "$" and the content in the "_" child.
Edit:
I forgot to show the output for your example input data
{
"states" : [{
"state" : [{
"$" : {
"id" : "AL"
},
"name" : [{
"_" : "Alabama"
}
]
}, {
"$" : {
"id" : "AK"
},
"name" : [{
"_" : "Alaska"
}
]
}
]
}
]
}
answered Jun 9 '15 at 13:14
FTav
252310
252310
Can it parse large XML data?
– Volatil3
Mar 1 '16 at 18:09
This solution is better because not discards XML attributes. See also why this complex structure is better than simplified ones, at xml.com/lpt/a/1658 (see "Semi-Structured XML").... Ops, for CDATA, as @txyoji suggested to flatten CDATA elements$xml = simplexml_load_file("myfile.xml",'SimpleXMLElement',LIBXML_NOCDATA);
.
– Peter Krauss
Oct 6 '16 at 4:27
Oops BUG!!! losting order and grouping tags. Test with<states> <state>Alabama</state> <p>John</p> <state>Alaska</state> </states>
.
– Peter Krauss
Oct 6 '16 at 4:57
add a comment |
Can it parse large XML data?
– Volatil3
Mar 1 '16 at 18:09
This solution is better because not discards XML attributes. See also why this complex structure is better than simplified ones, at xml.com/lpt/a/1658 (see "Semi-Structured XML").... Ops, for CDATA, as @txyoji suggested to flatten CDATA elements$xml = simplexml_load_file("myfile.xml",'SimpleXMLElement',LIBXML_NOCDATA);
.
– Peter Krauss
Oct 6 '16 at 4:27
Oops BUG!!! losting order and grouping tags. Test with<states> <state>Alabama</state> <p>John</p> <state>Alaska</state> </states>
.
– Peter Krauss
Oct 6 '16 at 4:57
Can it parse large XML data?
– Volatil3
Mar 1 '16 at 18:09
Can it parse large XML data?
– Volatil3
Mar 1 '16 at 18:09
This solution is better because not discards XML attributes. See also why this complex structure is better than simplified ones, at xml.com/lpt/a/1658 (see "Semi-Structured XML").... Ops, for CDATA, as @txyoji suggested to flatten CDATA elements
$xml = simplexml_load_file("myfile.xml",'SimpleXMLElement',LIBXML_NOCDATA);
.– Peter Krauss
Oct 6 '16 at 4:27
This solution is better because not discards XML attributes. See also why this complex structure is better than simplified ones, at xml.com/lpt/a/1658 (see "Semi-Structured XML").... Ops, for CDATA, as @txyoji suggested to flatten CDATA elements
$xml = simplexml_load_file("myfile.xml",'SimpleXMLElement',LIBXML_NOCDATA);
.– Peter Krauss
Oct 6 '16 at 4:27
Oops BUG!!! losting order and grouping tags. Test with
<states> <state>Alabama</state> <p>John</p> <state>Alaska</state> </states>
.– Peter Krauss
Oct 6 '16 at 4:57
Oops BUG!!! losting order and grouping tags. Test with
<states> <state>Alabama</state> <p>John</p> <state>Alaska</state> </states>
.– Peter Krauss
Oct 6 '16 at 4:57
add a comment |
A common pitfall is to forget that json_encode()
does not respect elements with a textvalue and attribute(s). It will choose one of those, meaning dataloss.
The function below solves that problem. If one decides to go for the json_encode
/decode
way, the following function is advised.
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 ) );
by doing so, <foo bar="3">Lorem</foo>
will not end up as {"foo":"Lorem"}
in your JSON.
Does not compile and does not produce the described output if syntax-errors are corrected.
– Richard Kiefer
Jan 21 '15 at 10:36
What is$dom
? Where did that come from?
– Jake Wilson
Jan 26 '15 at 20:20
$dom = new DOMDocument(); is where it comes from
– Scott
Nov 25 '15 at 21:28
Last line of code: $json = json_decode( json_encode( $sxml ) ) ); should be : $json = json_decode( json_encode( $sxml ) );
– Charlie Smith
Feb 29 '16 at 2:46
Definite +1 for this - very important point!
– Tom Folk
Apr 18 '16 at 10:09
add a comment |
A common pitfall is to forget that json_encode()
does not respect elements with a textvalue and attribute(s). It will choose one of those, meaning dataloss.
The function below solves that problem. If one decides to go for the json_encode
/decode
way, the following function is advised.
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 ) );
by doing so, <foo bar="3">Lorem</foo>
will not end up as {"foo":"Lorem"}
in your JSON.
Does not compile and does not produce the described output if syntax-errors are corrected.
– Richard Kiefer
Jan 21 '15 at 10:36
What is$dom
? Where did that come from?
– Jake Wilson
Jan 26 '15 at 20:20
$dom = new DOMDocument(); is where it comes from
– Scott
Nov 25 '15 at 21:28
Last line of code: $json = json_decode( json_encode( $sxml ) ) ); should be : $json = json_decode( json_encode( $sxml ) );
– Charlie Smith
Feb 29 '16 at 2:46
Definite +1 for this - very important point!
– Tom Folk
Apr 18 '16 at 10:09
add a comment |
A common pitfall is to forget that json_encode()
does not respect elements with a textvalue and attribute(s). It will choose one of those, meaning dataloss.
The function below solves that problem. If one decides to go for the json_encode
/decode
way, the following function is advised.
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 ) );
by doing so, <foo bar="3">Lorem</foo>
will not end up as {"foo":"Lorem"}
in your JSON.
A common pitfall is to forget that json_encode()
does not respect elements with a textvalue and attribute(s). It will choose one of those, meaning dataloss.
The function below solves that problem. If one decides to go for the json_encode
/decode
way, the following function is advised.
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 ) );
by doing so, <foo bar="3">Lorem</foo>
will not end up as {"foo":"Lorem"}
in your JSON.
edited Jun 8 '17 at 4:43
mkaatman
4,31612144
4,31612144
answered Dec 10 '13 at 22:03
Coder Of Salvation
8711
8711
Does not compile and does not produce the described output if syntax-errors are corrected.
– Richard Kiefer
Jan 21 '15 at 10:36
What is$dom
? Where did that come from?
– Jake Wilson
Jan 26 '15 at 20:20
$dom = new DOMDocument(); is where it comes from
– Scott
Nov 25 '15 at 21:28
Last line of code: $json = json_decode( json_encode( $sxml ) ) ); should be : $json = json_decode( json_encode( $sxml ) );
– Charlie Smith
Feb 29 '16 at 2:46
Definite +1 for this - very important point!
– Tom Folk
Apr 18 '16 at 10:09
add a comment |
Does not compile and does not produce the described output if syntax-errors are corrected.
– Richard Kiefer
Jan 21 '15 at 10:36
What is$dom
? Where did that come from?
– Jake Wilson
Jan 26 '15 at 20:20
$dom = new DOMDocument(); is where it comes from
– Scott
Nov 25 '15 at 21:28
Last line of code: $json = json_decode( json_encode( $sxml ) ) ); should be : $json = json_decode( json_encode( $sxml ) );
– Charlie Smith
Feb 29 '16 at 2:46
Definite +1 for this - very important point!
– Tom Folk
Apr 18 '16 at 10:09
Does not compile and does not produce the described output if syntax-errors are corrected.
– Richard Kiefer
Jan 21 '15 at 10:36
Does not compile and does not produce the described output if syntax-errors are corrected.
– Richard Kiefer
Jan 21 '15 at 10:36
What is
$dom
? Where did that come from?– Jake Wilson
Jan 26 '15 at 20:20
What is
$dom
? Where did that come from?– Jake Wilson
Jan 26 '15 at 20:20
$dom = new DOMDocument(); is where it comes from
– Scott
Nov 25 '15 at 21:28
$dom = new DOMDocument(); is where it comes from
– Scott
Nov 25 '15 at 21:28
Last line of code: $json = json_decode( json_encode( $sxml ) ) ); should be : $json = json_decode( json_encode( $sxml ) );
– Charlie Smith
Feb 29 '16 at 2:46
Last line of code: $json = json_decode( json_encode( $sxml ) ) ); should be : $json = json_decode( json_encode( $sxml ) );
– Charlie Smith
Feb 29 '16 at 2:46
Definite +1 for this - very important point!
– Tom Folk
Apr 18 '16 at 10:09
Definite +1 for this - very important point!
– Tom Folk
Apr 18 '16 at 10:09
add a comment |
Try to use this
$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;
Or
You can use this library : https://github.com/rentpost/xml2array
add a comment |
Try to use this
$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;
Or
You can use this library : https://github.com/rentpost/xml2array
add a comment |
Try to use this
$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;
Or
You can use this library : https://github.com/rentpost/xml2array
Try to use this
$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;
Or
You can use this library : https://github.com/rentpost/xml2array
edited Sep 5 '17 at 20:11
answered Jun 25 '16 at 12:15
Ajay Kumar
1,102620
1,102620
add a comment |
add a comment |
Optimizing Antonio Max answer:
$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);
I used this approach, but JSON is empty. XML is valid.
– ryabenko-pro
Jan 9 '18 at 19:07
add a comment |
Optimizing Antonio Max answer:
$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);
I used this approach, but JSON is empty. XML is valid.
– ryabenko-pro
Jan 9 '18 at 19:07
add a comment |
Optimizing Antonio Max answer:
$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);
Optimizing Antonio Max answer:
$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);
answered Oct 18 '17 at 8:16
Marco Leuti
412
412
I used this approach, but JSON is empty. XML is valid.
– ryabenko-pro
Jan 9 '18 at 19:07
add a comment |
I used this approach, but JSON is empty. XML is valid.
– ryabenko-pro
Jan 9 '18 at 19:07
I used this approach, but JSON is empty. XML is valid.
– ryabenko-pro
Jan 9 '18 at 19:07
I used this approach, but JSON is empty. XML is valid.
– ryabenko-pro
Jan 9 '18 at 19:07
add a comment |
I've used Miles Johnson's TypeConverter for this purpose. It's installable using Composer.
You could write something like this using it:
<?php
require 'vendor/autoload.php';
use mjohnsonutilityTypeConverter;
$xml = file_get_contents("file.xml");
$arr = TypeConverter::xmlToArray($xml, TypeConverter::XML_GROUP);
echo json_encode($arr);
add a comment |
I've used Miles Johnson's TypeConverter for this purpose. It's installable using Composer.
You could write something like this using it:
<?php
require 'vendor/autoload.php';
use mjohnsonutilityTypeConverter;
$xml = file_get_contents("file.xml");
$arr = TypeConverter::xmlToArray($xml, TypeConverter::XML_GROUP);
echo json_encode($arr);
add a comment |
I've used Miles Johnson's TypeConverter for this purpose. It's installable using Composer.
You could write something like this using it:
<?php
require 'vendor/autoload.php';
use mjohnsonutilityTypeConverter;
$xml = file_get_contents("file.xml");
$arr = TypeConverter::xmlToArray($xml, TypeConverter::XML_GROUP);
echo json_encode($arr);
I've used Miles Johnson's TypeConverter for this purpose. It's installable using Composer.
You could write something like this using it:
<?php
require 'vendor/autoload.php';
use mjohnsonutilityTypeConverter;
$xml = file_get_contents("file.xml");
$arr = TypeConverter::xmlToArray($xml, TypeConverter::XML_GROUP);
echo json_encode($arr);
answered May 29 '13 at 13:59
Husky
3,73723133
3,73723133
add a comment |
add a comment |
This is an improvement of the most upvoted solution by Antonio Max, which also works with XML that has namespaces (by replacing the colon with an underscore). It also has some extra options (and does parse <person my-attribute='name'>John</person>
correctly).
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;
}
One does not use Regex to parse XML, unless it's a simple XML with trivial structure and very predictable data. I can't stress enough how bad this solution is. This BREAKS DATA. Not to mention that it's incredibly slow (you parse with regex, and then you re-parse again?) and doesn't handle self-closing tags.
– AlexanderMP
Feb 7 '17 at 16:19
I don't think you really looked at the function. It doesn't use regex to do the actual parsing, only as a simple fix to deal with namespaces - which has been working for all my xml cases - and that it is working is the most important, rather than being "politically correct". You're welcome to improve it if you want, though!
– TheStoryCoder
Feb 13 '17 at 21:39
The fact that it has worked for you doesn't mean it's right. It's code like this that generates bugs that are immensely hard to diagnose, and generates exploits. I mean even looking superficially at XML specs on sites like this w3schools.com/xml/xml_elements.asp show a lot of reasons why this solution wouldn't work. Like I said, it fails to detect self-closing tags like<element/>
, fails to address elements that start with, or contain underscores, which is allowed in XML. Fails to detect CDATA. And as I've said, it's SLOW. It's an O(n^2) complexity because of inner parsing.
– AlexanderMP
May 9 '17 at 17:41
The thing is that dealing with namespaces wasn't even asked here, and there are PROPER ways to deal with namespaces. Namespaces exist as a helpful construction, NOT to be parsed like that and turned into an abomination that won't be processed by any reasonable parser. And all you needed to do for that is not to create the contender for the prize of "slowest algorithm of 2016", but to do a bit of searching, to come up with a myriad of actual solutions, like this one stackoverflow.com/questions/16412047/… And to call this an improvement? Wow.
– AlexanderMP
May 9 '17 at 17:48
add a comment |
This is an improvement of the most upvoted solution by Antonio Max, which also works with XML that has namespaces (by replacing the colon with an underscore). It also has some extra options (and does parse <person my-attribute='name'>John</person>
correctly).
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;
}
One does not use Regex to parse XML, unless it's a simple XML with trivial structure and very predictable data. I can't stress enough how bad this solution is. This BREAKS DATA. Not to mention that it's incredibly slow (you parse with regex, and then you re-parse again?) and doesn't handle self-closing tags.
– AlexanderMP
Feb 7 '17 at 16:19
I don't think you really looked at the function. It doesn't use regex to do the actual parsing, only as a simple fix to deal with namespaces - which has been working for all my xml cases - and that it is working is the most important, rather than being "politically correct". You're welcome to improve it if you want, though!
– TheStoryCoder
Feb 13 '17 at 21:39
The fact that it has worked for you doesn't mean it's right. It's code like this that generates bugs that are immensely hard to diagnose, and generates exploits. I mean even looking superficially at XML specs on sites like this w3schools.com/xml/xml_elements.asp show a lot of reasons why this solution wouldn't work. Like I said, it fails to detect self-closing tags like<element/>
, fails to address elements that start with, or contain underscores, which is allowed in XML. Fails to detect CDATA. And as I've said, it's SLOW. It's an O(n^2) complexity because of inner parsing.
– AlexanderMP
May 9 '17 at 17:41
The thing is that dealing with namespaces wasn't even asked here, and there are PROPER ways to deal with namespaces. Namespaces exist as a helpful construction, NOT to be parsed like that and turned into an abomination that won't be processed by any reasonable parser. And all you needed to do for that is not to create the contender for the prize of "slowest algorithm of 2016", but to do a bit of searching, to come up with a myriad of actual solutions, like this one stackoverflow.com/questions/16412047/… And to call this an improvement? Wow.
– AlexanderMP
May 9 '17 at 17:48
add a comment |
This is an improvement of the most upvoted solution by Antonio Max, which also works with XML that has namespaces (by replacing the colon with an underscore). It also has some extra options (and does parse <person my-attribute='name'>John</person>
correctly).
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;
}
This is an improvement of the most upvoted solution by Antonio Max, which also works with XML that has namespaces (by replacing the colon with an underscore). It also has some extra options (and does parse <person my-attribute='name'>John</person>
correctly).
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;
}
edited Nov 30 '16 at 9:31
user5997037
52
52
answered Nov 29 '16 at 13:12
TheStoryCoder
1,01421140
1,01421140
One does not use Regex to parse XML, unless it's a simple XML with trivial structure and very predictable data. I can't stress enough how bad this solution is. This BREAKS DATA. Not to mention that it's incredibly slow (you parse with regex, and then you re-parse again?) and doesn't handle self-closing tags.
– AlexanderMP
Feb 7 '17 at 16:19
I don't think you really looked at the function. It doesn't use regex to do the actual parsing, only as a simple fix to deal with namespaces - which has been working for all my xml cases - and that it is working is the most important, rather than being "politically correct". You're welcome to improve it if you want, though!
– TheStoryCoder
Feb 13 '17 at 21:39
The fact that it has worked for you doesn't mean it's right. It's code like this that generates bugs that are immensely hard to diagnose, and generates exploits. I mean even looking superficially at XML specs on sites like this w3schools.com/xml/xml_elements.asp show a lot of reasons why this solution wouldn't work. Like I said, it fails to detect self-closing tags like<element/>
, fails to address elements that start with, or contain underscores, which is allowed in XML. Fails to detect CDATA. And as I've said, it's SLOW. It's an O(n^2) complexity because of inner parsing.
– AlexanderMP
May 9 '17 at 17:41
The thing is that dealing with namespaces wasn't even asked here, and there are PROPER ways to deal with namespaces. Namespaces exist as a helpful construction, NOT to be parsed like that and turned into an abomination that won't be processed by any reasonable parser. And all you needed to do for that is not to create the contender for the prize of "slowest algorithm of 2016", but to do a bit of searching, to come up with a myriad of actual solutions, like this one stackoverflow.com/questions/16412047/… And to call this an improvement? Wow.
– AlexanderMP
May 9 '17 at 17:48
add a comment |
One does not use Regex to parse XML, unless it's a simple XML with trivial structure and very predictable data. I can't stress enough how bad this solution is. This BREAKS DATA. Not to mention that it's incredibly slow (you parse with regex, and then you re-parse again?) and doesn't handle self-closing tags.
– AlexanderMP
Feb 7 '17 at 16:19
I don't think you really looked at the function. It doesn't use regex to do the actual parsing, only as a simple fix to deal with namespaces - which has been working for all my xml cases - and that it is working is the most important, rather than being "politically correct". You're welcome to improve it if you want, though!
– TheStoryCoder
Feb 13 '17 at 21:39
The fact that it has worked for you doesn't mean it's right. It's code like this that generates bugs that are immensely hard to diagnose, and generates exploits. I mean even looking superficially at XML specs on sites like this w3schools.com/xml/xml_elements.asp show a lot of reasons why this solution wouldn't work. Like I said, it fails to detect self-closing tags like<element/>
, fails to address elements that start with, or contain underscores, which is allowed in XML. Fails to detect CDATA. And as I've said, it's SLOW. It's an O(n^2) complexity because of inner parsing.
– AlexanderMP
May 9 '17 at 17:41
The thing is that dealing with namespaces wasn't even asked here, and there are PROPER ways to deal with namespaces. Namespaces exist as a helpful construction, NOT to be parsed like that and turned into an abomination that won't be processed by any reasonable parser. And all you needed to do for that is not to create the contender for the prize of "slowest algorithm of 2016", but to do a bit of searching, to come up with a myriad of actual solutions, like this one stackoverflow.com/questions/16412047/… And to call this an improvement? Wow.
– AlexanderMP
May 9 '17 at 17:48
One does not use Regex to parse XML, unless it's a simple XML with trivial structure and very predictable data. I can't stress enough how bad this solution is. This BREAKS DATA. Not to mention that it's incredibly slow (you parse with regex, and then you re-parse again?) and doesn't handle self-closing tags.
– AlexanderMP
Feb 7 '17 at 16:19
One does not use Regex to parse XML, unless it's a simple XML with trivial structure and very predictable data. I can't stress enough how bad this solution is. This BREAKS DATA. Not to mention that it's incredibly slow (you parse with regex, and then you re-parse again?) and doesn't handle self-closing tags.
– AlexanderMP
Feb 7 '17 at 16:19
I don't think you really looked at the function. It doesn't use regex to do the actual parsing, only as a simple fix to deal with namespaces - which has been working for all my xml cases - and that it is working is the most important, rather than being "politically correct". You're welcome to improve it if you want, though!
– TheStoryCoder
Feb 13 '17 at 21:39
I don't think you really looked at the function. It doesn't use regex to do the actual parsing, only as a simple fix to deal with namespaces - which has been working for all my xml cases - and that it is working is the most important, rather than being "politically correct". You're welcome to improve it if you want, though!
– TheStoryCoder
Feb 13 '17 at 21:39
The fact that it has worked for you doesn't mean it's right. It's code like this that generates bugs that are immensely hard to diagnose, and generates exploits. I mean even looking superficially at XML specs on sites like this w3schools.com/xml/xml_elements.asp show a lot of reasons why this solution wouldn't work. Like I said, it fails to detect self-closing tags like
<element/>
, fails to address elements that start with, or contain underscores, which is allowed in XML. Fails to detect CDATA. And as I've said, it's SLOW. It's an O(n^2) complexity because of inner parsing.– AlexanderMP
May 9 '17 at 17:41
The fact that it has worked for you doesn't mean it's right. It's code like this that generates bugs that are immensely hard to diagnose, and generates exploits. I mean even looking superficially at XML specs on sites like this w3schools.com/xml/xml_elements.asp show a lot of reasons why this solution wouldn't work. Like I said, it fails to detect self-closing tags like
<element/>
, fails to address elements that start with, or contain underscores, which is allowed in XML. Fails to detect CDATA. And as I've said, it's SLOW. It's an O(n^2) complexity because of inner parsing.– AlexanderMP
May 9 '17 at 17:41
The thing is that dealing with namespaces wasn't even asked here, and there are PROPER ways to deal with namespaces. Namespaces exist as a helpful construction, NOT to be parsed like that and turned into an abomination that won't be processed by any reasonable parser. And all you needed to do for that is not to create the contender for the prize of "slowest algorithm of 2016", but to do a bit of searching, to come up with a myriad of actual solutions, like this one stackoverflow.com/questions/16412047/… And to call this an improvement? Wow.
– AlexanderMP
May 9 '17 at 17:48
The thing is that dealing with namespaces wasn't even asked here, and there are PROPER ways to deal with namespaces. Namespaces exist as a helpful construction, NOT to be parsed like that and turned into an abomination that won't be processed by any reasonable parser. And all you needed to do for that is not to create the contender for the prize of "slowest algorithm of 2016", but to do a bit of searching, to come up with a myriad of actual solutions, like this one stackoverflow.com/questions/16412047/… And to call this an improvement? Wow.
– AlexanderMP
May 9 '17 at 17:48
add a comment |
If you would like to only convert a specific part of the XML to JSON, you can use XPath to retrieve this and convert that to 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);
?>
Please note that if you Xpath is incorrect, this will die with an error. So if you're debugging this through AJAX calls I recommend you log the response bodies as well.
add a comment |
If you would like to only convert a specific part of the XML to JSON, you can use XPath to retrieve this and convert that to 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);
?>
Please note that if you Xpath is incorrect, this will die with an error. So if you're debugging this through AJAX calls I recommend you log the response bodies as well.
add a comment |
If you would like to only convert a specific part of the XML to JSON, you can use XPath to retrieve this and convert that to 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);
?>
Please note that if you Xpath is incorrect, this will die with an error. So if you're debugging this through AJAX calls I recommend you log the response bodies as well.
If you would like to only convert a specific part of the XML to JSON, you can use XPath to retrieve this and convert that to 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);
?>
Please note that if you Xpath is incorrect, this will die with an error. So if you're debugging this through AJAX calls I recommend you log the response bodies as well.
answered Aug 27 '13 at 13:15
ChrisR
611817
611817
add a comment |
add a comment |
Looks like the $state->name
variable is holding an array. You can use
var_dump($state)
inside the foreach
to test that.
If that's the case, you can change the line inside the foreach
to
$states= array('state' => array_shift($state->name));
to correct it.
looks like the attributes are arrays but not $state->name
– Bryan Hadlock
Jan 12 '12 at 6:11
add a comment |
Looks like the $state->name
variable is holding an array. You can use
var_dump($state)
inside the foreach
to test that.
If that's the case, you can change the line inside the foreach
to
$states= array('state' => array_shift($state->name));
to correct it.
looks like the attributes are arrays but not $state->name
– Bryan Hadlock
Jan 12 '12 at 6:11
add a comment |
Looks like the $state->name
variable is holding an array. You can use
var_dump($state)
inside the foreach
to test that.
If that's the case, you can change the line inside the foreach
to
$states= array('state' => array_shift($state->name));
to correct it.
Looks like the $state->name
variable is holding an array. You can use
var_dump($state)
inside the foreach
to test that.
If that's the case, you can change the line inside the foreach
to
$states= array('state' => array_shift($state->name));
to correct it.
answered Jan 12 '12 at 5:46
Michael Fenwick
1,003717
1,003717
looks like the attributes are arrays but not $state->name
– Bryan Hadlock
Jan 12 '12 at 6:11
add a comment |
looks like the attributes are arrays but not $state->name
– Bryan Hadlock
Jan 12 '12 at 6:11
looks like the attributes are arrays but not $state->name
– Bryan Hadlock
Jan 12 '12 at 6:11
looks like the attributes are arrays but not $state->name
– Bryan Hadlock
Jan 12 '12 at 6:11
add a comment |
The question doesn't say it, but usually PHP is returning JSON to a web page.
I find it much easier to convert the XML to JSON in the browser/page via a JS lib, for example:
https://code.google.com/p/x2js/downloads/detail?name=x2js-v1.1.3.zip
add a comment |
The question doesn't say it, but usually PHP is returning JSON to a web page.
I find it much easier to convert the XML to JSON in the browser/page via a JS lib, for example:
https://code.google.com/p/x2js/downloads/detail?name=x2js-v1.1.3.zip
add a comment |
The question doesn't say it, but usually PHP is returning JSON to a web page.
I find it much easier to convert the XML to JSON in the browser/page via a JS lib, for example:
https://code.google.com/p/x2js/downloads/detail?name=x2js-v1.1.3.zip
The question doesn't say it, but usually PHP is returning JSON to a web page.
I find it much easier to convert the XML to JSON in the browser/page via a JS lib, for example:
https://code.google.com/p/x2js/downloads/detail?name=x2js-v1.1.3.zip
answered Dec 5 '13 at 15:27
Bret Weinraub
767513
767513
add a comment |
add a comment |
All solutions here have problems!
... When the representation need perfect XML interpretation (without problems with attributes) and to reproduce all text-tag-text-tag-text-... and order of tags. Also good remember here that JSON object "is an unordered set" (not repeat keys and the keys can't have predefined order)... Even ZF's xml2json is wrong (!) because not preserve exactly the XML structure.
All solutions here have problems with this simple XML,
<states x-x='1'>
<state y="123">Alabama</state>
My name is <b>John</b> Doe
<state>Alaska</state>
</states>
... @FTav solution seems better than 3-line solution, but also have little bug when tested with this XML.
Old solution is the best (for loss-less representation)
The solution, today well-known as jsonML, is used by Zorba project and others, and was first presented in ~2006 or ~2007, by (separately) Stephen McKamey and John Snelson.
// 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);
Produce
["states",{"x-x":"1"},
"nt ",
["state",{"y":"123"},"Alabama"],
"nttMy name is ",
["b","John"],
" Doent ",
["state","Alaska"],
"nt"
]
See http://jsonML.org or github.com/mckamey/jsonml. The production rules of this JSON are based on the element JSON-analog,
This syntax is a element definition and recurrence, with element-list ::= element ',' element-list | element
.
Very unusual xml structure that I doubt would have real life use cases.
– TheStoryCoder
Feb 13 '17 at 21:49
add a comment |
All solutions here have problems!
... When the representation need perfect XML interpretation (without problems with attributes) and to reproduce all text-tag-text-tag-text-... and order of tags. Also good remember here that JSON object "is an unordered set" (not repeat keys and the keys can't have predefined order)... Even ZF's xml2json is wrong (!) because not preserve exactly the XML structure.
All solutions here have problems with this simple XML,
<states x-x='1'>
<state y="123">Alabama</state>
My name is <b>John</b> Doe
<state>Alaska</state>
</states>
... @FTav solution seems better than 3-line solution, but also have little bug when tested with this XML.
Old solution is the best (for loss-less representation)
The solution, today well-known as jsonML, is used by Zorba project and others, and was first presented in ~2006 or ~2007, by (separately) Stephen McKamey and John Snelson.
// 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);
Produce
["states",{"x-x":"1"},
"nt ",
["state",{"y":"123"},"Alabama"],
"nttMy name is ",
["b","John"],
" Doent ",
["state","Alaska"],
"nt"
]
See http://jsonML.org or github.com/mckamey/jsonml. The production rules of this JSON are based on the element JSON-analog,
This syntax is a element definition and recurrence, with element-list ::= element ',' element-list | element
.
Very unusual xml structure that I doubt would have real life use cases.
– TheStoryCoder
Feb 13 '17 at 21:49
add a comment |
All solutions here have problems!
... When the representation need perfect XML interpretation (without problems with attributes) and to reproduce all text-tag-text-tag-text-... and order of tags. Also good remember here that JSON object "is an unordered set" (not repeat keys and the keys can't have predefined order)... Even ZF's xml2json is wrong (!) because not preserve exactly the XML structure.
All solutions here have problems with this simple XML,
<states x-x='1'>
<state y="123">Alabama</state>
My name is <b>John</b> Doe
<state>Alaska</state>
</states>
... @FTav solution seems better than 3-line solution, but also have little bug when tested with this XML.
Old solution is the best (for loss-less representation)
The solution, today well-known as jsonML, is used by Zorba project and others, and was first presented in ~2006 or ~2007, by (separately) Stephen McKamey and John Snelson.
// 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);
Produce
["states",{"x-x":"1"},
"nt ",
["state",{"y":"123"},"Alabama"],
"nttMy name is ",
["b","John"],
" Doent ",
["state","Alaska"],
"nt"
]
See http://jsonML.org or github.com/mckamey/jsonml. The production rules of this JSON are based on the element JSON-analog,
This syntax is a element definition and recurrence, with element-list ::= element ',' element-list | element
.
All solutions here have problems!
... When the representation need perfect XML interpretation (without problems with attributes) and to reproduce all text-tag-text-tag-text-... and order of tags. Also good remember here that JSON object "is an unordered set" (not repeat keys and the keys can't have predefined order)... Even ZF's xml2json is wrong (!) because not preserve exactly the XML structure.
All solutions here have problems with this simple XML,
<states x-x='1'>
<state y="123">Alabama</state>
My name is <b>John</b> Doe
<state>Alaska</state>
</states>
... @FTav solution seems better than 3-line solution, but also have little bug when tested with this XML.
Old solution is the best (for loss-less representation)
The solution, today well-known as jsonML, is used by Zorba project and others, and was first presented in ~2006 or ~2007, by (separately) Stephen McKamey and John Snelson.
// 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);
Produce
["states",{"x-x":"1"},
"nt ",
["state",{"y":"123"},"Alabama"],
"nttMy name is ",
["b","John"],
" Doent ",
["state","Alaska"],
"nt"
]
See http://jsonML.org or github.com/mckamey/jsonml. The production rules of this JSON are based on the element JSON-analog,
This syntax is a element definition and recurrence, with element-list ::= element ',' element-list | element
.
edited Oct 6 '16 at 13:26
answered Oct 6 '16 at 6:30
Peter Krauss
5,2931079169
5,2931079169
Very unusual xml structure that I doubt would have real life use cases.
– TheStoryCoder
Feb 13 '17 at 21:49
add a comment |
Very unusual xml structure that I doubt would have real life use cases.
– TheStoryCoder
Feb 13 '17 at 21:49
Very unusual xml structure that I doubt would have real life use cases.
– TheStoryCoder
Feb 13 '17 at 21:49
Very unusual xml structure that I doubt would have real life use cases.
– TheStoryCoder
Feb 13 '17 at 21:49
add a comment |
$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
just add those three lines you will get the correct output:-)
add a comment |
$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
just add those three lines you will get the correct output:-)
add a comment |
$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
just add those three lines you will get the correct output:-)
$xml = simplexml_load_string($xml_string);
$json = json_encode($xml);
$array = json_decode($json,TRUE);
just add those three lines you will get the correct output:-)
answered Apr 26 '18 at 5:46
karthik
1297
1297
add a comment |
add a comment |
After researching a little bit all of the answers, I came up with a solution that worked just fine with my JavaScript functions across browsers (Including consoles / Dev Tools) :
<?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' ) );
*/
?>
It basically creates a new DOMDocument, loads and XML file into it and traverses through each one of the nodes and children getting the data / parameters and exporting it into JSON without the annoying "@" signs.
Link to the XML file.
add a comment |
After researching a little bit all of the answers, I came up with a solution that worked just fine with my JavaScript functions across browsers (Including consoles / Dev Tools) :
<?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' ) );
*/
?>
It basically creates a new DOMDocument, loads and XML file into it and traverses through each one of the nodes and children getting the data / parameters and exporting it into JSON without the annoying "@" signs.
Link to the XML file.
add a comment |
After researching a little bit all of the answers, I came up with a solution that worked just fine with my JavaScript functions across browsers (Including consoles / Dev Tools) :
<?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' ) );
*/
?>
It basically creates a new DOMDocument, loads and XML file into it and traverses through each one of the nodes and children getting the data / parameters and exporting it into JSON without the annoying "@" signs.
Link to the XML file.
After researching a little bit all of the answers, I came up with a solution that worked just fine with my JavaScript functions across browsers (Including consoles / Dev Tools) :
<?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' ) );
*/
?>
It basically creates a new DOMDocument, loads and XML file into it and traverses through each one of the nodes and children getting the data / parameters and exporting it into JSON without the annoying "@" signs.
Link to the XML file.
answered Jul 6 '18 at 0:08
Xedret
870817
870817
add a comment |
add a comment |
$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);
}
}
}
It is a small and universal solution based on an array of data can be a JSON transformed json_decode ...lucky
– Octavio Perez Gallegos
Jun 30 '16 at 22:45
1
In what way does this answer the original question? Your answer seems more complicated than the original question, and also doesn't seem to even mention JSON anywhere.
– Dan Roche
Jun 30 '16 at 22:54
Sorry, I uploaded the implementation is to respond to the conversion of XML to any understandable to process a simple PHP json_encode arrangement. Sorry for the lack of clarity
– Octavio Perez Gallegos
Jul 26 '16 at 17:45
add a comment |
$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);
}
}
}
It is a small and universal solution based on an array of data can be a JSON transformed json_decode ...lucky
– Octavio Perez Gallegos
Jun 30 '16 at 22:45
1
In what way does this answer the original question? Your answer seems more complicated than the original question, and also doesn't seem to even mention JSON anywhere.
– Dan Roche
Jun 30 '16 at 22:54
Sorry, I uploaded the implementation is to respond to the conversion of XML to any understandable to process a simple PHP json_encode arrangement. Sorry for the lack of clarity
– Octavio Perez Gallegos
Jul 26 '16 at 17:45
add a comment |
$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);
}
}
}
$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);
}
}
}
answered Jun 30 '16 at 22:43
Octavio Perez Gallegos
11
11
It is a small and universal solution based on an array of data can be a JSON transformed json_decode ...lucky
– Octavio Perez Gallegos
Jun 30 '16 at 22:45
1
In what way does this answer the original question? Your answer seems more complicated than the original question, and also doesn't seem to even mention JSON anywhere.
– Dan Roche
Jun 30 '16 at 22:54
Sorry, I uploaded the implementation is to respond to the conversion of XML to any understandable to process a simple PHP json_encode arrangement. Sorry for the lack of clarity
– Octavio Perez Gallegos
Jul 26 '16 at 17:45
add a comment |
It is a small and universal solution based on an array of data can be a JSON transformed json_decode ...lucky
– Octavio Perez Gallegos
Jun 30 '16 at 22:45
1
In what way does this answer the original question? Your answer seems more complicated than the original question, and also doesn't seem to even mention JSON anywhere.
– Dan Roche
Jun 30 '16 at 22:54
Sorry, I uploaded the implementation is to respond to the conversion of XML to any understandable to process a simple PHP json_encode arrangement. Sorry for the lack of clarity
– Octavio Perez Gallegos
Jul 26 '16 at 17:45
It is a small and universal solution based on an array of data can be a JSON transformed json_decode ...lucky
– Octavio Perez Gallegos
Jun 30 '16 at 22:45
It is a small and universal solution based on an array of data can be a JSON transformed json_decode ...lucky
– Octavio Perez Gallegos
Jun 30 '16 at 22:45
1
1
In what way does this answer the original question? Your answer seems more complicated than the original question, and also doesn't seem to even mention JSON anywhere.
– Dan Roche
Jun 30 '16 at 22:54
In what way does this answer the original question? Your answer seems more complicated than the original question, and also doesn't seem to even mention JSON anywhere.
– Dan Roche
Jun 30 '16 at 22:54
Sorry, I uploaded the implementation is to respond to the conversion of XML to any understandable to process a simple PHP json_encode arrangement. Sorry for the lack of clarity
– Octavio Perez Gallegos
Jul 26 '16 at 17:45
Sorry, I uploaded the implementation is to respond to the conversion of XML to any understandable to process a simple PHP json_encode arrangement. Sorry for the lack of clarity
– Octavio Perez Gallegos
Jul 26 '16 at 17:45
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f8830599%2fphp-convert-xml-to-json%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
please post input and output. please var_dump $xml as well.
– David Chan
Jan 12 '12 at 5:39
Please include a snippet of the XML and the final array structure you have after parsing it. (A
var_dump
works fine.)– nikc.org
Jan 12 '12 at 5:39
added input, output and var_dump
– Bryan Hadlock
Jan 12 '12 at 6:15
Some applications need "perfec XML-to-JSON map", that is jsonML, see solution here.
– Peter Krauss
Oct 6 '16 at 14:19