Changeset 84

Show
Ignore:
Timestamp:
01/17/07 16:52:29 (2 years ago)
Author:
schst
Message:

Basic features of XMLSerializer

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/main/php/xml/serializer/annotations/XMLAttribute.php

    r32 r84  
    3636     */ 
    3737    public function setAttributeName($attributeName) { 
    38         $this->tagName = $tagName; 
     38        $this->attributeName = $attributeName; 
    3939    } 
    4040 
  • trunk/src/main/php/xml/serializer/annotations/XMLTag.php

    r32 r84  
    3636     * @var string 
    3737     */ 
    38     protected $elementTagName = 'element'
     38    protected $elementTagName = null
    3939 
    4040    /** 
  • trunk/src/main/php/xml/serializer/stubXMLSerializer.php

    r65 r84  
    99stubClassLoader::load('xml.serializer.annotations.XMLTag', 
    1010                      'xml.serializer.annotations.XMLAttribute', 
    11                       'xml.serializer.annotations.XMLIgnore'); 
     11                      'xml.serializer.annotations.XMLIgnore', 
     12                      'relection.stubReflection'); 
    1213 
    1314/** 
     
    1819 */ 
    1920class stubXMLSerializer extends stubBaseObject { 
     21 
     22    const OPT_ROOT_TAG    = 1; 
     23 
     24    /** 
     25     * Default options 
     26     * 
     27     * @var array 
     28     */ 
     29    private $defaultOpts = array( 
     30                      self::OPT_ROOT_TAG    => null, 
     31                    ); 
     32                     
     33    /** 
     34     * Currently used options 
     35     * 
     36     * @var array 
     37     */ 
     38    private $opts; 
    2039     
    2140    /** 
     
    2645     * @param array $opts                      Options to influence the serializing, not used yet 
    2746     */ 
    28     public function serialize($data, stubXMLStreamWriter $xmlWriter, $opt = array()) { 
     47    public function serialize($data, stubXMLStreamWriter $xmlWriter, $opts = array()) { 
     48 
     49        // set the currently used options 
     50        $this->opts = array_merge($this->defaultOpts, $opts); 
    2951         
    30         // TODO: dynamically determine the root name 
    31         $this->serializeDispatcher($data, $xmlWriter, 'root'); 
     52        $this->serializeDispatcher($data, $xmlWriter, $this->opts[self::OPT_ROOT_TAG]); 
    3253    } 
    3354 
     
    3960     * @param string $tagName                  The name of the XML tag 
    4061     */ 
    41     protected function serializeDispatcher($data, stubXMLStreamWriter $xmlWriter, $tagName) { 
    42          
    43         $xmlWriter->writeStartElement($tagName); 
     62    protected function serializeDispatcher($data, stubXMLStreamWriter $xmlWriter, $tagName = null) { 
     63        $this->depth++; 
    4464        switch (gettype($data)) { 
    4565            case 'NULL': 
     66                if ($tagName === null) { 
     67                    $tagName = 'null'; 
     68                } 
     69                $xmlWriter->writeStartElement($tagName); 
    4670                $xmlWriter->writeStartElement('null'); 
    4771                $xmlWriter->writeEndElement(); 
     72                $xmlWriter->writeEndElement(); 
    4873                break; 
    4974            case 'boolean': 
     75                if ($tagName === null) { 
     76                    $tagName = 'boolean'; 
     77                } 
     78                $xmlWriter->writeStartElement($tagName); 
    5079                $xmlWriter->writeText($data === true ? 'true' : false); 
     80                $xmlWriter->writeEndElement(); 
    5181                break; 
    5282            case 'string': 
    5383            case 'integer': 
    5484            case 'double': 
     85                if ($tagName === null) { 
     86                    $tagName = gettype($data); 
     87                } 
     88                $xmlWriter->writeStartElement($tagName); 
    5589                $xmlWriter->writeText(strval($data)); 
     90                $xmlWriter->writeEndElement(); 
    5691                break; 
    5792            case 'array': 
    58                 $this->serializeArray($data, $xmlWriter); 
    59                 break; 
     93                $this->serializeArray($data, $xmlWriter, $tagName); 
     94                break; 
     95            case 'object': 
     96                $this->serializeObject($data, $xmlWriter, $tagName); 
     97                break; 
     98        } 
     99        $this->depth--; 
     100    } 
     101 
     102    /** 
     103     * Serialize an object 
     104     * 
     105     * @param object $object 
     106     * @param stubXMLStreamWriter $xmlWriter 
     107     * @param string 
     108     */ 
     109    protected function serializeObject($object, stubXMLStreamWriter $xmlWriter, $tagName) { 
     110        $clazz = new stubReflectionClass(get_class($object)); 
     111         
     112        if ($tagName === null) { 
     113            if ($clazz->hasAnnotation('XMLTag')) { 
     114                $xmlTag = $clazz->getAnnotation('XMLTag'); 
     115                $tagName = $xmlTag->getTagName(); 
     116            } else { 
     117                $tagName = get_class($object); 
     118            } 
     119        } 
     120         
     121        $xmlWriter->writeStartElement($tagName); 
     122 
     123        // export props 
     124        $properties = $clazz->getProperties(); 
     125        foreach ($properties as $property) { 
     126            if ($property->hasAnnotation('XMLIgnore')) { 
     127                continue; 
     128            } 
     129            $propValue = $property->getValue($object); 
     130            if ($property->hasAnnotation('XMLAttribute')) { 
     131                $xmlAttribute = $property->getAnnotation('XMLAttribute'); 
     132                $xmlWriter->writeAttribute($xmlAttribute->getAttributeName(), (string)$propValue); 
     133                continue; 
     134            } 
     135            if ($property->hasAnnotation('XMLTag')) { 
     136                $xmlTag = $property->getAnnotation('XMLTag'); 
     137                 
     138                if (is_array($propValue)) { 
     139                    $this->serializeArray($propValue, $xmlWriter, $xmlTag->getTagName(), $xmlTag->getElementTagName()); 
     140                } else { 
     141                    $this->serializeDispatcher($propValue, $xmlWriter, $xmlTag->getTagName());                   
     142                } 
     143                continue; 
     144            } 
     145        } 
     146 
     147        // export methods 
     148        $methods = $clazz->getMethods(); 
     149        foreach ($methods as $method) { 
     150            if ($method->hasAnnotation('XMLIgnore')) { 
     151                continue; 
     152            } 
     153            $returnValue = $method->invoke($object); 
     154            if ($method->hasAnnotation('XMLAttribute')) { 
     155                $xmlAttribute = $method->getAnnotation('XMLAttribute'); 
     156                $xmlWriter->writeAttribute($xmlAttribute->getAttributeName(), (string)$returnValue); 
     157                continue; 
     158            } 
     159            if ($method->hasAnnotation('XMLTag')) { 
     160                $xmlTag = $method->getAnnotation('XMLTag'); 
     161                 
     162                if (is_array($returnValue)) { 
     163                    $this->serializeArray($returnValue, $xmlWriter, $xmlTag->getTagName(), $xmlTag->getElementTagName()); 
     164                } else { 
     165                    $this->serializeDispatcher($returnValue, $xmlWriter, $xmlTag->getTagName());                     
     166                } 
     167                continue; 
     168            } 
    60169        } 
    61170        $xmlWriter->writeEndElement(); 
     
    67176     * @param array $array 
    68177     * @param stubXMLStreamWriter $xmlWriter 
    69      */ 
    70     protected function serializeArray($array, stubXMLStreamWriter $xmlWriter) { 
     178     * @param string $tagName The 'root' name for the array 
     179     * @param string $defaultTag The default tag for indexed arrays 
     180     */ 
     181    protected function serializeArray($array, stubXMLStreamWriter $xmlWriter, $tagName, $defaultTag = null) { 
     182        if ($tagName === null) { 
     183            $tagName = 'array'; 
     184        } 
     185        $xmlWriter->writeStartElement($tagName); 
    71186        foreach ($array as $key => $value) { 
    72             $this->serializeDispatcher($value, $xmlWriter, $key); 
    73         } 
     187            if (is_int($key)) { 
     188                if (null === $defaultTag) { 
     189                   $this->serializeDispatcher($value, $xmlWriter); 
     190                } else { 
     191                    $this->serializeDispatcher($value, $xmlWriter, $defaultTag); 
     192                } 
     193            } else { 
     194                $this->serializeDispatcher($value, $xmlWriter, $key); 
     195            } 
     196        } 
     197        $xmlWriter->writeEndElement(); 
    74198    } 
    75199} 
  • trunk/src/test/php/xml/stubXMLSerializerTestCase.php

    r83 r84  
    1111 
    1212/** 
     13 * Simple Test class to test the XMLSerializer 
     14 * 
     15 * @XMLTag(tagName=foo) 
     16 */ 
     17class XMLSerializerFoo { 
     18     
     19    /** 
     20     * Scalar property 
     21     * 
     22     * @var int 
     23     * @XMLTag(tagName=bar) 
     24     */ 
     25    public $bar = 42; 
     26 
     27    /** 
     28     * Another scalar property 
     29     * 
     30     * @var string 
     31     * @XMLAttribute(attributeName=bar) 
     32     */ 
     33    public $scalar = "test"; 
     34 
     35    /** 
     36     * Should not be exported to XML 
     37     * 
     38     * @var string 
     39     * @XMLIgnore 
     40     */ 
     41    public $ignoreMe = 'Ignore'; 
     42} 
     43 
     44/** 
     45 * Simple Test class to test the XMLSerializer 
     46 * 
     47 * @XMLTag(tagName=container) 
     48 */ 
     49class XMLSerializerList { 
     50     
     51    /** 
     52     * Scalar property 
     53     * 
     54     * @var int 
     55     * @XMLTag(tagName=list,elementTagName=item) 
     56     */ 
     57    public $bar = array('one', 'two', 'three'); 
     58} 
     59 
     60/** 
     61 * Simple Test class to test the XMLSerializer 
     62 * 
     63 * @XMLTag(tagName=class) 
     64 */ 
     65class XMLSerializerMethods { 
     66     
     67    /** 
     68     * Return a value 
     69     * 
     70     * @return string 
     71     * @XMLAttribute(attributeName=method) 
     72     */ 
     73    public function getValue() { 
     74        return "returned"; 
     75    } 
     76} 
     77 
     78/** 
    1379 * Test for XMLSerializer 
    1480 * 
     
    36102    public function testNull() { 
    37103        $writer = new stubDomXMLStreamWriter(); 
    38         $this->serializer->serialize(null, $writer); 
     104        $this->serializer->serialize(null, $writer, array(stubXMLSerializer::OPT_ROOT_TAG => 'root')); 
    39105        $this->assertEqual('<?xml version="1.0" encoding="ISO-8859-1"?>' . "\n" . '<root><null/></root>' . "\n", $writer->asXML()); 
    40106    } 
     
    45111    public function testString() { 
    46112        $writer = new stubDomXMLStreamWriter(); 
    47         $this->serializer->serialize('This is a string.', $writer); 
     113        $this->serializer->serialize('This is a string.', $writer, array(stubXMLSerializer::OPT_ROOT_TAG => 'root')); 
    48114        $this->assertEqual('<?xml version="1.0" encoding="ISO-8859-1"?>' . "\n" . '<root>This is a string.</root>' . "\n", $writer->asXML()); 
    49115    } 
     
    54120    public function testInteger() { 
    55121        $writer = new stubDomXMLStreamWriter(); 
    56         $this->serializer->serialize(45, $writer); 
     122        $this->serializer->serialize(45, $writer, array(stubXMLSerializer::OPT_ROOT_TAG => 'root')); 
    57123        $this->assertEqual('<?xml version="1.0" encoding="ISO-8859-1"?>' . "\n" . '<root>45</root>' . "\n", $writer->asXML()); 
    58124    } 
     
    63129    public function testFloat() { 
    64130        $writer = new stubDomXMLStreamWriter(); 
    65         $this->serializer->serialize(2.352, $writer); 
     131        $this->serializer->serialize(2.352, $writer, array(stubXMLSerializer::OPT_ROOT_TAG => 'root')); 
    66132        $this->assertEqual('<?xml version="1.0" encoding="ISO-8859-1"?>' . "\n" . '<root>2.352</root>' . "\n", $writer->asXML()); 
    67133    } 
     
    72138    public function testBoolean() { 
    73139        $writer = new stubDomXMLStreamWriter(); 
    74         $this->serializer->serialize(true, $writer); 
     140        $this->serializer->serialize(true, $writer, array(stubXMLSerializer::OPT_ROOT_TAG => 'root')); 
    75141        $this->assertEqual('<?xml version="1.0" encoding="ISO-8859-1"?>' . "\n" . '<root>true</root>' . "\n", $writer->asXML()); 
    76142    } 
     
    85151                    'three' => 'four' 
    86152                 ); 
    87         $this->serializer->serialize($array, $writer); 
     153        $this->serializer->serialize($array, $writer, array(stubXMLSerializer::OPT_ROOT_TAG => 'root')); 
    88154        $this->assertEqual('<?xml version="1.0" encoding="ISO-8859-1"?>' . "\n" . '<root><one>two</one><three>four</three></root>' . "\n", $writer->asXML()); 
     155    } 
     156 
     157    /** 
     158     * Test serializing an indexed array 
     159     */ 
     160    public function testIndexedArray() { 
     161        $writer = new stubDomXMLStreamWriter(); 
     162        $array = array('one', 'two', 'three'); 
     163        $this->serializer->serialize($array, $writer, array(stubXMLSerializer::OPT_ROOT_TAG => 'root')); 
     164        $this->assertEqual('<?xml version="1.0" encoding="ISO-8859-1"?>' . "\n" . '<root><string>one</string><string>two</string><string>three</string></root>' . "\n", $writer->asXML()); 
    89165    } 
    90166 
     
    98174                    'three' => array('four' => 'five') 
    99175                 ); 
    100         $this->serializer->serialize($array, $writer); 
     176        $this->serializer->serialize($array, $writer, array(stubXMLSerializer::OPT_ROOT_TAG => 'root')); 
    101177        $this->assertEqual('<?xml version="1.0" encoding="ISO-8859-1"?>' . "\n" . '<root><one>two</one><three><four>five</four></three></root>' . "\n", $writer->asXML()); 
    102178    } 
     179 
     180    /** 
     181     * Test serializing an object 
     182     */ 
     183    public function testObject() { 
     184        $writer = new stubDomXMLStreamWriter(); 
     185        $obj = new XMLSerializerFoo(); 
     186        $this->serializer->serialize($obj, $writer); 
     187        $this->assertEqual('<?xml version="1.0" encoding="ISO-8859-1"?>' . "\n" . '<foo bar="test"><bar>42</bar></foo>' . "\n", $writer->asXML()); 
     188    } 
     189 
     190    /** 
     191     * Test serializing a nested object 
     192     */ 
     193    public function testNestedObject() { 
     194        $writer = new stubDomXMLStreamWriter(); 
     195        $obj = new XMLSerializerFoo(); 
     196        $obj->bar = new XMLSerializerFoo(); 
     197        $this->serializer->serialize($obj, $writer); 
     198        $this->assertEqual('<?xml version="1.0" encoding="ISO-8859-1"?>' . "\n" . '<foo bar="test"><bar bar="test"><bar>42</bar></bar></foo>' . "\n", $writer->asXML()); 
     199    } 
     200 
     201    /** 
     202     * Test serializing an object with an array property 
     203     */ 
     204    public function testArrayProperty() { 
     205        $writer = new stubDomXMLStreamWriter(); 
     206        $obj = new XMLSerializerList(); 
     207        $this->serializer->serialize($obj, $writer); 
     208        $this->assertEqual('<?xml version="1.0" encoding="ISO-8859-1"?>' . "\n" . '<container><list><item>one</item><item>two</item><item>three</item></list></container>' . "\n", $writer->asXML()); 
     209    } 
     210 
     211    /** 
     212     * Test serializing an object with methods 
     213     */ 
     214    public function testObjectMethods() { 
     215        $writer = new stubDomXMLStreamWriter(); 
     216        $obj = new XMLSerializerMethods(); 
     217        $this->serializer->serialize($obj, $writer); 
     218        $this->assertEqual('<?xml version="1.0" encoding="ISO-8859-1"?>' . "\n" . '<class method="returned"/>' . "\n", $writer->asXML()); 
     219    } 
    103220} 
    104221?>