Pages

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