Wednesday, August 14, 2013

How to parse XML with php code which contains namespace, cdata, ampersand

Download xml.class.php

Php code to parse xml which contains namespace, cdata and ampersand symbol included


<?php
class XmlToArrayParser {
    /** The array created by the parser can be assigned to any variable: $anyVarArr = $domObj->array.*/
    public $array = array();
    private $parse_error = false;
    private $parser;
    private $pointer;

    /** Constructor: $domObj = new xmlToArrayParser($xml); */
    public function __construct($xml) {
        $xml = str_replace(array('&'), array('&amp;'), $xml);
        $this->pointer =& $this->array;
        $this->parser = xml_parser_create("UTF-8");
        xml_set_object($this->parser, $this);
        xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false);
        xml_set_element_handler($this->parser, "tag_open", "tag_close");
        xml_set_character_data_handler($this->parser, "cdata");
        $this->parse_error = xml_parse($this->parser, ltrim($xml)) ? false : true;
    }

    /** Free the parser. */
    public function __destruct() {
        xml_parser_free($this->parser);
    }

    /** Get the xml error if an an error in the xml file occured during parsing. */
    public function get_xml_error() {
        if ($this->parse_error) {
            $errCode = xml_get_error_code($this->parser);
            $thisError = "Error Code [" . $errCode . "] \"<strong style='color:red;'>" . xml_error_string($errCode) . "</strong>\",
                            at char " . xml_get_current_column_number($this->parser) . "
                            on line " . xml_get_current_line_number($this->parser) . "";
        } else {
            $thisError = $this->parse_error;
        }
        return $thisError;
    }

    private function tag_open($parser, $tag, $attributes) {
        $this->convert_to_array($tag, 'attrib');
        $idx = $this->convert_to_array($tag, 'cdata');
        if (isset($idx)) {
            $this->pointer[$tag][$idx] = Array(
                '@idx' => $idx,
                '@parent' => &$this->pointer
            );
            $this->pointer =& $this->pointer[$tag][$idx];
        } else {
            $this->pointer[$tag] = Array(
                '@parent' => &$this->pointer
            );
            $this->pointer =& $this->pointer[$tag];
        }
        if (!empty($attributes)) {
            $this->pointer['attrib'] = $attributes;
        }
    }

    /** Adds the current elements content to the current pointer[cdata] array. */
    private function cdata($parser, $cdata) {
        if (strlen(trim($cdata)) > 0) {
            if (isset($this->pointer['cdata'])) {
                $this->pointer['cdata'] .= $cdata;
            } else {
                $this->pointer['cdata'] = $cdata;
            }
        }
    }

    private function tag_close($parser, $tag) {
        $current =& $this->pointer;
        if (isset($this->pointer['@idx'])) {
            unset($current['@idx']);
        }

        $this->pointer =& $this->pointer['@parent'];
        unset($current['@parent']);

        if (isset($current['cdata']) && count($current) == 1) {
            $current = $current['cdata'];
        } else if (empty($current['cdata'])) {
            unset($current['cdata']);
        }
    }

    /** Converts a single element item into array(element[0]) if a second element of the same name is encountered. */
    private function convert_to_array($tag, $item) {
        if (isset($this->pointer[$tag][$item])) {
            $content = $this->pointer[$tag];
            $this->pointer[$tag] = array(
                (0) => $content
            );
            $idx = 1;
        } else if (isset($this->pointer[$tag])) {
            $idx = count($this->pointer[$tag]);
            if (!isset($this->pointer[$tag][0])) {
                foreach ($this->pointer[$tag] as $key => $value) {
                    unset($this->pointer[$tag][$key]);
                    $this->pointer[$tag][0][$key] = $value;
                }
            }
        } else {
            $idx = null;
        }
        return $idx;
    }
}
?>

Parsing XML example


<?php
$xmlString = "<?xml version=\"1.0\" encoding=\"utf-8\"?>
<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\"
    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
    xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">
    <soap:Body>
        <CreateCustomerResponse xmlns=\"https://www.eway.com.au/gateway/managedpayment\">
            <CreateCustomerResult>9876543211000</CreateCustomerResult>
        </CreateCustomerResponse>
    </soap:Body>
    <soap:Body>
        <CreateCustomerResponse xmlns=\"https://www.eway.com.au/gateway/managedpayment\">
            <CreateCustomerResult>9876543211000</CreateCustomerResult>
        </CreateCustomerResponse>
    </soap:Body>
    <address name=\"pritom\">
        <actual content=\"Pritom Kumar\"/>
        <forward forwarding=\"yes\" content=\"pritom\">Forward to pritom & else one</forward>
        <response responding=\"yes\"><![CDATA[Thanks you.]]></response>
    </address>
</soap:Envelope>";

echo "<pre>";
$xmlObject = new XmlToArrayParser($xmlString);
print_r($xmlObject->array);
echo "</pre>";
?>

Output


Array
(
    [soap:Envelope] => Array
        (
            [attrib] => Array
                (
                    [xmlns:soap] => http://www.w3.org/2003/05/soap-envelope
                    [xmlns:xsi] => http://www.w3.org/2001/XMLSchema-instance
                    [xmlns:xsd] => http://www.w3.org/2001/XMLSchema
                )

            [soap:Body] => Array
                (
                    [0] => Array
                        (
                            [CreateCustomerResponse] => Array
                                (
                                    [attrib] => Array
                                        (
                                            [xmlns] => https://www.eway.com.au/gateway/managedpayment
                                        )

                                    [CreateCustomerResult] => 9876543211000
                                )

                        )

                    [1] => Array
                        (
                            [CreateCustomerResponse] => Array
                                (
                                    [attrib] => Array
                                        (
                                            [xmlns] => https://www.eway.com.au/gateway/managedpayment
                                        )

                                    [CreateCustomerResult] => 9876543211000
                                )

                        )

                )

            [address] => Array
                (
                    [attrib] => Array
                        (
                            [name] => pritom
                        )

                    [actual] => Array
                        (
                            [attrib] => Array
                                (
                                    [content] => Pritom Kumar
                                )

                        )

                    [forward] => Array
                        (
                            [attrib] => Array
                                (
                                    [forwarding] => yes
                                    [content] => pritom
                                )

                            [cdata] => Forward to pritom & else one
                        )

                    [response] => Array
                        (
                            [attrib] => Array
                                (
                                    [responding] => yes
                                )

                            [cdata] => Thanks you.
                        )

                )

        )

)

No comments:

Post a Comment