Completed
Pull Request — behat-2.x (#43)
by Timothée
02:50
created

Xml::isEqual()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
namespace Rezzza\RestApiBehatExtension\Xml;
4
5
class Xml
6
{
7
    private $content;
8
9
    public function __construct($content)
10
    {
11
        $this->parseXml($content);
12
        $this->content = $content;
13
    }
14
15
    public function read()
16
    {
17
        return $this->content;
18
    }
19
20
    public function pretty()
21
    {
22
        $dom = $this->parseXml($this->content);
23
        $dom->formatOutput = true;
24
25
        return $dom->saveXml();
26
    }
27
28
    public function isEqual(Xml $xml)
29
    {
30
        return $this->parseXml($this->content)->saveXml() === $this->parseXml($xml->read())->saveXml();
31
    }
32
33
    public function getNamespaces()
34
    {
35
        return simplexml_import_dom($this->parseXml($this->content))->getNamespaces(true);
36
    }
37
38
    public function xpath($element)
39
    {
40
        $dom = $this->parseXml($this->content);
41
        $xpath = new \DOMXpath($dom);
42
        $namespaces = $this->getNamespaces();
43
        $defaultNamespaceUri = $dom->lookupNamespaceURI(null);
44
        $defaultNamespacePrefix = $defaultNamespaceUri ? $dom->lookupPrefix($defaultNamespaceUri) : null;
45
        foreach ($namespaces as $prefix => $namespace) {
46
            if (empty($prefix) && empty($defaultNamespacePrefix) && !empty($defaultNamespaceUri)) {
47
                $prefix = 'rootns';
48
            }
49
            $xpath->registerNamespace($prefix, $namespace);
50
        }
51
52
        // "fix" queries to the default namespace if any namespaces are defined
53
        if (!empty($namespaces) && empty($defaultNamespacePrefix) && !empty($defaultNamespaceUri)) {
54
            for ($i=0; $i < 2; ++$i) {
55
                $element = preg_replace('/\/(\w+)(\[[^]]+\])?\//', '/rootns:$1$2/', $element);
56
            }
57
            $element = preg_replace('/\/(\w+)(\[[^]]+\])?$/', '/rootns:$1$2', $element);
58
        }
59
60
        return $xpath->query($element);
61
    }
62
63
    private function parseXml($content)
64
    {
65
        $dom = new \DomDocument();
66
        $dom->strictErrorChecking = false;
67
        $dom->validateOnParse = false;
68
        $dom->preserveWhiteSpace = false;
69
        $dom->formatOutput = false;
70
        $dom->loadXML($content, LIBXML_PARSEHUGE);
71
        $error = libxml_get_last_error();
72
        if (!empty($error)) {
73
            // https://bugs.php.net/bug.php?id=46465
74
            if ($error->message != 'Validation failed: no DTD found !') {
75
                throw new \DomException($error->message . ' at line ' . $error->line);
76
            }
77
        }
78
79
        return $dom;
80
    }
81
}
82