Passed
Push — main ( 9da3ef...d17500 )
by Dante
01:29
created

XmlTrait::readXml()   B

Complexity

Conditions 8
Paths 42

Size

Total Lines 22
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 16
c 1
b 0
f 0
dl 0
loc 22
rs 8.4444
cc 8
nc 42
nop 2
1
<?php
2
declare(strict_types=1);
3
4
/**
5
 * BEdita, API-first content management framework
6
 * Copyright 2024 Atlas Srl, Chialab Srl
7
 *
8
 * This file is part of BEdita: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published
10
 * by the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
14
 */
15
namespace BEdita\ImportTools\Utility;
16
17
use Cake\Core\InstanceConfigTrait;
18
use XMLReader;
19
20
/**
21
 * Trait for share Xml stuff.
22
 *
23
 * This provides `readXml` method to progressively read a xml file element by element.
24
 *
25
 * Usage example:
26
 * ```php
27
 * use BEdita\ImportTools\Utility\XmlTrait;
28
 *
29
 * class MyImporter
30
 * {
31
 *     use XmlTrait;
32
 *
33
 *     public function import(string $filename): void
34
 *     {
35
 *         foreach ($this->readXml($filename, 'post') as $obj) {
36
 *             // process $obj
37
 *         }
38
 *     }
39
 * }
40
 * ```
41
 */
42
trait XmlTrait
43
{
44
    use InstanceConfigTrait;
45
    use FileTrait;
46
47
    /**
48
     * Progressively read a Xml file
49
     *
50
     * @param string $path Path to Xml file
51
     * @param string $element Element name for XML files
52
     * @return \Generator<array<array-key, string>>
53
     */
54
    protected function readXml(string $path, string $element): \Generator
55
    {
56
        try {
57
            $reader = new XMLReader();
58
            $reader->open($path);
59
            $process = true;
60
            while ($process) {
61
                while (!($reader->nodeType == XMLReader::ELEMENT && $reader->name == $element)) {
62
                    if (!$reader->read()) {
63
                        $process = false;
64
                        break;
65
                    }
66
                }
67
                if ($reader->nodeType == XMLReader::ELEMENT && $reader->name == $element) {
68
                    $xml = simplexml_load_string($reader->readOuterXml(), null, LIBXML_NOCDATA);
69
                    $json = json_encode($xml);
70
                    yield json_decode($json, true);
71
                    $reader->next();
72
                }
73
            }
74
        } catch (\Exception $e) {
75
            throw new \RuntimeException(sprintf('Cannot open file: %s', $path), 0, $e);
76
        }
77
    }
78
}
79