Completed
Push — master ( 163938...0052aa )
by Christopher
03:50
created

XML2Array   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 135
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 5
Bugs 0 Features 1
Metric Value
wmc 26
c 5
b 0
f 1
lcom 1
cbo 0
dl 0
loc 135
rs 10
1
<?php
2
namespace POData\UriProcessor;
3
4
class XML2Array
5
{
6
    /**
7
     * @var string
8
     */
9
    private static $encoding = 'UTF-8';
10
    /**
11
     * @var \DOMDocument
12
     */
13
    private static $xml = null;
14
    /**
15
     * Convert an XML to Array.
16
     *
17
     * @param string $input_xml
18
     *
19
     * @return array
20
     *
21
     * @throws \Exception
22
     */
23
    public static function createArray($input_xml)
24
    {
25
        if(!isset($input_xml) || 0 === strlen($input_xml){
0 ignored issues
show
Bug introduced by
Avoid IF statements that are always true or false
Loading history...
26
           return [];
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_RETURN
Loading history...
27
        }
28
        $xml = self::getXMLRoot();
29
        if (is_string($input_xml)) {
30
            try {
31
                $xml->loadXML($input_xml);
32
                if (!is_object($xml) || empty($xml->documentElement)) {
33
                    throw new \Exception();
34
                }
35
            } catch (\Exception $ex) {
36
                throw new \Exception('[XML2Array] Error parsing the XML string.' . PHP_EOL . $ex->getMessage());
37
            }
38
        } elseif (is_object($input_xml)) {
39
            if (get_class($input_xml) != 'DOMDocument') {
40
                throw new \Exception('[XML2Array] The input XML object should be of type: DOMDocument.');
41
            }
42
            $xml = self::$xml = $input_xml;
43
        } else {
44
            throw new \Exception('[XML2Array] Invalid input');
45
        }
46
        $array[$xml->documentElement->tagName] = self::convert($xml->documentElement);
47
        self::$xml = null; // clear the xml node in the class for 2nd time use.
48
        return $array;
49
    }
50
    /**
51
     * Initialize the root XML node [optional].
52
     *
53
     * @param string $version
54
     * @param string $encoding
55
     * @param bool   $standalone
56
     * @param bool   $format_output
57
     */
58
    public static function init($version = '1.0', $encoding = 'utf-8', $standalone = false, $format_output = true)
59
    {
60
        self::$xml = new \DomDocument($version, $encoding);
61
        self::$xml->xmlStandalone = $standalone;
62
        self::$xml->formatOutput = $format_output;
63
        self::$encoding = $encoding;
64
    }
65
    /**
66
     * Convert an Array to XML.
67
     *
68
     * @param \DOMNode $node - XML as a string or as an object of DOMDocument
69
     *
70
     * @return array
71
     */
72
    private static function convert(\DOMNode $node)
73
    {
74
        $output = [];
75
        switch ($node->nodeType) {
76
            case XML_CDATA_SECTION_NODE:
77
                $output['@cdata'] = trim($node->textContent);
78
                break;
79
            case XML_TEXT_NODE:
80
                $output = trim($node->textContent);
81
                break;
82
            case XML_ELEMENT_NODE:
83
                // for each child node, call the covert function recursively
84
                for ($i = 0, $m = $node->childNodes->length; $i < $m; ++$i) {
85
                    $child = $node->childNodes->item($i);
86
                    $v = self::convert($child);
87
                    if (isset($child->tagName)) {
88
                        $t = $child->tagName;
89
                        // assume more nodes of same kind are coming
90
                        if (!array_key_exists($t, $output)) {
91
                            $output[$t] = [];
92
                        }
93
                        $output[$t][] = $v;
94
                    } else {
95
                        //check if it is not an empty node
96
                        if (!empty($v)) {
97
                            $output = $v;
98
                        }
99
                    }
100
                }
101
                if (is_array($output)) {
102
                    // if only one node of its kind, assign it directly instead if array($value);
103
                    foreach ($output as $t => $v) {
104
                        if (is_array($v) && count($v) == 1) {
105
                            $output[$t] = $v[0];
106
                        }
107
                    }
108
                    if (empty($output)) {
109
                        //for empty nodes
110
                        $output = '';
111
                    }
112
                }
113
                // loop through the attributes and collect them
114
                if ($node->attributes->length) {
115
                    $a = [];
116
                    foreach ($node->attributes as $attrName => $attrNode) {
117
                        $a[$attrName] = $attrNode->value;
118
                    }
119
                    // if its an leaf node, store the value in @value instead of directly storing it.
120
                    if (!is_array($output)) {
121
                        $output = ['@value' => $output];
122
                    }
123
                    $output['@attributes'] = $a;
124
                }
125
                break;
126
        }
127
        return $output;
128
    }
129
    /**
130
     * Get the root XML node, if there isn't one, create it.
131
     *
132
     * @return \DOMDocument
133
     */
134
    private static function getXMLRoot()
135
    {
136
        if (empty(self::$xml)) {
137
            self::init();
138
        }
139
        return self::$xml;
140
    }
141
}
142