Skip to content

Commit

Permalink
[Serializer] added the ability to add attributes to nodes using an ar…
Browse files Browse the repository at this point in the history
…ray key begining with @

Example:

array(
	'foo-bar' => array(
		'@id' => 1,
		'@name' => 'Bar'
	),
	Foo' => array(
		'Bar' => "Test",
		'@type' => 'test'
	)
)

Parse XML now creates @ attribites for the array.

$rss = array(
   "channel" => array(
     "title" => "Test RSS",
     "description" => "Test description",
     "item" => array(
       0 => array(
         "title" => "Test Title 1",
         "link" => "http://foo.com"
       ),
       1 => array(
         "title" => "Test Title 2",
         "link" => "http://bar.com"
       )
     )
   )
);

<channel>
    <title>Test RSS</title>
    <description>Test description</description>
    <item>
        <title>Test Title 1</title>
        <link>http://foo.com</link>
    </item>
    <item>
        <title>Test Title 2</title>
        <link>http://bar.com</title>
    </item>
</channel>
  • Loading branch information
johnwards authored and fabpot committed Feb 14, 2011
1 parent 8588d55 commit 73cd26e
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 6 deletions.
33 changes: 30 additions & 3 deletions src/Symfony/Component/Serializer/Encoder/XmlEncoder.php
Expand Up @@ -90,6 +90,11 @@ protected function parseXml($node)
foreach ($node->children() as $key => $subnode) {
if ($subnode->count()) {
$value = $this->parseXml($subnode);
if ($subnode->attributes()) {
foreach ($subnode->attributes() as $attrkey => $attr) {
$value['@'.$attrkey] = (string) $attr;
}
}
} else {
$value = (string) $subnode;
}
Expand All @@ -102,6 +107,11 @@ protected function parseXml($node)
$data[] = $tmp;
$data[] = $value;
}
} elseif (key_exists($key, $data)) {
if (false === is_array($data[$key])) {
$data[$key] = array($data[$key]);
}
$data[$key][] = $value;
} else {
$data[$key] = $value;
}
Expand All @@ -122,8 +132,25 @@ protected function buildXml($parentNode, $data)

if (is_array($data) || $data instanceof \Traversable) {
foreach ($data as $key => $data) {
if (is_array($data) && false === is_numeric($key)) {
$append = $this->appendNode($parentNode, $data, $key);
//Ah this is the magic @ attribute types.
if (strpos($key,"@")===0 && is_scalar($data) && $this->isElementNameValid($attributeName = substr($key,1))) {
$parentNode->setAttribute($attributeName, $data);
} elseif (is_array($data) && false === is_numeric($key)) {
/**
* Is this array fully numeric keys?
*/
if (ctype_digit( implode('', array_keys($data) ) )) {
/**
* Create nodes to append to $parentNode based on the $key of this array
* Produces <xml><item>0</item><item>1</item></xml>
* From array("item" => array(0,1));
*/
foreach ($data as $subData) {
$append = $this->appendNode($parentNode, $subData, $key);
}
} else {
$append = $this->appendNode($parentNode, $data, $key);
}
} elseif (is_numeric($key) || !$this->isElementNameValid($key)) {
$append = $this->appendNode($parentNode, $data, "item", $key);
} else {
Expand Down Expand Up @@ -194,7 +221,7 @@ protected function selectNodeType($node, $val)
return $this->appendCData($node, $val);
} elseif (is_bool($val)) {
return $this->appendText($node, (int) $val);
} elseif ($val instanceof \DOMNode){
} elseif ($val instanceof \DOMNode) {
$child = $this->dom->importNode($val, true);
$node->appendChild($child);
}
Expand Down
Expand Up @@ -53,6 +53,33 @@ public function testSetRootNodeName()
$this->assertEquals($expected, $this->encoder->encode($obj, 'xml'));
}

public function testAttributes()
{
$obj = new ScalarDummy;
$obj->xmlFoo = array(
'foo-bar' => array(
'@id' => 1,
'@name' => 'Bar'
),
'Foo' => array(
'Bar' => "Test",
'@Type' => 'test'
),
'föo_bär' => '',
"Bar" => array(1,2,3)
);
$expected = '<?xml version="1.0"?>'."\n".
'<response>'.
'<foo-bar id="1" name="Bar"/>'.
'<Foo Type="test"><Bar><![CDATA[Test]]></Bar></Foo>'.
'<föo_bär><![CDATA[]]></föo_bär>'.
'<Bar>1</Bar>'.
'<Bar>2</Bar>'.
'<Bar>3</Bar>'.
'</response>'."\n";
$this->assertEquals($expected, $this->encoder->encode($obj, 'xml'));
}

public function testElementNameValid()
{
$obj = new ScalarDummy;
Expand Down Expand Up @@ -112,8 +139,9 @@ protected function getXmlSource()
return '<?xml version="1.0"?>'."\n".
'<response>'.
'<foo><![CDATA[foo]]></foo>'.
'<bar><item key="0"><![CDATA[a]]></item><item key="1"><![CDATA[b]]></item></bar>'.
'<baz><key><![CDATA[val]]></key><key2><![CDATA[val]]></key2><item key="A B"><![CDATA[bar]]></item></baz>'.
'<bar><![CDATA[a]]></bar><bar><![CDATA[b]]></bar>'.
'<baz><key><![CDATA[val]]></key><key2><![CDATA[val]]></key2><item key="A B"><![CDATA[bar]]></item>'.
'<Barry><FooBar id="1"><Baz><![CDATA[Ed]]></Baz></FooBar></Barry></baz>'.
'<qux>1</qux>'.
'</response>'."\n";
}
Expand All @@ -123,7 +151,7 @@ protected function getObject()
$obj = new Dummy;
$obj->foo = 'foo';
$obj->bar = array('a', 'b');
$obj->baz = array('key' => 'val', 'key2' => 'val', 'A B' => 'bar');
$obj->baz = array('key' => 'val', 'key2' => 'val', 'A B' => 'bar', "Barry" => array('FooBar' => array("@id"=>1,"Baz"=>"Ed")));
$obj->qux = "1";
return $obj;
}
Expand Down

0 comments on commit 73cd26e

Please sign in to comment.