Procházet zdrojové kódy

[Serializer] added the ability to add attributes to nodes using an array 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>
John Wards před 14 roky
rodič
revize
73cd26e2ca

+ 30 - 3
src/Symfony/Component/Serializer/Encoder/XmlEncoder.php

@@ -90,6 +90,11 @@ class XmlEncoder extends AbstractEncoder
         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;
             }
@@ -102,6 +107,11 @@ class XmlEncoder extends AbstractEncoder
                     $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;
             }
@@ -122,8 +132,25 @@ class XmlEncoder extends AbstractEncoder
 
         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 {
@@ -194,7 +221,7 @@ class XmlEncoder extends AbstractEncoder
             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);
         }

+ 31 - 3
tests/Symfony/Tests/Component/Serializer/Encoder/XmlEncoderTest.php

@@ -53,6 +53,33 @@ class XmlEncoderTest extends \PHPUnit_Framework_TestCase
         $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;
@@ -112,8 +139,9 @@ class XmlEncoderTest extends \PHPUnit_Framework_TestCase
         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";
     }
@@ -123,7 +151,7 @@ class XmlEncoderTest extends \PHPUnit_Framework_TestCase
         $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;
     }