Completed
Push — master ( b6657b...e9ba9e )
by Rafael
02:42
created

XML2Array::init()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 1
eloc 4
nc 1
nop 3
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 \DOMDocument
36
     * @throws \InvalidArgumentException
37
     */
38
    public static function createArray($inputXml)
39
    {
40
        $xml = self::getXMLRoot();
41
        if (is_string($inputXml)) {
42
            $parsed = $xml->loadXML($inputXml);
43
            if (!$parsed) {
44
                throw new \InvalidArgumentException('[XML2Array] Error parsing the XML string.');
45
            }
46
        } else {
47
            if (get_class($inputXml) !== 'DOMDocument') {
48
                throw new \InvalidArgumentException('[XML2Array] The input XML object should be of type: DOMDocument.');
49
            }
50
            $xml = self::$xml = $inputXml;
51
        }
52
        $array = [];
53
        $array[$xml->documentElement->tagName] = self::convert($xml->documentElement);
54
        self::$xml = null;// clear the xml node in the class for 2nd time use.
55
56
        return $array;
57
    }
58
59
    /**
60
     * Convert an Array to XML
61
     *
62
     * @param mixed $node - XML as a string or as an object of DOMDocument
63
     *
64
     * @return mixed
65
     */
66
    private static function convert($node)
67
    {
68
        $output = [];
69
70
        switch ($node->nodeType) {
71
            case XML_CDATA_SECTION_NODE:
72
                $output[self::$prefixAttributes . 'cdata'] = trim($node->textContent);
73
                break;
74
75
            case XML_TEXT_NODE:
76
                $output = trim($node->textContent);
77
                break;
78
79
            case XML_ELEMENT_NODE:
80
                // for each child node, call the covert function recursively
81
                for ($i = 0, $m = $node->childNodes->length; $i < $m; $i++) {
82
                    $child = $node->childNodes->item($i);
83
                    $v = self::convert($child);
84
                    if (isset($child->tagName)) {
85
                        $t = $child->tagName;
86
87
                        // assume more nodes of same kind are coming
88
                        if (!array_key_exists($t, $output)) {
89
                            $output[$t] = [];
90
                        }
91
                        $output[$t][] = $v;
92
                    } else {
93
                        //check if it is not an empty text node
94
                        if ($v !== '') {
95
                            $output = $v;
96
                        }
97
                    }
98
                }
99
100
                if (is_array($output)) {
101
                    // if only one node of its kind, assign it directly instead if array($value);
102
                    foreach ($output as $t => $v) {
103
                        if (is_array($v) && count($v) === 1) {
104
                            $output[$t] = $v[0];
105
                        }
106
                    }
107
                    if (count($output) === 0) {
108
                        //for empty nodes
109
                        $output = '';
110
                    }
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] = (string)$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 = [self::$prefixAttributes . 'value' => $output];
122
                    }
123
                    $output[self::$prefixAttributes . 'attributes'] = $a;
124
                }
125
                break;
126
        }
127
128
        return $output;
129
    }
130
}