1 |
6657531f
|
Andreas Kohlbecker
|
<?php
|
2 |
|
|
/**
|
3 |
|
|
* @file
|
4 |
|
|
* This PHP class converts XML-based data into JSON formatted data.
|
5 |
|
|
*
|
6 |
|
|
* This program makes use of several open source PHP utility classes and
|
7 |
|
|
* functions.
|
8 |
|
|
*
|
9 |
|
|
* First Created on: Oct/04/2006
|
10 |
|
|
* Last Modified on: Oct/07/2006 (updated to Drupal coding standard Oct 19/2012)
|
11 |
|
|
*
|
12 |
|
|
* @licence
|
13 |
|
|
* This code is made available free of charge with the rights to use, copy,
|
14 |
|
|
* modify, merge, publish and distribute. This Software shall be used for
|
15 |
|
|
* Good, not Evil.
|
16 |
|
|
*/
|
17 |
|
|
|
18 |
|
|
module_load_include('php', 'cdm_api', 'json/JSON');
|
19 |
|
|
|
20 |
|
|
// Internal program-specific Debug option.
|
21 |
|
|
define("DEBUG", FALSE);
|
22 |
|
|
|
23 |
|
|
// Maximum Recursion Depth that we can allow.
|
24 |
|
|
define("MAX_RECURSION_DEPTH_ALLOWED", 25);
|
25 |
|
|
|
26 |
|
|
// An empty string.
|
27 |
|
|
define("EMPTY_STR", "");
|
28 |
|
|
|
29 |
|
|
// SimpleXMLElement object property name for attributes.
|
30 |
|
|
define("SIMPLE_XML_ELEMENT_OBJECT_PROPERTY_FOR_ATTRIBUTES", "@attributes");
|
31 |
|
|
|
32 |
|
|
// SimpleXMLElement object name.
|
33 |
|
|
define("SIMPLE_XML_ELEMENT_PHP_CLASS", "SimpleXMLElement");
|
34 |
|
|
|
35 |
|
|
class xml2json {
|
36 |
|
|
|
37 |
|
|
/**
|
38 |
|
|
* Transforms the XML based String data into JSON format.
|
39 |
|
|
*
|
40 |
|
|
* If the input XML string is in table format, the resulting JSON output
|
41 |
|
|
* will also be in table format. Conversely, if the input XML string is
|
42 |
|
|
* in tree format, the resulting JSON output will also be in tree format.
|
43 |
|
|
*
|
44 |
|
|
* @param string $xmlStringContents
|
45 |
|
|
* XML data string.
|
46 |
|
|
*
|
47 |
|
|
* @return mixed
|
48 |
|
|
* JSON.
|
49 |
|
|
*/
|
50 |
|
|
public static function transformXmlStringToJson($xmlStringContents) {
|
51 |
|
|
/*
|
52 |
|
|
Get the SimpleXMLElement representation of the function input
|
53 |
|
|
parameter that contains XML string. Convert the XML string
|
54 |
|
|
contents to SimpleXMLElement type. SimpleXMLElement type is
|
55 |
|
|
nothing but an object that can be processed with normal property
|
56 |
|
|
selectors and (associative) array iterators.
|
57 |
|
|
simplexml_load_string returns a SimpleXMLElement object which
|
58 |
|
|
contains an instance variable which itself is an associative array of
|
59 |
|
|
several SimpleXMLElement objects.
|
60 |
|
|
*/
|
61 |
|
|
$simpleXmlElementObject = simplexml_load_string($xmlStringContents);
|
62 |
|
|
|
63 |
|
|
if ($simpleXmlElementObject == NULL) {
|
64 |
|
|
return(EMPTY_STR);
|
65 |
|
|
}
|
66 |
|
|
|
67 |
|
|
$simpleXmlRootElementName = $simpleXmlElementObject->getName();
|
68 |
|
|
|
69 |
|
|
if (DEBUG) {
|
70 |
|
|
// Uncomment to see the inner details of
|
71 |
|
|
// the SimpleXMLElement object.
|
72 |
|
|
// var_dump($simpleXmlRootElementName);
|
73 |
|
|
// var_dump($simpleXmlElementObject);
|
74 |
|
|
}
|
75 |
|
|
|
76 |
|
|
$jsonOutput = EMPTY_STR;
|
77 |
|
|
// Let us convert the XML structure into PHP array structure.
|
78 |
|
|
$array1 = xml2json::convertSimpleXmlElementObjectIntoArray($simpleXmlElementObject);
|
79 |
|
|
|
80 |
|
|
if (($array1 != NULL) && (sizeof($array1) > 0)) {
|
81 |
|
|
// Create a new instance of Services_JSON.
|
82 |
|
|
$json = new Services_JSON();
|
83 |
|
|
$jsonOutput = $json->encode($array1);
|
84 |
|
|
|
85 |
|
|
if (DEBUG) {
|
86 |
|
|
// var_dump($array1);
|
87 |
|
|
// var_dump($jsonOutput);
|
88 |
|
|
}
|
89 |
|
|
}
|
90 |
|
|
/* End of if (($array1 != NULL) && (sizeof($array1) > 0)). */
|
91 |
|
|
|
92 |
|
|
return($jsonOutput);
|
93 |
|
|
}
|
94 |
|
|
/* End of function transformXmlStringToJson. */
|
95 |
|
|
|
96 |
|
|
/**
|
97 |
|
|
* Converts a SimpleXmlElementObject into an associative array.
|
98 |
|
|
*
|
99 |
|
|
* This function accepts a SimpleXmlElementObject as a single argument.
|
100 |
|
|
* If the input XML is in table format (i.e. non-nested), the resulting
|
101 |
|
|
* associative array will also be in a table format. Conversely, if the input
|
102 |
|
|
* XML is in tree (i.e. nested) format, this function will return an
|
103 |
|
|
* associative array (tree/nested) representation of that XML.
|
104 |
|
|
*
|
105 |
|
|
* There are so many ways to turn an XML document into a PHP array. Out of all
|
106 |
|
|
* those options, the recursive logic here uses a method that is very nicely
|
107 |
|
|
* documented by the PHP open source community in the SimpleXMLElement section
|
108 |
|
|
* of the PHP manual available at www.php.net. Credit goes to all those kind
|
109 |
|
|
* PHP (People Helping People!!!) souls.
|
110 |
|
|
*
|
111 |
|
|
* Caution and Remarks: IT IS A RECURSIVE FUNCTION.
|
112 |
|
|
*
|
113 |
|
|
* @param mixed $simpleXmlElementObject
|
114 |
|
|
* Simple XML Element Object.
|
115 |
|
|
* @param int $recursionDepth
|
116 |
|
|
* Needs to be used only when this function is called recursively. It can
|
117 |
|
|
* be omitted when this function is called from another function.
|
118 |
|
|
*
|
119 |
|
|
* @return array
|
120 |
|
|
* If everything is successful, it returns an associate array containing
|
121 |
|
|
* the data collected from the XML format. Otherwise, it returns NULL.
|
122 |
|
|
*/
|
123 |
|
|
public static function convertSimpleXmlElementObjectIntoArray($simpleXmlElementObject, &$recursionDepth = 0) {
|
124 |
|
|
// Keep an eye on how deeply we are involved in recursion.
|
125 |
|
|
if ($recursionDepth > MAX_RECURSION_DEPTH_ALLOWED) {
|
126 |
|
|
// Fatal error. Exit now.
|
127 |
|
|
return(NULL);
|
128 |
|
|
}
|
129 |
|
|
|
130 |
|
|
if ($recursionDepth == 0) {
|
131 |
|
|
if (get_class($simpleXmlElementObject) != SIMPLE_XML_ELEMENT_PHP_CLASS) {
|
132 |
|
|
// If the external caller doesn't call this function initially
|
133 |
|
|
// with a SimpleXMLElement object, return now.
|
134 |
|
|
return(NULL);
|
135 |
|
|
}
|
136 |
|
|
else {
|
137 |
|
|
// Store the original SimpleXmlElementObject sent by the caller.
|
138 |
|
|
// We will need it at the very end when we return from here for good.
|
139 |
|
|
$callerProvidedSimpleXmlElementObject = $simpleXmlElementObject;
|
140 |
|
|
}
|
141 |
|
|
}
|
142 |
|
|
/* End of if ($recursionDepth == 0) { */
|
143 |
|
|
|
144 |
|
|
if (get_class($simpleXmlElementObject) == SIMPLE_XML_ELEMENT_PHP_CLASS) {
|
145 |
|
|
|
146 |
|
|
// Get a copy of the simpleXmlElementObject.
|
147 |
|
|
$copyOfsimpleXmlElementObject = $simpleXmlElementObject;
|
148 |
|
|
|
149 |
|
|
// Get the object variables in the SimpleXmlElement object for us
|
150 |
|
|
// to iterate.
|
151 |
|
|
$simpleXmlElementObject = get_object_vars($simpleXmlElementObject);
|
152 |
|
|
}
|
153 |
|
|
|
154 |
|
|
// It needs to be an array of object variables.
|
155 |
|
|
if (is_array($simpleXmlElementObject)) {
|
156 |
|
|
|
157 |
|
|
// Initialize the result array.
|
158 |
|
|
$resultArray = array();
|
159 |
|
|
|
160 |
|
|
// Is the input array size 0? Then, we reached the rare CDATA text if any.
|
161 |
|
|
if (count($simpleXmlElementObject) <= 0) {
|
162 |
|
|
|
163 |
|
|
// Let us return the lonely CDATA. It could even be whitespaces.
|
164 |
|
|
return (trim(strval($copyOfsimpleXmlElementObject)));
|
165 |
|
|
}
|
166 |
|
|
|
167 |
|
|
// Let us walk through the child elements now.
|
168 |
|
|
foreach ($simpleXmlElementObject as $key => $value) {
|
169 |
|
|
// When this block of code is commented, XML attributes will be
|
170 |
|
|
// added to the result array.
|
171 |
|
|
// Uncomment the following block of code if XML attributes are
|
172 |
|
|
// NOT required to be returned as part of the result array.
|
173 |
|
|
/*
|
174 |
|
|
if((is_string($key)) && ($key == SIMPLE_XML_ELEMENT_OBJECT_PROPERTY_FOR_ATTRIBUTES)) {
|
175 |
|
|
continue;
|
176 |
|
|
}
|
177 |
|
|
*/
|
178 |
|
|
// Let us recursively process the current element we just visited.
|
179 |
|
|
// Increase the recursion depth by one.
|
180 |
|
|
$recursionDepth++;
|
181 |
|
|
$resultArray[$key] = xml2json::convertSimpleXmlElementObjectIntoArray($value, $recursionDepth);
|
182 |
|
|
|
183 |
|
|
// Decrease the recursion depth by one.
|
184 |
|
|
$recursionDepth--;
|
185 |
|
|
}
|
186 |
|
|
/* End of foreach($simpleXmlElementObject as $key=>$value) { */
|
187 |
|
|
|
188 |
|
|
if ($recursionDepth == 0) {
|
189 |
|
|
// That is it. We are heading to the exit now.
|
190 |
|
|
// Set the XML root element name as the root [top-level] key of
|
191 |
|
|
// the associative array that we are going to return to the caller of
|
192 |
|
|
// this recursive function.
|
193 |
|
|
$tempArray = $resultArray;
|
194 |
|
|
$resultArray = array();
|
195 |
|
|
$resultArray[$callerProvidedSimpleXmlElementObject->getName()] = $tempArray;
|
196 |
|
|
}
|
197 |
|
|
|
198 |
|
|
return ($resultArray);
|
199 |
|
|
}
|
200 |
|
|
else {
|
201 |
|
|
// We are now looking at either the XML attribute text or
|
202 |
|
|
// the text between the XML tags.
|
203 |
|
|
return (trim(strval($simpleXmlElementObject)));
|
204 |
|
|
}
|
205 |
|
|
/* End of else. */
|
206 |
|
|
|
207 |
|
|
}
|
208 |
|
|
/* End of function convertSimpleXmlElementObjectIntoArray. */
|
209 |
|
|
|
210 |
|
|
}
|
211 |
|
|
/* End of class xml2json. */
|