[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Phpgroupware-cvs] property/inc class.XmlToArray.inc.php
From: |
Sigurd Nes |
Subject: |
[Phpgroupware-cvs] property/inc class.XmlToArray.inc.php |
Date: |
Wed, 10 Jan 2007 13:28:45 +0000 |
CVSROOT: /sources/phpgroupware
Module name: property
Changes by: Sigurd Nes <sigurdne> 07/01/10 13:28:45
Modified files:
inc : class.XmlToArray.inc.php
Log message:
Simplify the output and added option to skip attributes
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/property/inc/class.XmlToArray.inc.php?cvsroot=phpgroupware&r1=1.1&r2=1.2
Patches:
Index: class.XmlToArray.inc.php
===================================================================
RCS file: /sources/phpgroupware/property/inc/class.XmlToArray.inc.php,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- class.XmlToArray.inc.php 9 Jan 2007 15:08:37 -0000 1.1
+++ class.XmlToArray.inc.php 10 Jan 2007 13:28:45 -0000 1.2
@@ -1,57 +1,66 @@
-<?
-
-define('XMLTOARRAY_VERSION','0.5');
+<?php
+ /**
+ * XmlToArray
+ * @author Rasmus Andersson address@hidden http://rasmusandersson.se/}
+ * @author Eric Rosebrock http://www.phpfreaks.com
+ * @author Sigurd Nes <address@hidden>
+ * @copyright Copyright (C) 2002-2007 Free Software Foundation, Inc.
http://www.fsf.org/
+ * @license http://www.gnu.org/licenses/gpl.html GNU General Public
License
+ * @package phpgwapi
+ * @subpackage xml
+ * @version $Id: class.XmlToArray.inc.php,v 1.2 2007/01/10 13:28:45
sigurdne Exp $
+ * @internal This class originated from: address@hidden AT:
http://www.devdump.com/phpxml.php
+ */
-/**
-* Parse XML to an array.
-*
-* Works about the same way as address@hidden XmlToArray} but returns a
slightly more complex/detailed structure.
-* Also, take a look at the ArrayToXml class - wich is the opposite to this
class.
-*
-* Part of parse() and _getChildren() originates from kris[at]h3x.com,
http://www.devdump.com/phpxml.php
-*
-* <b>Example</b><code>
-* require_once('XmlToArray2.php');
-* $xa = new XmlToArray2();
-* $a = $xa->parseFile('test.xml');
-* print_r( $a );</code>
-*
-* <b>Example</b><code>
-* require_once('XmlToArray2.php');
-* $xa = new XmlToArray2('utf-8');
-* $a = $xa->parse('<root><child name="test"><hello>Yes</hello><hello>'
-* .'Yes again</hello></child></root>');
-* print_r( $a );</code>
-*
-*
-* <b>Changelog</b>
-* - v0.1 - Implemented Kris's methods into the predecessor class XmlToArray
and cleaned up a bit.
-* - v0.2 - Added option for value-modifier callback function.
-* Added automatic utf8 decoding.
-* Whitespaces is now passed through core parser and handled
explicitly.
-* Added option for stripping off linebreaks.
-* Added build-in error logging and reporting.
-* Changed attribute and value keys to comform to generic standard.
(@ and #)
-* - v0.3 - Added option to include or not include empty values (#) -
default is not to include them.
-* ie: <tag foo="bar" />, <tag /> or <tag></tag> But not: <tag>
</tag>
-* Changed setValueModifier() to accept array(object, function)
type parameter or string.
-* - v0.4 - Improved error reporting and handling.
-* - v0.5 - Added the option to make all tags and attributes lower case or
upper case.
-*
-*
-* <b>Known issues</b>
-* - None at the moment
-* - Please send bug reports to rasmus[at]flajm.se
-*
-*
-* @version 0.5 / 2004-10-30
-* @author Rasmus Andersson address@hidden http://rasmusandersson.se/}
-* @see ArrayToXml
-* @package fuse
-* @subpackage data
-*/
-class XmlToArray {
+ /**
+ * Parse XML to an array.
+ *
+ * Works about the same way as address@hidden XmlToArray} but returns a
slightly more complex/detailed structure.
+ * Also, take a look at the ArrayToXml class - wich is the opposite to
this class.
+ *
+ * Part of parse() and _getChildren() originates from kris[at]h3x.com,
http://www.devdump.com/phpxml.php
+ *
+ * <b>Example</b><code>
+ * require_once('XmlToArray2.php');
+ * $xa = new XmlToArray2();
+ * $a = $xa->parseFile('test.xml');
+ * print_r( $a );</code>
+ *
+ * <b>Example</b><code>
+ * require_once('XmlToArray2.php');
+ * $xa = new XmlToArray2('utf-8');
+ * $a = $xa->parse('<root><child
name="test"><hello>Yes</hello><hello>'
+ * .'Yes
again</hello></child></root>');
+ * print_r( $a );</code>
+ *
+ *
+ * <b>Changelog</b>
+ * - v0.1 - Implemented Kris's methods into the predecessor class
XmlToArray and cleaned up a bit.
+ * - v0.2 - Added option for value-modifier callback function.
+ * Added automatic utf8 decoding.
+ * Whitespaces is now passed through core parser
and handled explicitly.
+ * Added option for stripping off linebreaks.
+ * Added build-in error logging and reporting.
+ * Changed attribute and value keys to comform to
generic standard. (@ and #)
+ * - v0.3 - Added option to include or not include empty values
(#) - default is not to include them.
+ * ie: <tag foo="bar" />, <tag /> or <tag></tag>
But not: <tag> </tag>
+ * Changed setValueModifier() to accept
array(object, function) type parameter or string.
+ * - v0.4 - Improved error reporting and handling.
+ * - v0.5 - Added the option to make all tags and attributes lower
case or upper case.
+ * - v0.6 - Added the option to skip attributes - and simplify the
output (Sigurd Nes)
+ *
+ * <b>Known issues</b>
+ * - None at the moment
+ * - Please send bug reports to rasmus[at]flajm.se
+ *
+ *
+ * @version 0.6 / 2007-01-10
+ * @package phpgwapi
+ * @subpackage xml
+ */
+ class XmlToArray
+ {
/**
* @var string
* @access private
@@ -117,6 +126,10 @@
var $_lower_case_tags = false;
+ /**
+ * @var bool
+ */
+ var $get_attributes = false;
/**
* Create an instance of this class as an object and set some options.
@@ -128,17 +141,28 @@
* @return object XmlToArray instance
*/
function XmlToArray ( $encoding = NULL, $stripLinebreaks = NULL,
$includeRootElement = NULL,
- $automaticUtf8Decoding = NULL, $includeEmptyValues
= NULL ) {
+
$automaticUtf8Decoding = NULL, $includeEmptyValues = NULL )
+ {
if( is_string($encoding) )
+ {
$this->setEncoding( $encoding );
+ }
if( is_bool($stripLinebreaks) )
+ {
$this->setStripsLinebreaks( $stripLinebreaks );
+ }
if( is_bool($includeRootElement) )
+ {
$this->setIncludesRoot( $includeRootElement );
+ }
if( is_bool($automaticUtf8Decoding) )
+ {
$this->setDecodesUTF8Automaticly( $automaticUtf8Decoding );
+ }
if( is_bool($includeEmptyValues) )
+ {
$this->setIncludesEmptyValues( $includeEmptyValues );
+ }
list($usec, $sec) = explode(" ", microtime());
$this->_error_start_timer = (float)$usec + (float)$sec;
@@ -152,9 +176,11 @@
*
* @param string $enc
*/
- function setEncoding ( $enc ) {
+ function setEncoding ( $enc )
+ {
$enc = strtoupper($enc);
- if( $enc != 'ISO-8859-1' && $enc != 'UTF-8' && $enc != 'US-ASCII' ) {
+ if( $enc != 'ISO-8859-1' && $enc != 'UTF-8' && $enc !=
'US-ASCII' )
+ {
$this->_logError( 'setEncoding', 'Unsupported encoding specified.
Using default/current.' );
return;
}
@@ -165,7 +191,8 @@
/**
* @return string
*/
- function encoding () {
+ function encoding ()
+ {
return $this->_encoding;
}
@@ -173,7 +200,8 @@
/**
* @param bool $b
*/
- function setStripsLinebreaks ( $b ) {
+ function setStripsLinebreaks ( $b )
+ {
$this->_strip_linebreaks = $b;
}
@@ -181,7 +209,8 @@
/**
* @return bool
*/
- function stripsLinebreaks () {
+ function stripsLinebreaks ()
+ {
return $this->_strip_linebreaks;
}
@@ -189,7 +218,8 @@
/**
* @param int $i CASE_LOWER or CASE_UPPER
*/
- function setTagCase ( $i ) {
+ function setTagCase ( $i )
+ {
$this->_lower_case_tags = ($i == CASE_LOWER);
}
@@ -200,7 +230,8 @@
*
* @param bool $b
*/
- function setIncludesRoot ( $b ) {
+ function setIncludesRoot ( $b )
+ {
$this->_includesRoot = $b;
}
@@ -208,7 +239,8 @@
/**
* @return bool
*/
- function includesRoot () {
+ function includesRoot ()
+ {
return $this->_includesRoot;
}
@@ -219,7 +251,8 @@
*
* @param bool $b
*/
- function setDecodesUTF8Automaticly ( $b ) {
+ function setDecodesUTF8Automaticly ( $b )
+ {
$this->_automaticUtf8Decoding = $b;
}
@@ -227,7 +260,8 @@
/**
* @return bool
*/
- function decodesUTF8Automaticly () {
+ function decodesUTF8Automaticly ()
+ {
return $this->_automaticUtf8Decoding;
}
@@ -238,7 +272,8 @@
*
* @param bool $b
*/
- function setIncludesEmptyValues ( $b ) {
+ function setIncludesEmptyValues ( $b )
+ {
$this->_include_empty_values = $b;
}
@@ -246,7 +281,8 @@
/**
* @return bool
*/
- function includesEmptyValues () {
+ function includesEmptyValues ()
+ {
return $this->_include_empty_values;
}
@@ -258,7 +294,8 @@
* Disabled by default.
*
* <b>Example</b><code>
- * function myValueModifier( $value ) {
+ * function myValueModifier( $value )
+ * {
* return strtoupper($value);
* }
* $xa = new XmlToArray2('utf-8');
@@ -271,19 +308,27 @@
* or array(&$object, 'function')
* @return bool Success?
*/
- function setValueModifier ( $function ) {
- if( is_string($function) ) {
- if( function_exists( $function ) ) {
+ function setValueModifier ( $function )
+ {
+ if( is_string($function) )
+ {
+ if( function_exists( $function ) )
+ {
$this->_valueModifier = $function;
return true;
- } else {
+ }
+ else
+ {
$this->_logError( 'setValueModifier', 'Registered value
modifier function can not be found.' );
return false;
}
}
else if( is_array($function) )
+ {
$this->_valueModifier = $function;
- else {
+ }
+ else
+ {
$this->_logError( 'setValueModifier', 'Parameter of unsupported
type. Should be string or array.' );
return false;
}
@@ -294,7 +339,8 @@
/**
* @return string
*/
- function valueModifier () {
+ function valueModifier ()
+ {
return $this->_valueModifier;
}
@@ -305,8 +351,10 @@
* @param string $file
* @return array
*/
- function parseFile ( $file ) {
- if (!file_exists($file)) {
+ function parseFile ( $file )
+ {
+ if (!file_exists($file))
+ {
$this->_logError( 'parseFile', 'The file "'.$file.'" can not be
found!' );
return array();
}
@@ -317,7 +365,8 @@
/**
* @access private
*/
- function _logError( $function, $msg ) {
+ function _logError( $function, $msg )
+ {
list($usec, $sec) = explode(" ", microtime());
$time = ((float)$usec + (float)$sec) - $this->_error_start_timer;
$this->_error_trace[] = array( $function, $msg, $time );
@@ -329,12 +378,15 @@
*
* @return string|NULL NULL is returned if no errors.
*/
- function errors () {
+ function errors ()
+ {
if( count($this->_error_trace) == 0 ) return NULL;
$s = '';
$len = count($this->_error_trace) -1;
for ($i=$len; $i>-1;$i--)
+ {
$s .= '['.round($this->_error_trace[$i][2]*1000,2).' ms]
<b>XmlToArray2->'.$this->_error_trace[$i][0].'()</b>
'.$this->_error_trace[$i][1] . "<br/>";
+ }
return $s;
}
@@ -345,13 +397,20 @@
*
* @access private
*/
- function _onValue ( $value ) {
+ function _onValue ( $value )
+ {
if( $this->_strip_linebreaks )
+ {
$value = preg_replace('/[\r\n]+/', ' ', $value);
+ }
if( $this->_decodeUtf8 )
+ {
$value = utf8_decode($value);
+ }
if( $this->_valueModifier != NULL )
+ {
$value = @call_user_func( $this->_valueModifier, $value );
+ }
return $value;
}
@@ -361,9 +420,12 @@
*
* @access private
*/
- function _onAttributes ( $attr ) {
+ function _onAttributes ( $attr )
+ {
foreach( $attr as $k => $v )
+ {
$attr[$k] = $this->_onValue($v);
+ }
return $attr;
}
@@ -374,26 +436,32 @@
* @param string $data
* @return array
*/
- function parse ( $data ) {
-
+ function parse ( $data )
+ {
$data = trim($data);
$err = false;
- if( $data == '' ) {
+ if( $data == '' )
+ {
$this->_logError( 'parse', 'Empty data' );
return array();
}
if( $this->_automaticUtf8Decoding )
+ {
if($this->_seems_utf8( $data ))
+ {
$this->_decodeUtf8 = true;
+ }
+ }
$parser = xml_parser_create( $this->_encoding );
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option( $parser, XML_OPTION_SKIP_WHITE, 0);
xml_parse_into_struct( $parser, $data, $vals, $index ) or $err = true;
- if( $err ) {
+ if( $err )
+ {
$this->_logError( 'parse', 'XML parser failed: '
.ucfirst(xml_error_string(xml_get_error_code($parser))) );
xml_parser_free( $parser );
@@ -405,14 +473,26 @@
$i = 0;
$tagname = ( $this->_lower_case_tags ) ? strtolower($vals[$i]['tag'])
: $vals[$i]['tag'];
- if (isset($vals[$i]['attributes'])) {
+ if (isset($vals[$i]['attributes']))
+ {
+ if($this->get_attributes)
+ {
$tree[$tagname][]['@'] = $vals[$i]['attributes'];
$index = count($tree[$tagname])-1;
$tree[$tagname][$index] = array_merge($tree[$tagname][$index],
$this->_getChildren($vals, $i));
- } else
+ }
+ else
+ {
+ $tree[$tagname][] =
$this->_getChildren($vals, $i);
+ }
+ }
+ else
+ {
$tree[$tagname][] = $this->_getChildren($vals, $i);
+ }
- if ( !$this->_includesRoot ) {
+ if ( !$this->_includesRoot )
+ {
$keys = array_keys($tree);
$tree = $tree[$keys[0]][0];
}
@@ -424,57 +504,88 @@
* @access private
* @return mixed
*/
- function _getChildren( $vals, &$i ) {
+ function _getChildren( $vals, &$i )
+ {
$children = array(); // Contains node data
if (isset($vals[$i]['value']))
+ {
if( trim($vals[$i]['value']) != '' )
- // $children['#'] = $this->_onValue( $vals[$i]['value'] );
+ {
$children = $this->_onValue( $vals[$i]['value'] );
-
- while (++$i < count($vals)) {
- switch ($vals[$i]['type']) {
-
+ }
+ while (++$i < count($vals))
+ {
+ switch ($vals[$i]['type'])
+ {
case 'cdata':
if (isset($children['#']))
+ {
if( trim($vals[$i]['value']) != '' )
+ {
$children['#'] .= $vals[$i]['value'];
+ }
+ }
else
+ {
if( trim($vals[$i]['value']) != '' )
+ {
$children['#'] = $vals[$i]['value'];
+ }
+ }
break;
case 'complete':
$tagname = ( $this->_lower_case_tags ) ?
strtolower($vals[$i]['tag']) : $vals[$i]['tag'];
- if (isset($vals[$i]['attributes'])) {
- $children[$tagname][]['@'] = $vals[$i]['attributes'];
+ if
(isset($vals[$i]['attributes']))
+ {
+ // $children[$tagname][]['@'] =
$vals[$i]['attributes'];
+
if($this->get_attributes)
+ {
+
$children[$tagname]['@'] = $vals[$i]['attributes'];
$index = count($children[$tagname])-1;
+ }
if (isset($vals[$i]['value']))
- $children[$tagname][$index] = $this->_onValue(
$vals[$i]['value'] );
- // $children[$tagname][$index]['#'] =
$this->_onValue( $vals[$i]['value'] );
+ {
+
$children[$tagname] = $this->_onValue( $vals[$i]['value'] );
+ }
else if( $this->_include_empty_values )
- $children[$tagname][$index] = '';
- // $children[$tagname][$index]['#'] = '';
+ {
+
$children[$tagname] = '';
+ }
}
else
+ {
if (isset($vals[$i]['value']))
- // $children[$tagname][]['#'] = $this->_onValue(
$vals[$i]['value'] );
+ {
$children[$tagname] = $this->_onValue(
$vals[$i]['value'] );
+ }
else if( $this->_include_empty_values )
- // $children[$tagname][]['#'] = '';
+ {
$children[$tagname] = '';
-
+ }
+ }
break;
case 'open':
$tagname = ( $this->_lower_case_tags ) ?
strtolower($vals[$i]['tag']) : $vals[$i]['tag'];
- if (isset($vals[$i]['attributes'])) {
+ if
(isset($vals[$i]['attributes']))
+ {
+
if($this->get_attributes)
+ {
$children[$tagname][]['@'] = $this->_onAttributes(
$vals[$i]['attributes'] );
$index = count($children[$vals[$i]['tag']])-1;
$children[$tagname][$index] = array_merge(
$children[$tagname][$index] , $this->_getChildren($vals, $i) );
}
else
+ {
+
$children[$tagname][] = $this->_getChildren($vals, $i);
+ }
+ }
+ else
+ {
$children[$tagname][] = $this->_getChildren($vals, $i);
+ }
break;
case 'close':
@@ -482,13 +593,16 @@
}//switch
}//while
}
+ }
/**
* @access private
*/
- function _seems_utf8($Str) {
- for ($i=0; $i<strlen($Str); $i++) {
+ function _seems_utf8($Str)
+ {
+ for ($i=0; $i<strlen($Str); $i++)
+ {
if (ord($Str[$i]) < 0x80) continue; # 0bbbbbbb
elseif ((ord($Str[$i]) & 0xE0) == 0xC0) $n=1; # 110bbbbb
elseif ((ord($Str[$i]) & 0xF0) == 0xE0) $n=2; # 1110bbbb
@@ -497,12 +611,13 @@
elseif ((ord($Str[$i]) & 0xFE) == 0xFC) $n=5; # 1111110b
else return false; # Does not match any model
for ($j=0; $j<$n; $j++) # n bytes matching 10bbbbbb follow ?
+ {
if ((++$i == strlen($Str)) || ((ord($Str[$i]) & 0xC0) != 0x80))
+ {
return false;
}
+ }
+ }
return true;
}
-
-}
-
-?>
+ }