Index: XML.php =================================================================== RCS file: /repository/pear/Structures_DataGrid/DataGrid/DataSource/XML.php,v retrieving revision 1.8 diff -u -r1.8 XML.php --- XML.php 23 Apr 2006 18:45:10 -0000 1.8 +++ XML.php 30 Jun 2006 09:44:09 -0000 @@ -29,6 +29,13 @@ * * "xpath": XPath to a subset of the XML data. * + * "fieldAttribute": Which Attribute of the XML source should be + * used as column field name (only used if the XML source has attributes). + * + * "labelAttribute": Which Attribute of the XML source should be + * used as column label (only used if "generate_columns" is true and the + * XML source has attributes). + * * @package Structures_DataGrid * @author Olivier Guilyardi * @category Structures @@ -44,7 +51,13 @@ function Structures_DataGrid_DataSource_XML() { parent::Structures_DataGrid_DataSource_Array(); - $this->_addDefaultOptions(array('xpath' => '')); + $this->_addDefaultOptions( + array( + 'xpath' => '', + 'fieldAttribute' => null, + 'labelAttribute' => null + ) + ); } /** @@ -79,7 +92,13 @@ // Instantiate XML_Unserializer Object $unserializer = &new XML_Unserializer(); $unserializer->setOption('parseAttributes', true); + // Set containers for attributes and content (for the case attributes are found) $unserializer->setOption('attributesArray', 'attributes'); + $unserializer->setOption('contentName', 'content'); + // Use fieldAttribute as item key, if fieldAttribute option set + if (!is_null($this->_options['fieldAttribute'])) { + $unserializer->setOption('keyAttribute', $this->_options['fieldAttribute']); + } // Unserialize the XML Data $test = $unserializer->unserialize($xml, false); @@ -98,16 +117,61 @@ return PEAR::raiseError('Unable to bind the xml data. '. 'You may want to set the \'xpath\' option.'); } - - $this->_ar[] = $row; + $this->_ar[] = $this->_processRow($row); } if ($this->_ar and !$this->_options['fields']) { - $this->setOptions(array('fields' => array_keys($this->_ar[0]))); + $this->setOption('fields', array_keys($this->_ar[0])); } return true; } + + /** + * Process XML row + * + * @access private + * @param array $row Row from unserializer data array + * @param string $keyPrefix Prepended to key, for recursive processing + * @return array of form: array($field1 => $value1, $field2 => $value2, ...) + */ + function _processRow($row, $keyPrefix='') + { + $rowProcessed = array(); + foreach ($row as $item => $info) { + $itemKey = $keyPrefix.$item; + switch (true) { + // Item has no attributes and unique tag name + case !is_array($info): + $rowProcessed[$itemKey] = $info; + break; + // Items with non-unique tag names, or fieldAttribute option is null + // Process array elements recursively as separate items + case !isset($info['attributes']): + $rowProcessed += $this->_processRow($info, $itemKey); + break; + // Attributes found: field attribute is already in item key + // extract label if option set and $this->_options['labels'] is empty + case !$this->_options['labels'] && + !is_null($this->_options['labelAttribute']): + if (isset($info['attributes'][$this->_options['labelAttribute']])) { + $labels[$itemKey] = $info['attributes'][$this->_options['labelAttribute']]; + } + else { + $labels[$itemKey] = $itemKey; + } + // no break here; we need the content! + default: + $rowProcessed[$itemKey] = isset($info['content']) + ? $info['content'] : ''; + } + } + // Set labels if extracted + if (!$this->_options['labels'] && isset($labels)) { + $this->setOption('labels', $labels); + } + return $rowProcessed; + } }