Completed
Push — master ( 752f4b...2fa01c )
by Adrien
02:37
created

SimpleXMLElement::children()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 0
cts 6
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 0
crap 6
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 96
    public function __construct($xmlData)
31
    {
32 96
        $this->useXMLInternalErrors();
33
34
        try {
35 96
            $this->simpleXMLElement = new \SimpleXMLElement($xmlData);
36 96
        } 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 90
        $this->resetXMLInternalErrorsSetting();
43 90
    }
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 87
    public function getAttribute($name, $namespace = null)
53
    {
54 87
        $isPrefix = ($namespace !== null);
55 87
        $attributes = $this->simpleXMLElement->attributes($namespace, $isPrefix);
56 87
        $attributeValue = $attributes->{$name};
57
58 87
        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 66
    public function registerXPathNamespace($prefix, $namespace)
71
    {
72 66
        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 69
    public function xpath($path)
83
    {
84 69
        $elements = $this->simpleXMLElement->xpath($path);
85
86 69
        if ($elements !== false) {
87 69
            $wrappedElements = [];
88 69
            foreach ($elements as $element) {
89 69
                $wrappedElement = $this->wrapSimpleXMLElement($element);
90
91 69
                if ($wrappedElement !== null) {
92 69
                    $wrappedElements[] = $this->wrapSimpleXMLElement($element);
93 69
                }
94 69
            }
95
96 69
            $elements = $wrappedElements;
97 69
        }
98
99 69
        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 72
    protected function wrapSimpleXMLElement(\SimpleXMLElement $element)
109
    {
110 72
        $wrappedElement = null;
111 72
        $elementAsXML = $element->asXML();
112
113 72
        if ($elementAsXML !== false) {
114 72
            $wrappedElement = new SimpleXMLElement($elementAsXML);
115 72
        }
116
117 72
        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 69
    public function removeNodesMatchingXPath($path)
128
    {
129 69
        $nodesToRemove = $this->simpleXMLElement->xpath($path);
130
131 69
        foreach ($nodesToRemove as $nodeToRemove) {
132 9
            unset($nodeToRemove[0]);
133 69
        }
134 69
    }
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
     * @return string
154
     */
155 66
    public function __toString()
156
    {
157 66
        return $this->simpleXMLElement->__toString();
158
    }
159
}
160