Skip to content

Commit 665dc94

Browse files
committed
feat: add XML parser
1 parent 24d59d5 commit 665dc94

File tree

2 files changed

+107
-0
lines changed

2 files changed

+107
-0
lines changed

src/XML.php

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace axios\tools;
6+
7+
class XML
8+
{
9+
public static function decode(string $xml_string): array
10+
{
11+
libxml_disable_entity_loader(true);
12+
13+
return json_decode(
14+
json_encode(
15+
simplexml_load_string($xml_string, 'SimpleXMLElement', LIBXML_NOCDATA)
16+
),
17+
true
18+
);
19+
}
20+
21+
/**
22+
* @param string $root_node <data></data>
23+
* @param array $root_attr <data attrs></data>
24+
* @param string $item_node <data><item></item></data>
25+
* @param string $item_key <data><item id=""></item></data>
26+
* @param string $encoding
27+
*/
28+
public static function encode(array $data, $root_node = 'data', $root_attr = [], $item_node = 'item', $item_key = 'id', $encoding = 'utf-8'): string
29+
{
30+
$attr = '';
31+
if (!empty($root_attr)) {
32+
$array = [];
33+
foreach ($root_attr as $key => $value) {
34+
$array[] = "{$key}=\"{$value}\"";
35+
}
36+
$attr = implode(' ', $array);
37+
}
38+
$attr = empty($attr) ? '' : " {trim({$attr})}";
39+
$xml = "<?xml version=\"1.0\" encoding=\"{$encoding}\"?>";
40+
$xml .= "<{$root_node}{$attr}>";
41+
$xml .= self::dataToXml($data, $item_node, $item_key);
42+
$xml .= "</{$root_node}>";
43+
44+
return $xml;
45+
}
46+
47+
/**
48+
* convert array to xml string.
49+
*
50+
* @param array $data array data
51+
* @param string $item <item></item>
52+
* @param string $id <item id=""></item>
53+
*/
54+
protected static function dataToXml(array $data, string $item, string $id): string
55+
{
56+
$xml = $attr = '';
57+
foreach ($data as $key => $val) {
58+
if (is_numeric($key)) {
59+
$id && $attr = " {$id}=\"{$key}\"";
60+
$key = $item;
61+
}
62+
$xml .= "<{$key}{$attr}>";
63+
$xml .= (\is_array($val) || \is_object($val)) ? self::dataToXml($val, $item, $id) : $val;
64+
$xml .= "</{$key}>";
65+
}
66+
67+
return $xml;
68+
}
69+
}

tests/unit/XMLTest.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace axios\tools\tests\unit;
6+
7+
use axios\tools\XML;
8+
use PHPUnit\Framework\TestCase;
9+
10+
/**
11+
* @internal
12+
* @coversNothing
13+
*/
14+
class XMLTest extends TestCase
15+
{
16+
public function test()
17+
{
18+
$data = [
19+
'foo' => 'bar',
20+
'bool' => true,
21+
'list' => [1, 2, 3, 4],
22+
'map' => ['a' => 'b', 'c' => 'd'],
23+
];
24+
$expected = '<?xml version="1.0" encoding="utf-8"?><data><foo>bar</foo><bool>1</bool><list><item id="0">1</item><item id="1">2</item><item id="2">3</item><item id="3">4</item></list><map><a>b</a><c>d</c></map></data>';
25+
$this->assertEquals(
26+
$expected,
27+
XML::encode($data)
28+
);
29+
$this->assertEquals([
30+
'foo' => 'bar',
31+
'bool' => true,
32+
'list' => [
33+
'item' => [1, 2, 3, 4],
34+
],
35+
'map' => ['a' => 'b', 'c' => 'd'],
36+
], XML::decode($expected));
37+
}
38+
}

0 commit comments

Comments
 (0)