XML2Array   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 106
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 1
Bugs 1 Features 0
Metric Value
wmc 20
lcom 1
cbo 1
dl 0
loc 106
rs 10
c 1
b 1
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A createArray() 0 20 4
C convert() 0 64 16
1
<?php
2
3
/**
4
 * LICENSE: This file is subject to the terms and conditions defined in
5
 * file 'LICENSE', which is part of this source code package.
6
 *
7
 * @copyright 2016 Copyright(c) - All rights reserved.
8
 */
9
10
namespace Rafrsr\LibArray2Xml;
11
12
/**
13
 * XML2Array: A class to convert XML to array in PHP
14
 * It returns the array which can be converted back to XML using the Array2XML script
15
 * It takes an XML string or a DOMDocument object as an input.
16
 *
17
 * Based on http://www.lalit.org/lab/convert-xml-to-array-in-php-xml2array/
18
 *
19
 *  - some minor bug fixes
20
 *  - support for php7
21
 *  - tests
22
 *
23
 * Usage:
24
 *       $array = XML2Array::createArray($xml);
25
 */
26
class XML2Array
27
{
28
    use  CommonsTrait;
29
30
    /**
31
     * Convert an XML to Array
32
     *
33
     * @param string $inputXml - xml to convert
34
     *
35
     * @return array
36
     *
37
     * @throws \InvalidArgumentException
38
     */
39
    public static function createArray($inputXml)
40
    {
41
        $xml = self::getXMLRoot();
42
        if (is_string($inputXml)) {
43
            $parsed = $xml->loadXML($inputXml);
44
            if (!$parsed) {
45
                throw new \InvalidArgumentException('[XML2Array] Error parsing the XML string.');
46
            }
47
        } else {
48
            if (get_class($inputXml) !== 'DOMDocument') {
49
                throw new \InvalidArgumentException('[XML2Array] The input XML object should be of type: DOMDocument.');
50
            }
51
            $xml = self::$xml = $inputXml;
52
        }
53
        $array = [];
54
        $array[$xml->documentElement->tagName] = self::convert($xml->documentElement);
55
        self::$xml = null;// clear the xml node in the class for 2nd time use.
56
57
        return $array;
58
    }
59
60
    /**
61
     * Convert an Array to XML
62
     *
63
     * @param mixed $node - XML as a string or as an object of DOMDocument
64
     *
65
     * @return mixed
66
     */
67
    private static function convert($node)
68
    {
69
        $output = [];
70
71
        switch ($node->nodeType) {
72
            case XML_CDATA_SECTION_NODE:
73
                $output[self::$prefixAttributes . 'cdata'] = trim($node->textContent);
74
                break;
75
76
            case XML_TEXT_NODE:
77
                $output = trim($node->textContent);
78
                break;
79
80
            case XML_ELEMENT_NODE:
81
                // for each child node, call the covert function recursively
82
                for ($i = 0, $m = $node->childNodes->length; $i < $m; $i++) {
83
                    $child = $node->childNodes->item($i);
84
                    $v = self::convert($child);
85
                    if (isset($child->tagName)) {
86
                        $t = $child->tagName;
87
88
                        // assume more nodes of same kind are coming
89
                        if (!array_key_exists($t, $output)) {
90
                            $output[$t] = [];
91
                        }
92
                        $output[$t][] = $v;
93
                    } else {
94
                        //check if it is not an empty text node
95
                        if ($v !== '') {
96
                            $output = $v;
97
                        }
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 (count($output) === 0) {
109
                        //for empty nodes
110
                        $output = '';
111
                    }
112
                }
113
114
                // loop through the attributes and collect them
115
                if ($node->attributes->length) {
116
                    $a = [];
117
                    foreach ($node->attributes as $attrName => $attrNode) {
118
                        $a[$attrName] = (string)$attrNode->value;
119
                    }
120
                    // if its an leaf node, store the value in @value instead of directly storing it.
121
                    if (!is_array($output)) {
122
                        $output = [self::$prefixAttributes . 'value' => $output];
123
                    }
124
                    $output[self::$prefixAttributes . 'attributes'] = $a;
125
                }
126
                break;
127
        }
128
129
        return $output;
130
    }
131
}