XMLConverter::recordElement()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 8
ccs 5
cts 5
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * League.Csv (https://csv.thephpleague.com)
5
 *
6
 * (c) Ignace Nyamagana Butera <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace League\Csv;
15
16
use DOMAttr;
17
use DOMDocument;
18
use DOMElement;
19
use DOMException;
20
21
/**
22
 * Converts tabular data into a DOMDocument object.
23
 */
24
class XMLConverter
25
{
26
    /**
27
     * XML Root name.
28
     *
29
     * @var string
30
     */
31
    protected $root_name = 'csv';
32
33
    /**
34
     * XML Node name.
35
     *
36
     * @var string
37
     */
38
    protected $record_name = 'row';
39
40
    /**
41
     * XML Item name.
42
     *
43
     * @var string
44
     */
45
    protected $field_name = 'cell';
46
47
    /**
48
     * XML column attribute name.
49
     *
50
     * @var string
51
     */
52
    protected $column_attr = '';
53
54
    /**
55
     * XML offset attribute name.
56
     *
57
     * @var string
58
     */
59
    protected $offset_attr = '';
60
61
    /**
62
     * Conversion method list.
63
     *
64
     * @var array
65
     */
66
    protected $encoder = [
67
        'field' => [
68
            true => 'fieldToElementWithAttribute',
69
            false => 'fieldToElement',
70
        ],
71
        'record' => [
72
            true => 'recordToElementWithAttribute',
73
            false => 'recordToElement',
74
        ],
75
    ];
76
77
    /**
78
     * Convert a Record collection into a DOMDocument.
79
     */
80 3
    public function convert(iterable $records): DOMDocument
81
    {
82 3
        $doc = new DOMDocument('1.0');
83 3
        $node = $this->import($records, $doc);
84 3
        $doc->appendChild($node);
85
86 3
        return $doc;
87
    }
88
89
    /**
90
     * Create a new DOMElement related to the given DOMDocument.
91
     *
92
     * **DOES NOT** attach to the DOMDocument
93
     */
94 3
    public function import(iterable $records, DOMDocument $doc): DOMElement
95
    {
96 3
        $field_encoder = $this->encoder['field']['' !== $this->column_attr];
97 3
        $record_encoder = $this->encoder['record']['' !== $this->offset_attr];
98 3
        $root = $doc->createElement($this->root_name);
99 3
        foreach ($records as $offset => $record) {
100 3
            $node = $this->$record_encoder($doc, $record, $field_encoder, $offset);
101 3
            $root->appendChild($node);
102
        }
103
104 3
        return $root;
105
    }
106
107
    /**
108
     * Convert a CSV record into a DOMElement and
109
     * adds its offset as DOMElement attribute.
110
     */
111 6
    protected function recordToElementWithAttribute(
112
        DOMDocument $doc,
113
        array $record,
114
        string $field_encoder,
115
        int $offset
116
    ): DOMElement {
117 6
        $node = $this->recordToElement($doc, $record, $field_encoder);
118 6
        $node->setAttribute($this->offset_attr, (string) $offset);
119
120 6
        return $node;
121
    }
122
123
    /**
124
     * Convert a CSV record into a DOMElement.
125
     */
126 6
    protected function recordToElement(DOMDocument $doc, array $record, string $field_encoder): DOMElement
127
    {
128 6
        $node = $doc->createElement($this->record_name);
129 6
        foreach ($record as $node_name => $value) {
130 6
            $item = $this->$field_encoder($doc, (string) $value, $node_name);
131 6
            $node->appendChild($item);
132
        }
133
134 6
        return $node;
135
    }
136
137
    /**
138
     * Convert Cell to Item.
139
     *
140
     * Convert the CSV item into a DOMElement and adds the item offset
141
     * as attribute to the returned DOMElement
142
     *
143
     * @param int|string $node_name
144
     */
145 6
    protected function fieldToElementWithAttribute(DOMDocument $doc, string $value, $node_name): DOMElement
146
    {
147 6
        $item = $this->fieldToElement($doc, $value);
148 6
        $item->setAttribute($this->column_attr, (string) $node_name);
149
150 6
        return $item;
151
    }
152
153
    /**
154
     * Convert Cell to Item.
155
     *
156
     * @param string $value Record item value
157
     */
158 6
    protected function fieldToElement(DOMDocument $doc, string $value): DOMElement
159
    {
160 6
        $item = $doc->createElement($this->field_name);
161 6
        $item->appendChild($doc->createTextNode($value));
162
163 6
        return $item;
164
    }
165
166
    /**
167
     * XML root element setter.
168
     */
169 9
    public function rootElement(string $node_name): self
170
    {
171 9
        $clone = clone $this;
172 9
        $clone->root_name = $this->filterElementName($node_name);
173
174 6
        return $clone;
175
    }
176
177
    /**
178
     * Filter XML element name.
179
     *
180
     * @throws DOMException If the Element name is invalid
181
     */
182 9
    protected function filterElementName(string $value): string
183
    {
184 9
        return (new DOMElement($value))->tagName;
185
    }
186
187
    /**
188
     * XML Record element setter.
189
     */
190 6
    public function recordElement(string $node_name, string $record_offset_attribute_name = ''): self
191
    {
192 6
        $clone = clone $this;
193 6
        $clone->record_name = $this->filterElementName($node_name);
194 6
        $clone->offset_attr = $this->filterAttributeName($record_offset_attribute_name);
195
196 6
        return $clone;
197
    }
198
199
    /**
200
     * Filter XML attribute name.
201
     *
202
     * @param string $value Element name
203
     *
204
     * @throws DOMException If the Element attribute name is invalid
205
     */
206 9
    protected function filterAttributeName(string $value): string
207
    {
208 9
        if ('' === $value) {
209 3
            return $value;
210
        }
211
212 6
        return (new DOMAttr($value))->name;
213
    }
214
215
    /**
216
     * XML Field element setter.
217
     */
218 6
    public function fieldElement(string $node_name, string $fieldname_attribute_name = ''): self
219
    {
220 6
        $clone = clone $this;
221 6
        $clone->field_name = $this->filterElementName($node_name);
222 6
        $clone->column_attr = $this->filterAttributeName($fieldname_attribute_name);
223
224 6
        return $clone;
225
    }
226
}
227