Xml::xpath()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 3.0327

Importance

Changes 0
Metric Value
cc 3
eloc 12
c 0
b 0
f 0
nc 4
nop 2
dl 0
loc 22
ccs 11
cts 13
cp 0.8462
crap 3.0327
rs 9.8666
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Derafu: Biblioteca PHP (Núcleo).
7
 * Copyright (C) Derafu <https://www.derafu.org>
8
 *
9
 * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10
 * bajo los términos de la Licencia Pública General Affero de GNU publicada por
11
 * la Fundación para el Software Libre, ya sea la versión 3 de la Licencia, o
12
 * (a su elección) cualquier versión posterior de la misma.
13
 *
14
 * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15
 * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16
 * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la Licencia Pública
17
 * General Affero de GNU para obtener una información más detallada.
18
 *
19
 * Debería haber recibido una copia de la Licencia Pública General Affero de GNU
20
 * junto a este programa.
21
 *
22
 * En caso contrario, consulte <http://www.gnu.org/licenses/agpl.html>.
23
 */
24
25
namespace Derafu\Lib\Core\Helper;
26
27
use DOMDocument;
28
use DOMNodeList;
29
use DOMXPath;
30
use InvalidArgumentException;
31
32
/**
33
 * Clase con utilidades para trabajar con strings XML.
34
 */
35
class Xml
36
{
37
    /**
38
     * Ejecuta una consulta XPath en un documento XML.
39
     *
40
     * @param string|DOMDocument $xml Documento XML a consultar.
41
     * @param string $expression Expresión XPath a ejecutar en el XML.
42
     * @return DOMNodeList Nodos resultantes de la consulta XPath.
43
     */
44 2
    public static function xpath(
45
        string|DOMDocument $xml,
46
        string $expression
47
    ): DOMNodeList {
48 2
        if (is_string($xml)) {
49
            $document = new DOMDocument();
50
            $document->loadXml($xml);
51
        } else {
52 2
            $document = $xml;
53
        }
54
55 2
        $xpath = new DOMXPath($document);
56 2
        $result = @$xpath->query($expression);
57
58 2
        if ($result === false) {
59 1
            throw new InvalidArgumentException(sprintf(
60 1
                'Expresión XPath inválida: %s',
61 1
                $expression
62 1
            ));
63
        }
64
65 1
        return $result;
66
    }
67
68
    /**
69
     * Sanitiza los valores que son asignados a los tags del XML.
70
     *
71
     * @param string $xml Texto que se asignará como valor al nodo XML.
72
     * @return string Texto sanitizado.
73
     */
74 38
    public static function sanitize(string $xml): string
75
    {
76
        // Si no se paso un texto o bien es un número no se hace nada.
77 38
        if (!$xml || is_numeric($xml)) {
78 8
            return $xml;
79
        }
80
81
        // Convertir "predefined entities" de XML.
82 33
        $replace = [
83 33
            '&amp;' => '&',
84 33
            '&#38;' => '&',
85 33
            '&lt;' => '<',
86 33
            '&#60;' => '<',
87 33
            '&gt;' => '>',
88 33
            '&#62' => '>',
89 33
            '&quot;' => '"',
90 33
            '&#34;' => '"',
91 33
            '&apos;' => '\'',
92 33
            '&#39;' => '\'',
93 33
        ];
94 33
        $xml = str_replace(array_keys($replace), array_values($replace), $xml);
95
96
        // Esto es a propósito, se deben volver a reemplazar.
97 33
        $xml = str_replace('&', '&amp;', $xml);
98
99
        /*$xml = str_replace(
100
            ['"', '\''],
101
            ['&quot;', '&apos;'],
102
            $xml
103
        );*/
104
105
        // Entregar texto sanitizado.
106 33
        return $xml;
107
    }
108
109
    /**
110
     * Corrige las entities '&apos;' y '&quot;' en el XML.
111
     *
112
     * La corrección se realiza solo dentro del contenido de tags del XML, pero
113
     * no en los atributos de los tags.
114
     *
115
     * @param string $xml XML a corregir.
116
     * @return string XML corregido.
117
     */
118 51
    public static function fixEntities(string $xml): string
119
    {
120 51
        $replace = [
121 51
            '\'' => '&apos;',
122 51
            '"' => '&quot;',
123 51
        ];
124 51
        $replaceFrom = array_keys($replace);
125 51
        $replaceTo = array_values($replace);
126
127 51
        $newXml = '';
128 51
        $n_chars = strlen($xml);
129 51
        $convert = false;
130
131 51
        for ($i = 0; $i < $n_chars; ++$i) {
132 48
            if ($xml[$i] === '>') {
133 48
                $convert = true;
134
            }
135 48
            if ($xml[$i] === '<') {
136 48
                $convert = false;
137
            }
138 48
            $newXml .= $convert
139 48
                ? str_replace($replaceFrom, $replaceTo, $xml[$i])
140 48
                : $xml[$i]
141 48
            ;
142
        }
143
144 51
        return $newXml;
145
    }
146
}
147