Failed Conditions
Push — perf-tests ( 50942d...2fc93e )
by Adrien
14:53
created

SimpleXMLElement   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 162
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 2
Bugs 0 Features 1
Metric Value
wmc 18
c 2
b 0
f 1
lcom 1
cbo 2
dl 0
loc 162
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 16 2
A getAttribute() 0 8 2
A registerXPathNamespace() 0 4 1
A xpath() 0 19 4
A wrapSimpleXMLElement() 0 11 2
A removeNodesMatchingXPath() 0 8 2
A getFirstChildByTagName() 0 9 2
A children() 0 10 2
A __toString() 0 4 1
1
<?php
2
3
namespace Box\Spout\Reader\Wrapper;
4
5
use Box\Spout\Reader\Exception\XMLProcessingException;
6
7
8
/**
9
 * Class SimpleXMLElement
10
 * Wrapper around the built-in SimpleXMLElement. This class does not extend \SimpleXMLElement
11
 * because it its constructor is final... Instead, it is used as a passthrough.
12
 * @see \SimpleXMLElement
13
 *
14
 * @package Box\Spout\Reader\Wrapper
15
 */
16
class SimpleXMLElement
17
{
18
    use XMLInternalErrorsHelper;
19
20
    /** @var \SimpleXMLElement Instance of the wrapped SimpleXMLElement object */
21
    protected $simpleXMLElement;
22
23
    /**
24
     * Creates a new SimpleXMLElement object
25
     * @see \SimpleXMLElement::__construct
26
     *
27
     * @param string $xmlData A well-formed XML string
28
     * @throws \Box\Spout\Reader\Exception\XMLProcessingException If the XML string is not well-formed
29
     */
30
    public function __construct($xmlData)
31
    {
32
        $this->useXMLInternalErrors();
33
34
        try {
35
            $this->simpleXMLElement = new \SimpleXMLElement($xmlData);
36
        } catch (\Exception $exception) {
37
            // if the data is invalid, the constructor will throw an Exception
38
            $this->resetXMLInternalErrorsSetting();
39
            throw new XMLProcessingException($this->getLastXMLErrorMessage());
40
        }
41
42
        $this->resetXMLInternalErrorsSetting();
43
44
        return $this->simpleXMLElement;
45
    }
46
47
    /**
48
     * Returns the attribute for the given name.
49
     *
50
     * @param string $name Attribute name
51
     * @param string|null|void $namespace An optional namespace for the retrieved attributes
52
     * @return string|null The attribute value or NULL if attribute not found
53
     */
54
    public function getAttribute($name, $namespace = null)
55
    {
56
        $isPrefix = ($namespace !== null);
57
        $attributes = $this->simpleXMLElement->attributes($namespace, $isPrefix);
58
        $attributeValue = $attributes->{$name};
59
60
        return ($attributeValue !== null) ? (string) $attributeValue : null;
61
    }
62
63
    /**
64
     * Creates a prefix/ns context for the next XPath query
65
     * @see \SimpleXMLElement::registerXPathNamespace
66
     *
67
     * @param string $prefix The namespace prefix to use in the XPath query for the namespace given in "namespace".
68
     * @param string $namespace The namespace to use for the XPath query. This must match a namespace in
69
     *                          use by the XML document or the XPath query using "prefix" will not return any results.
70
     * @return bool TRUE on success or FALSE on failure.
71
     */
72
    public function registerXPathNamespace($prefix, $namespace)
73
    {
74
        return $this->simpleXMLElement->registerXPathNamespace($prefix, $namespace);
75
    }
76
77
    /**
78
     * Runs XPath query on XML data
79
     * @see \SimpleXMLElement::xpath
80
     *
81
     * @param string $path An XPath path
82
     * @return SimpleXMLElement[]|bool an array of SimpleXMLElement objects or FALSE in case of an error.
83
     */
84
    public function xpath($path)
85
    {
86
        $elements = $this->simpleXMLElement->xpath($path);
87
88
        if ($elements !== false) {
89
            $wrappedElements = [];
90
            foreach ($elements as $element) {
91
                $wrappedElement = $this->wrapSimpleXMLElement($element);
92
93
                if ($wrappedElement !== null) {
94
                    $wrappedElements[] = $this->wrapSimpleXMLElement($element);
95
                }
96
            }
97
98
            $elements = $wrappedElements;
99
        }
100
101
        return $elements;
102
    }
103
104
    /**
105
     * Wraps the given element into an instance of the wrapper
106
     *
107
     * @param \SimpleXMLElement $element Element to be wrapped
108
     * @return SimpleXMLElement|null The wrapped element or NULL if the given element is invalid
109
     */
110
    protected function wrapSimpleXMLElement(\SimpleXMLElement $element)
111
    {
112
        $wrappedElement = null;
113
        $elementAsXML = $element->asXML();
114
115
        if ($elementAsXML !== false) {
116
            $wrappedElement = new SimpleXMLElement($elementAsXML);
117
        }
118
119
        return $wrappedElement;
120
    }
121
122
    /**
123
     * Remove all nodes matching the given XPath query.
124
     * It does not map to any \SimpleXMLElement function.
125
     *
126
     * @param string $path An XPath path
127
     * @return void
128
     */
129
    public function removeNodesMatchingXPath($path)
130
    {
131
        $nodesToRemove = $this->simpleXMLElement->xpath($path);
132
133
        foreach ($nodesToRemove as $nodeToRemove) {
134
            unset($nodeToRemove[0]);
135
        }
136
    }
137
138
    /**
139
     * Returns the first child matching the given tag name
140
     *
141
     * @param string $tagName
142
     * @return SimpleXMLElement|null The first child matching the tag name or NULL if none found
143
     */
144
    public function getFirstChildByTagName($tagName)
145
    {
146
        $doesElementExist = isset($this->simpleXMLElement->{$tagName});
147
148
        /** @var \SimpleXMLElement $realElement */
149
        $realElement = $this->simpleXMLElement->{$tagName};
150
151
        return $doesElementExist ? $this->wrapSimpleXMLElement($realElement) : null;
152
    }
153
154
    /**
155
     * Returns the immediate children.
156
     *
157
     * @return array The children
158
     */
159
    public function children()
160
    {
161
        $children = [];
162
163
        foreach ($this->simpleXMLElement->children() as $child) {
164
            $children[] = $this->wrapSimpleXMLElement($child);
165
        }
166
167
        return $children;
168
    }
169
170
    /**
171
     * @return string
172
     */
173
    public function __toString()
174
    {
175
        return $this->simpleXMLElement->__toString();
176
    }
177
}
178