Completed
Push — fix_windows_test ( db6202...c04b37 )
by Adrien
04:02
created

SimpleXMLElement::getAttribute()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 8
rs 9.4285
ccs 5
cts 5
cp 1
cc 2
eloc 5
nc 2
nop 2
crap 2
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 93
    public function __construct($xmlData)
31
    {
32 93
        $this->useXMLInternalErrors();
33
34
        try {
35 93
            $this->simpleXMLElement = new \SimpleXMLElement($xmlData);
36 93
        } catch (\Exception $exception) {
37
            // if the data is invalid, the constructor will throw an Exception
38 6
            $this->resetXMLInternalErrorsSetting();
39 6
            throw new XMLProcessingException($this->getLastXMLErrorMessage());
40
        }
41
42 87
        $this->resetXMLInternalErrorsSetting();
43 87
    }
44
45
    /**
46
     * Returns the attribute for the given name.
47
     *
48
     * @param string $name Attribute name
49
     * @param string|null|void $namespace An optional namespace for the retrieved attributes
50
     * @return string|null The attribute value or NULL if attribute not found
51
     */
52 84
    public function getAttribute($name, $namespace = null)
53
    {
54 84
        $isPrefix = ($namespace !== null);
55 84
        $attributes = $this->simpleXMLElement->attributes($namespace, $isPrefix);
56 84
        $attributeValue = $attributes->{$name};
57
58 84
        return ($attributeValue !== null) ? (string) $attributeValue : null;
59
    }
60
61
    /**
62
     * Creates a prefix/ns context for the next XPath query
63
     * @see \SimpleXMLElement::registerXPathNamespace
64
     *
65
     * @param string $prefix The namespace prefix to use in the XPath query for the namespace given in "namespace".
66
     * @param string $namespace The namespace to use for the XPath query. This must match a namespace in
67
     *                          use by the XML document or the XPath query using "prefix" will not return any results.
68
     * @return bool TRUE on success or FALSE on failure.
69
     */
70 63
    public function registerXPathNamespace($prefix, $namespace)
71
    {
72 63
        return $this->simpleXMLElement->registerXPathNamespace($prefix, $namespace);
73
    }
74
75
    /**
76
     * Runs XPath query on XML data
77
     * @see \SimpleXMLElement::xpath
78
     *
79
     * @param string $path An XPath path
80
     * @return SimpleXMLElement[]|bool an array of SimpleXMLElement objects or FALSE in case of an error.
81
     */
82 66
    public function xpath($path)
83
    {
84 66
        $elements = $this->simpleXMLElement->xpath($path);
85
86 66
        if ($elements !== false) {
87 66
            $wrappedElements = [];
88 66
            foreach ($elements as $element) {
89 66
                $wrappedElement = $this->wrapSimpleXMLElement($element);
90
91 66
                if ($wrappedElement !== null) {
92 66
                    $wrappedElements[] = $this->wrapSimpleXMLElement($element);
93 66
                }
94 66
            }
95
96 66
            $elements = $wrappedElements;
97 66
        }
98
99 66
        return $elements;
100
    }
101
102
    /**
103
     * Wraps the given element into an instance of the wrapper
104
     *
105
     * @param \SimpleXMLElement $element Element to be wrapped
106
     * @return SimpleXMLElement|null The wrapped element or NULL if the given element is invalid
107
     */
108 69
    protected function wrapSimpleXMLElement(\SimpleXMLElement $element)
109
    {
110 69
        $wrappedElement = null;
111 69
        $elementAsXML = $element->asXML();
112
113 69
        if ($elementAsXML !== false) {
114 69
            $wrappedElement = new SimpleXMLElement($elementAsXML);
115 69
        }
116
117 69
        return $wrappedElement;
118
    }
119
120
    /**
121
     * Remove all nodes matching the given XPath query.
122
     * It does not map to any \SimpleXMLElement function.
123
     *
124
     * @param string $path An XPath path
125
     * @return void
126
     */
127 66
    public function removeNodesMatchingXPath($path)
128
    {
129 66
        $nodesToRemove = $this->simpleXMLElement->xpath($path);
130
131 66
        foreach ($nodesToRemove as $nodeToRemove) {
132 9
            unset($nodeToRemove[0]);
133 66
        }
134 66
    }
135
136
    /**
137
     * Returns the first child matching the given tag name
138
     *
139
     * @param string $tagName
140
     * @return SimpleXMLElement|null The first child matching the tag name or NULL if none found
141
     */
142 3
    public function getFirstChildByTagName($tagName)
143
    {
144 3
        $doesElementExist = isset($this->simpleXMLElement->{$tagName});
145
146
        /** @var \SimpleXMLElement $realElement */
147 3
        $realElement = $this->simpleXMLElement->{$tagName};
148
149 3
        return $doesElementExist ? $this->wrapSimpleXMLElement($realElement) : null;
150
    }
151
152
    /**
153
     * Returns the immediate children.
154
     *
155
     * @return array The children
156
     */
157
    public function children()
158
    {
159
        $children = [];
160
161
        foreach ($this->simpleXMLElement->children() as $child) {
162
            $children[] = $this->wrapSimpleXMLElement($child);
163
        }
164
165
        return $children;
166
    }
167
168
    /**
169
     * @return string
170
     */
171 63
    public function __toString()
172
    {
173 63
        return $this->simpleXMLElement->__toString();
174
    }
175
}
176