Skip to content

Commit a97d751

Browse files
mattvickClementGautier
authored andcommitted
Added support for encoding and decoding namespaced xml (xmlns)
1 parent a937c02 commit a97d751

File tree

2 files changed

+83
-5
lines changed

2 files changed

+83
-5
lines changed

Encoder/XmlEncoder.php

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,22 @@ public function decode($data, $format, array $context = array())
9999
// todo: throw an exception if the root node name is not correctly configured (bc)
100100

101101
if ($rootNode->hasChildNodes()) {
102-
return $this->parseXml($rootNode);
102+
103+
$xpath = new \DOMXPath($dom);
104+
$data = array();
105+
foreach ($xpath->query('namespace::*', $dom->documentElement) as $nsNode) {
106+
$data['@'.$nsNode->nodeName] = $nsNode->nodeValue;
107+
}
108+
109+
if (isset($data['@xmlns:xml'])) {
110+
unset($data['@xmlns:xml']);
111+
}
112+
113+
if (empty($data)) {
114+
return $this->parseXml($rootNode);
115+
}
116+
117+
return array_merge($data, (array) $this->parseXml($rootNode));
103118
}
104119

105120
if (!$rootNode->hasAttributes()) {
@@ -227,7 +242,7 @@ final protected function isElementNameValid($name)
227242
{
228243
return $name &&
229244
false === strpos($name, ' ') &&
230-
preg_match('#^[\pL_][\pL0-9._-]*$#ui', $name);
245+
preg_match('#^[\pL_][\pL0-9._:-]*$#ui', $name);
231246
}
232247

233248
/**
@@ -281,11 +296,11 @@ private function parseXmlAttributes(\DOMNode $node)
281296

282297
$data = array();
283298

284-
foreach ($node->attributes as $attrkey => $attr) {
299+
foreach ($node->attributes as $attr) {
285300
if (ctype_digit($attr->nodeValue)) {
286-
$data['@'.$attrkey] = (int) $attr->nodeValue;
301+
$data['@'.$attr->nodeName] = (int) $attr->nodeValue;
287302
} else {
288-
$data['@'.$attrkey] = $attr->nodeValue;
303+
$data['@'.$attr->nodeName] = $attr->nodeValue;
289304
}
290305
}
291306

Tests/Encoder/XmlEncoderTest.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,14 @@ public function testEncode()
203203
$this->assertEquals($source, $this->encoder->encode($obj, 'xml'));
204204
}
205205

206+
public function testEncodeWithNamespace()
207+
{
208+
$source = $this->getNamespacedXmlSource();
209+
$array = $this->getNamespacedArray();
210+
211+
$this->assertEquals($source, $this->encoder->encode($array, 'xml'));
212+
}
213+
206214
public function testEncodeSerializerXmlRootNodeNameOption()
207215
{
208216
$options = array('xml_root_node_name' => 'test');
@@ -253,6 +261,14 @@ public function testDecodeCdataWrappingAndWhitespace()
253261
$this->assertEquals($expected, $this->encoder->decode($xml, 'xml'));
254262
}
255263

264+
public function testDecodeWithNamespace()
265+
{
266+
$source = $this->getNamespacedXmlSource();
267+
$array = $this->getNamespacedArray();
268+
269+
$this->assertEquals($array, $this->encoder->decode($source, 'xml'));
270+
}
271+
256272
public function testDecodeScalarWithAttribute()
257273
{
258274
$source = '<?xml version="1.0"?>'."\n".
@@ -414,6 +430,53 @@ protected function getXmlSource()
414430
'</response>'."\n";
415431
}
416432

433+
protected function getNamespacedXmlSource()
434+
{
435+
return '<?xml version="1.0"?>'."\n".
436+
'<response xmlns="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app" xmlns:media="http://search.yahoo.com/mrss/" xmlns:gd="http://schemas.google.com/g/2005" xmlns:yt="http://gdata.youtube.com/schemas/2007">'.
437+
'<qux>1</qux>'.
438+
'<app:foo>foo</app:foo>'.
439+
'<yt:bar>a</yt:bar><yt:bar>b</yt:bar>'.
440+
'<media:baz><media:key>val</media:key><media:key2>val</media:key2><item key="A B">bar</item>'.
441+
'<item><title>title1</title></item><item><title>title2</title></item>'.
442+
'<Barry size="large"><FooBar gd:id="1"><Baz>Ed</Baz></FooBar></Barry></media:baz>'.
443+
'</response>'."\n";
444+
}
445+
446+
protected function getNamespacedArray()
447+
{
448+
return array(
449+
'@xmlns' => 'http://www.w3.org/2005/Atom',
450+
'@xmlns:app' => 'http://www.w3.org/2007/app',
451+
'@xmlns:media' => 'http://search.yahoo.com/mrss/',
452+
'@xmlns:gd' => 'http://schemas.google.com/g/2005',
453+
'@xmlns:yt' => 'http://gdata.youtube.com/schemas/2007',
454+
'qux' => "1",
455+
'app:foo' => "foo",
456+
'yt:bar' => array("a", "b"),
457+
'media:baz' => array(
458+
'media:key' => "val",
459+
'media:key2' => "val",
460+
'A B' => "bar",
461+
'item' => array(
462+
array(
463+
'title' => 'title1',
464+
),
465+
array(
466+
'title' => 'title2',
467+
)
468+
),
469+
'Barry' => array(
470+
'@size' => 'large',
471+
'FooBar' => array(
472+
'Baz' => 'Ed',
473+
'@gd:id' => 1,
474+
),
475+
),
476+
),
477+
);
478+
}
479+
417480
protected function getObject()
418481
{
419482
$obj = new Dummy();

0 commit comments

Comments
 (0)