XML generator library

Derek Jones edited this page Jul 5, 2012 · 9 revisions
Clone this wiki locally

By JoostV Forum thread http://codeigniter.com/forums/viewthread/108264/

EDIT: most recent code is on Github: https://github.com/accent-interactive/xml_writer

This is a very easy to use XML writer library I developed to write XLM for communication with a Flash app. But it can be used to generate any well-formed XML document. Thought I’d share. Any comments welcome, of course smile

It can be used to create any XML, not matter how deep. Every branche and node can have one or more attributes, if needed. Need CDATA? Just set a parameter to true. The library prints XML directly to screen, setting XML headers first, or it can return the XML as a string. Just place the library in applications/library and you’re good to go.

Basically, you can add two types of data:

  • branches - you need to start a new branch and end it before adding the next branch
  • nodes - nodes are children to a branch. You do not have to start and end a node, just add it.

Example use: place this in your controller (of course you would normally collect the data from a database, making the code much cleaner than it is in this example) CONTROLLER


function write_xml() {
    // Load XML writer library
    $this->load->library('MY_Xml_writer');
    
    // Initiate class
    $xml = new MY_Xml_writer;
    $xml->setRootName('my_store');
    $xml->initiate();
    
    // Start branch 1
    $xml->startBranch('cars');
    
    // Set branch 1-1 and its nodes
    $xml->startBranch('car', array('country' => 'usa')); // start branch 1-1
    $xml->addNode('make', 'Ford');
    $xml->addNode('model', 'T-Ford', array(), true);
    $xml->endBranch();
    
    // Set branch 1-2 and its nodes
    $xml->startBranch('car', array('country' => 'Japan')); // start branch
    $xml->addNode('make', 'Toyota');
    $xml->addNode('model', 'Corolla', array(), true);
    $xml->endBranch();
    
    // End branch 1
    $xml->endBranch();
    
    // Start branch 2
    $xml->startBranch('bikes'); // start branch
    
    // Set branch 2-1  and its nodes
    $xml->startBranch('bike', array('country' => 'usa')); // start branch
    $xml->addNode('make', 'Harley-Davidson');
    $xml->addNode('model', 'Soft tail', array(), true);
    $xml->endBranch();
    
    // End branch 2
    $xml->endBranch();
    
    // Print the XML to screen
    $xml->getXml(true);
}

This will produce the following XML:


<?xml version="1.0" encoding="UTF-8"?>
<my_store>
    <cars>
        <car country="usa">
            <make>Ford</make>
            <model>&lt;![CDATA[T-Ford]]></model>
        </car>
        <car country="Japan">
            <make>Toyota</make>
            <model>&lt;![CDATA[Corolla]]></model>
        </car>
    </cars>
    <bikes>
        <bike country="usa">
            <make>Harley-Davidson</make>
            <model>&lt;![CDATA[Soft tail]]></model>
        </bike>
    </bikes>
</my_store>

EXTRA OPTIONS Before you call initiate() you can set some XML settings if you wish: $xml->setRootName($string); // Set the value of the root tag for this XML. Defaults to 'root' $xml->setXmlVersion($string); // Set the value of the XMl version for this XML. Defaults to '1.0' $xml->setCharSet($string); // Set the character set for this XML. Defaults to 'UTF-8' $xml->setIndentStr($string); // Set indenting for every new node in this XML. Defaults to '    '. $xml->setXsltFilePath($string); // Set the XSLT filepath for this XML. This should be an absolute URL. Defaults to '' (no XSL)

USE A VIEW If you do not wish to print, but rather send the XML string to a view file: $data['xml'] = $xml->getXml(); $this->load->view('xml_template', $data);

LIBRARY SOURCE CODE MY_Xml_writer.php


&lt;?php  if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* Class used to write XMl document.
* Extends XMLWriter (PHP5 only!)
*
* Initialize the class:
* $this->load->library('MY_Xml_writer');
* $xml = new MY_Xml_writer;
* $xml->initiate();
*
* Start a branch with attributes:
* $xml->startBranch('car', array('country' => 'usa', 'type' => 'racecar'));
*
* End (close) a branch
* $xml->endBranch();
*
* Add a CDATA node with attributes:
* $xml->addNode('model', 'Corolla', array('year' => '2002'), true);
*
* Print the XMl directly to screen:
* $xml->getXml(true);
*
* Pass the XMl to a view file:
* $data['xml'] = $xml->getXml();
* $this->load->view('xml_template', $data);
*
* @name /library/Accent/Xml/Accent_Xml_Writer.php
* @category Accent_application
* @version 1.0
* @author Joost van Veen
* @copyright Accent Webdesign
* @created: 10 mrt 2009
*/
class MY_Xml_writer extends XMLWriter
{
    
    /**
     * Name of the root element for this XMl. Defaults to root.
     */
    private $_rootName = '';
    
    /**
     * XML version. Defaults to 1.0
     */
    private $_xmlVersion = '1.0';
    
    /**
     * Character set. Defaukts to UTF-8.
     */
    private $_charSet = 'UTF-8';
    
    /**
     * Indent for every new tag. Defaults to spaces.  
     */
    private $_indentString = '    ';
    
    /**
     * Sets an xslt path for this XML. Defaults to ''.
     * Xslt will only be included in the XML if $_xsltFilePath is not an
     * empty string.
     */
    private $_xsltFilePath = '';

    public function __construct ()
    {}

    /**
     * Set the value of the root tag for this XML
     */
    public function setRootName ($rootName)
    {
        $this->_rootName = $rootName;
    }

    /**
     * Set the value of the XMl version for this XML.
     */
    public function setXmlVersion ($version)
    {
        $this->_xmlVersion = $version;
    }

    /**
     * Set the character set for this XML.
     */
    public function setCharSet ($charSet)
    {
        $this->_charSet = $charSet;
    }

    /**
     * Set indenting for every new node in this XML.
     */
    public function setIndentStr ($indentString)
    {
        $this->_indentString = $indentString;
    }

    /**
     * Set the XSLT filepath for this XML. This should be an absolute URL.
     */
    public function setXsltFilePath ($xsltFilePath)
    {
        $this->_xsltFilePath = $xsltFilePath;
    }

    public function initiate ()
    {
        // Create new xmlwriter using memory for string output.
        $this->openMemory();
        
        // Set indenting, if any.
        if ($this->_indentString) {
            $this->setIndent(true);
            $this->setIndentString($this->_indentString);
        }
        
        // Set DTD.
        $this->startDocument($this->_xmlVersion, $this->_charSet);
        
        // Set XSLT stylesheet path, if any.
        if ($this->_xsltFilePath) {
            $this->writePi('xml-stylesheet', 'type="text/xsl" href="' . $this->_xsltFilePath . '"');
        }
        
        // Set the root tag.
        $this->startElement($this->_rootName);
    }

    /**
     * Start a new branch that will contain nodes.
     */
    public function startBranch ($name, $attributes = array())
    {
        $this->startElement($name);
        $this->_addAttributes($attributes);
    }

    /**
     * End an open branch. A branch needs to be closed explicitely if the branch
     * is followed directly by another branch.
     */
    public function endBranch ()
    {
        $this->endElement();
    }

    /**
     * Add a node, typically a child to a branch.
     *
     * If you wish to create a simple text node, just set $name and $value.
     * If you wish to create a CDATA node, set $name, $value and $cdata.
     * You can set attributes for every node, passing a key=>value $attributes array
     *
     * @param string $name
     * @param string $value
     * @param array attributes
     * @param boolean $cdata
     * @return void
     */
    public function addNode ($name, $value, $attributes = array(), $cdata = false)
    {
        /**
         * Set a CDATA element.
         */
        if ($cdata) {
            $this->startElement($name);
            $this->_addAttributes($attributes);
            $this->writeCdata($value);
            $this->endElement();
        }
        /**
         * Set a simple text element.
         */
        else {
            $this->startElement($name);
            $this->_addAttributes($attributes);
            $this->text($value);
            $this->endElement();
        }
    }

    /**
     * Close the XML document, print to screen if $echo == true, and return a
     * string containing the full XML.
     *
     * @param boolean echo - if true, print XML to screen.
     * @return string - The full XML.
     */
    public function getXml ($echo = false)
    {
        
        /**
         * Set header.
         */
        if ($echo == true) {
            header('Content-type: text/xml');
        }
        
        /**
         * Close XMl document.
         */
        $this->endElement();
        $this->endDocument();
        
        /**
         * Return or echo output.
         */
        $output = $this->outputMemory();
        if ($echo == true) {
            // Print XML to screen.
            print $output;
        }
        
        return $output;
    }

    /**
     * Add attributes to an element.
     *
     * @param array $attributes
     */
    private function _addAttributes ($attributes)
    {
        if (count($attributes) > 0) {
            // We have attributes, let's set them
            foreach ($attributes as $key => $value) {
                $this->writeAttribute($key, $value);
            }
        }
    }
} 

Enjoy! Joost van Veen Accent Interactive http://twitter.com/joostvanveen