Login   Register  
PHP Classes
elePHPant
Icontem

File: XmlHelper.class.php

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Richard Williams  >  XML Helper  >  XmlHelper.class.php  >  Download  
File: XmlHelper.class.php
Role: Class source
Content type: text/plain
Description: Class
Class: XML Helper
Extract XML data into an array and vice-versa
Author: By
Last change:
Date: 3 years ago
Size: 8,762 bytes
 

Contents

Class file image Download
<?php
/**
 * Class of utility functions for XML manipulation.
 * 
 * $array = xmlToArray($xmlString) Convert an XML string to an equivalent array.
 * $xmlString = arrayToXml($array) Convert an array to an equivalent XML string.
 *
 * See the accompanying doc file for details of use.
 * See the accompanying phpunit test file for examples of use.
 *
 * Please report any bugs to richard at roguewavelimited.com.  If possible include
 * a sample data file and description of the bug.
 *
 * If you have any suggestions on how to improve this class, let me know.
 * 
 * You are free to use this class in any way you see fit.
 *
 * Richard Williams
 * Rogue Wave Limited
 * Jan 2, 2011
 */

class XmlHelper {

    
// Name to use as name of attribute array.
    
private $attributesArrayName 'attributes';
    
    
// Case folding  (uppercasing of names) is on by default (just like normal parser)
    
private $foldCase true;

    
// Turn off values returned as arrays and ignore attributes.
    // Attributes and value arrays are on by default.
    
private $noAttributes false;

    
// If true, then leaing and trailing whitespace is removed from attributes and values.
    // Off by default.
    
private $trimText false;

    
// Vals returned by DOM parser.
    
private $vals;

    
// Name to use as name of value array.
    
private $valueArrayName 'value';

    
/**
     * Create XML from an array.
     *
     * @param <type> $array
     * @param <type> $numericName Name to be used for numeric array indexes.
     */
    
function arrayToXml ($array) {
        
$dom = new DOMDocument();
        
$dom->encoding "ISO-8859-1";
//        $dom->encoding = "UTF-8";

        
$each each($array);
        
$root $each[0];
        
$array $each[1];

        
$rootNode $dom->appendChild($dom->createElement($root));
        
$this->putChildren($dom$array$rootNode);

        return 
$dom->saveXML();
    }
    

    private function 
putChildren(DOMDocument &$dom, array $arrDOMElement $node) {

        
/*
         * Each node can be one of three types.  'value', an array indicating a sub-node
         * 'and 'attributes' indicating an array of attributes.
         */

        
$arrayParent null;
        foreach(
$arr as $name => $content) {

            if (
strtoupper($name) == 'ATTRIBUTES') {
                foreach(
$content as $n => $v) {
                    
$node->setAttribute($n$v);
                }
            
            } else if (
strtoupper($name) == 'VALUE') {
                
$node->appendChild($dom->createTextNode($content));

            } else {

                
// An integer index means that this starts a set
                // of elements with the same name.

                
if (is_integer($name)) {

                    
// Get the parent node and remove the integer element.

                    
$child $node;
                    if (
is_null($arrayParent)) {
                        
$arrayParent $node->parentNode;
                        
$arrayParent->removeChild($child);

                    } else {
                        
$child $dom->createElement($node->tagName, (is_array($content) ? null htmlspecialchars($content)));
                    }

                    
$arrayParent->appendChild($child);

                } else {

                    
$child $dom->createElement($name, (is_array($content) ? null htmlspecialchars($content)));
                    
$node->appendChild($child);
                }
                
                if (
is_array($content)) {
                    
self::putChildren($dom$content$child);
                }
            }
        }
    }



    function 
xmlToArray ($xmldata) {

        
$parser xml_parser_create ('ISO-8859-1');
//        $parser = xml_parser_create ('UTF-8');
        
xml_parser_set_option($parserXML_OPTION_SKIP_WHITE1);
        
xml_parser_set_option($parserXML_OPTION_CASE_FOLDING$this->foldCase);

        
$vals = array();
        if (!
xml_parse_into_struct ($parser$xmldata$vals)) {
            throw new 
Exception(sprintf("XML error: %s at line %d",
                            
xml_error_string(xml_get_error_code($parser)),
                            
xml_get_current_line_number($parser)));        }
        
$folding xml_parser_get_option($parserXML_OPTION_CASE_FOLDING);
        
xml_parser_free ($parser);

        
$this->vals $vals;

        if (
$folding) {
            
$this->valueArrayName strtoupper($this->valueArrayName);
            
$this->attributesArrayName strtoupper($this->attributesArrayName);
        }

        
// Trim attributes and values if option set.

        
if ($this->trimText) {
            foreach(
$vals as &$val) {
                if (
count($val['attributes']) > 0) {
                    foreach(
$val['attributes'] as $name => $att) {
                        if (
$this->trimText$val['attributes'][$name] = trim($att);
                    }
                }
                if (isset(
$val['value'])) {
                    if (
$this->trimText$val['value'] = trim($val['value']);
                }
            }
        }

        
$i 0;
        
$children $this->getChildren ($vals$i$vals[$i]['type']);

        
// Add value and attributes to if present.

        
$valatt $this->addAttributesAndValue($vals0);
        if (! empty(
$valatt)) $children array_merge($valatt$children);

        
$result [$vals [$i]['tag']] = $children;
        return 
$result;
    }


    
/*
     * Called recursively to parse the vals array.
     */
    
private function getChildren ($vals, &$i$type) {

        
// If the type is 'complete' it means that there are no children of this element.

        
$children = array ();

        if (
$type != 'complete') {

            while (
$vals [++$i]['type'] != 'close') {
                
$type $vals [$i]['type'];
                
$tag $vals [$i]['tag'];

                
$valatt $this->addAttributesAndValue($vals$i);

                
// Check if we already have an element with this name and need to create an array

                
if (isset ($children [$tag])) {

                    
$temp array_keys ($children [$tag]);

                    if (
is_string ($temp [0])) {
                        
$a $children [$tag];
                        unset (
$children [$tag]);
                        
$children [$tag][0] = $a;
                    }

                    
$child $this->getChildren($vals$i$type);
                    if (! empty(
$valatt)) $child array_merge($valatt$child);
                    
$children [$tag][] = $child;

                } else {

                    
$children [$tag] = $this->getChildren ($vals$i$type);

                    
// If a scalar is returned from addAttributeAndValue just set that as the return
                    // otherwise merge it with the existing children.

                    
if (! is_array($valatt)) {
                        
$children[$tag] = $valatt;
                    } else {
                        if (! empty(
$valatt)) $children[$tag] = array_merge($valatt$children[$tag]);
                    }
                }
            }
        }

        return 
$children;
    }

    
/**
     * Add any attributes or values from parser to the output array.
     *
     * @param array $vals Parser vals.
     * @param int $i Nesting level.
     * @return array.
     */
    
private function addAttributesAndValue($vals$i) {

        
$array = array();
        if (
$this->noAttributes) {
            if (isset (
$vals[$i]['value'])) $array $vals [$i]['value'];

        } else {
            if (isset (
$vals[$i]['value'])) $array = array($this->valueArrayName => $vals [$i]['value']);
            if (isset (
$vals[$i]['attributes']))
                
$array array_merge($array, array($this->attributesArrayName => $vals[$i]['attributes']));
        }
        return 
$array;
    }

    
/**
     * Provides access to the parser's vals array.
     * @return array of parser vals
     */
    
function getParserVals() {
        return 
$this->vals;
    }

    
/**
     * If true then values are returned as raw values instead of as a 'VALUE' array.
     * Also attributes are ignored.
     * @param boolean $switch
     */
    
function setNoAttributes($switch) {
        
$this->noAttributes $switch;
    }

    
/**
     * Set case folding (uppercasing) of all returned array names.
     * This includes any value and attribute arrays.
     * @param boolean $switch
     */
    
function setCaseFolding($switch) {
        
$this->foldCase $switch;
    }

    
/**
     * If set, trims leading and trailing white space from attribute value and value text.
     * @param boolean $switch
     */
    
function setTrimText($switch) {
        
$this->trimText $switch;
    }
}
?>