Web студия "GrandView"
  Главная   Написать Контакты
   
   
О проекте
Руководство php
 

CLXXV. XML Parser Functions

Введение

XML (eXtensible Markup Language) is a data format for structured document interchange on the Web. It is a standard defined by The World Wide Web consortium (W3C). Information about XML and related technologies can be found at http://www.w3.org/XML/.

This PHP extension implements support for James Clark's expat in PHP. This toolkit lets you parse, but not validate, XML documents. It supports three source character encodings also provided by PHP: US-ASCII, ISO-8859-1 and UTF-8. UTF-16 is not supported.

This extension lets you create XML parsers and then define handlers for different XML events. Each XML parser also has a few parameters you can adjust.

Требования

This extension uses an expat compat layer by default. It can use also expat, which can be found at http://www.jclark.com/xml/expat.html. The Makefile that comes with expat does not build a library by default, you can use this make rule for that:
libexpat.a: $(OBJS)
    ar -rc $@ $(OBJS)
    ranlib $@
A source RPM package of expat can be found at http://sourceforge.net/projects/expat/.

Установка

These functions are enabled by default, using the bundled expat library. You can disable XML support with --disable-xml. If you compile PHP as a module for Apache 1.3.9 or later, PHP will automatically use the bundled expat library from Apache. In order you don't want to use the bundled expat library configure PHP --with-expat-dir=DIR, where DIR should point to the base installation directory of expat.

Версия PHP для Windows имеет встроенную поддержку данного расширения. Это означает, что для использования данных функций не требуется загрузка никаких дополнительных расширений.

Настройка во время выполнения

Данное расширение не определяет никакие директивы конфигурации в php.ini.

Типы ресурсов

xml

The xml resource as returned by xml_parser_create() and xml_parser_create_ns() references an xml parser instance to be used with the functions provided by this extension.

Предопределенные константы

Перечисленные ниже константы определены данным расширением и могут быть доступны только в том случае, если PHP был собран с поддержкой этого расширения или же в том случае, если данное расширение подгружается во время выполнения.

XML_ERROR_NONE (integer)

XML_ERROR_NO_MEMORY (integer)

XML_ERROR_SYNTAX (integer)

XML_ERROR_NO_ELEMENTS (integer)

XML_ERROR_INVALID_TOKEN (integer)

XML_ERROR_UNCLOSED_TOKEN (integer)

XML_ERROR_PARTIAL_CHAR (integer)

XML_ERROR_TAG_MISMATCH (integer)

XML_ERROR_DUPLICATE_ATTRIBUTE (integer)

XML_ERROR_JUNK_AFTER_DOC_ELEMENT (integer)

XML_ERROR_PARAM_ENTITY_REF (integer)

XML_ERROR_UNDEFINED_ENTITY (integer)

XML_ERROR_RECURSIVE_ENTITY_REF (integer)

XML_ERROR_ASYNC_ENTITY (integer)

XML_ERROR_BAD_CHAR_REF (integer)

XML_ERROR_BINARY_ENTITY_REF (integer)

XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF (integer)

XML_ERROR_MISPLACED_XML_PI (integer)

XML_ERROR_UNKNOWN_ENCODING (integer)

XML_ERROR_INCORRECT_ENCODING (integer)

XML_ERROR_UNCLOSED_CDATA_SECTION (integer)

XML_ERROR_EXTERNAL_ENTITY_HANDLING (integer)

XML_OPTION_CASE_FOLDING (integer)

XML_OPTION_TARGET_ENCODING (integer)

XML_OPTION_SKIP_TAGSTART (integer)

XML_OPTION_SKIP_WHITE (integer)

Event Handlers

The XML event handlers defined are:

Таблица 1. Supported XML handlers

PHP function to set handlerEvent description
xml_set_element_handler() Element events are issued whenever the XML parser encounters start or end tags. There are separate handlers for start tags and end tags.
xml_set_character_data_handler() Character data is roughly all the non-markup contents of XML documents, including whitespace between tags. Note that the XML parser does not add or remove any whitespace, it is up to the application (you) to decide whether whitespace is significant.
xml_set_processing_instruction_handler() PHP programmers should be familiar with processing instructions (PIs) already. <?php ?> is a processing instruction, where php is called the "PI target". The handling of these are application-specific, except that all PI targets starting with "XML" are reserved.
xml_set_default_handler() What goes not to another handler goes to the default handler. You will get things like the XML and document type declarations in the default handler.
xml_set_unparsed_entity_decl_handler() This handler will be called for declaration of an unparsed (NDATA) entity.
xml_set_notation_decl_handler() This handler is called for declaration of a notation.
xml_set_external_entity_ref_handler() This handler is called when the XML parser finds a reference to an external parsed general entity. This can be a reference to a file or URL, for example. See the external entity example for a demonstration.

Case Folding

The element handler functions may get their element names case-folded. Case-folding is defined by the XML standard as "a process applied to a sequence of characters, in which those identified as non-uppercase are replaced by their uppercase equivalents". In other words, when it comes to XML, case-folding simply means uppercasing.

By default, all the element names that are passed to the handler functions are case-folded. This behaviour can be queried and controlled per XML parser with the xml_parser_get_option() and xml_parser_set_option() functions, respectively.

Error Codes

The following constants are defined for XML error codes (as returned by xml_parse()):

XML_ERROR_NONE
XML_ERROR_NO_MEMORY
XML_ERROR_SYNTAX
XML_ERROR_NO_ELEMENTS
XML_ERROR_INVALID_TOKEN
XML_ERROR_UNCLOSED_TOKEN
XML_ERROR_PARTIAL_CHAR
XML_ERROR_TAG_MISMATCH
XML_ERROR_DUPLICATE_ATTRIBUTE
XML_ERROR_JUNK_AFTER_DOC_ELEMENT
XML_ERROR_PARAM_ENTITY_REF
XML_ERROR_UNDEFINED_ENTITY
XML_ERROR_RECURSIVE_ENTITY_REF
XML_ERROR_ASYNC_ENTITY
XML_ERROR_BAD_CHAR_REF
XML_ERROR_BINARY_ENTITY_REF
XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF
XML_ERROR_MISPLACED_XML_PI
XML_ERROR_UNKNOWN_ENCODING
XML_ERROR_INCORRECT_ENCODING
XML_ERROR_UNCLOSED_CDATA_SECTION
XML_ERROR_EXTERNAL_ENTITY_HANDLING

Character Encoding

PHP's XML extension supports the Unicode character set through different character encodings. There are two types of character encodings, source encoding and target encoding. PHP's internal representation of the document is always encoded with UTF-8.

Source encoding is done when an XML document is parsed. Upon creating an XML parser, a source encoding can be specified (this encoding can not be changed later in the XML parser's lifetime). The supported source encodings are ISO-8859-1, US-ASCII and UTF-8. The former two are single-byte encodings, which means that each character is represented by a single byte. UTF-8 can encode characters composed by a variable number of bits (up to 21) in one to four bytes. The default source encoding used by PHP is ISO-8859-1.

Target encoding is done when PHP passes data to XML handler functions. When an XML parser is created, the target encoding is set to the same as the source encoding, but this may be changed at any point. The target encoding will affect character data as well as tag names and processing instruction targets.

If the XML parser encounters characters outside the range that its source encoding is capable of representing, it will return an error.

If PHP encounters characters in the parsed XML document that can not be represented in the chosen target encoding, the problem characters will be "demoted". Currently, this means that such characters are replaced by a question mark.

Примеры

Here are some example PHP scripts parsing XML documents.

XML Element Structure Example

This first example displays the structure of the start elements in a document with indentation.

Пример 1. Show XML Element Structure

<?php
$file
= "data.xml";
$depth = array();

function
startElement($parser, $name, $attrs)
{
    global
$depth;
    for (
$i = 0; $i < $depth[$parser]; $i++) {
        echo
"  ";
    }
    echo
"$name\n";
   
$depth[$parser]++;
}

function
endElement($parser, $name)
{
    global
$depth;
   
$depth[$parser]--;
}

$xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, "startElement", "endElement");
if (!(
$fp = fopen($file, "r"))) {
    die(
"could not open XML input");
}

while (
$data = fread($fp, 4096)) {
    if (!
xml_parse($xml_parser, $data, feof($fp))) {
        die(
sprintf("XML error: %s at line %d",
                   
xml_error_string(xml_get_error_code($xml_parser)),
                   
xml_get_current_line_number($xml_parser)));
    }
}
xml_parser_free($xml_parser);
?>

XML Tag Mapping Example

Пример 2. Map XML to HTML

This example maps tags in an XML document directly to HTML tags. Elements not found in the "map array" are ignored. Of course, this example will only work with a specific XML document type.

<?php
$file
= "data.xml";
$map_array = array(
   
"BOLD"     => "B",
   
"EMPHASIS" => "I",
   
"LITERAL"  => "TT"
);

function
startElement($parser, $name, $attrs)
{
    global
$map_array;
    if (isset(
$map_array[$name])) {
        echo
"<$map_array[$name]>";
    }
}

function
endElement($parser, $name)
{
    global
$map_array;
    if (isset(
$map_array[$name])) {
        echo
"</$map_array[$name]>";
    }
}

function
characterData($parser, $data)
{
    echo
$data;
}

$xml_parser = xml_parser_create();
// use case-folding so we are sure to find the tag in $map_array
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");
if (!(
$fp = fopen($file, "r"))) {
    die(
"could not open XML input");
}

while (
$data = fread($fp, 4096)) {
    if (!
xml_parse($xml_parser, $data, feof($fp))) {
        die(
sprintf("XML error: %s at line %d",
                   
xml_error_string(xml_get_error_code($xml_parser)),
                   
xml_get_current_line_number($xml_parser)));
    }
}
xml_parser_free($xml_parser);
?>

XML External Entity Example

This example highlights XML code. It illustrates how to use an external entity reference handler to include and parse other documents, as well as how PIs can be processed, and a way of determining "trust" for PIs containing code.

XML documents that can be used for this example are found below the example (xmltest.xml and xmltest2.xml.)

Пример 3. External Entity Example

<?php
$file
= "xmltest.xml";

function
trustedFile($file)
{
   
// only trust local files owned by ourselves
   
if (!eregi("^([a-z]+)://", $file)
        &&
fileowner($file) == getmyuid()) {
            return
true;
    }
    return
false;
}

function
startElement($parser, $name, $attribs)
{
    echo
"&lt;<font color=\"#0000cc\">$name</font>";
    if (
count($attribs)) {
        foreach (
$attribs as $k => $v) {
            echo
" <font color=\"#009900\">$k</font>=\"<font
                   color=\"#990000\">$v</font>\""
;
        }
    }
    echo
"&gt;";
}

function
endElement($parser, $name)
{
    echo
"&lt;/<font color=\"#0000cc\">$name</font>&gt;";
}

function
characterData($parser, $data)
{
    echo
"<b>$data</b>";
}

function
PIHandler($parser, $target, $data)
{
    switch (
strtolower($target)) {
        case
"php":
            global
$parser_file;
           
// If the parsed document is "trusted", we say it is safe
            // to execute PHP code inside it.  If not, display the code
            // instead.
           
if (trustedFile($parser_file[$parser])) {
                eval(
$data);
            } else {
               
printf("Untrusted PHP code: <i>%s</i>",
                       
htmlspecialchars($data));
            }
            break;
    }
}

function
defaultHandler($parser, $data)
{
    if (
substr($data, 0, 1) == "&" && substr($data, -1, 1) == ";") {
       
printf('<font color="#aa00aa">%s</font>',
               
htmlspecialchars($data));
    } else {
       
printf('<font size="-1">%s</font>',
               
htmlspecialchars($data));
    }
}

function
externalEntityRefHandler($parser, $openEntityNames, $base, $systemId,
                                 
$publicId) {
    if (
$systemId) {
        if (!list(
$parser, $fp) = new_xml_parser($systemId)) {
           
printf("Could not open entity %s at %s\n", $openEntityNames,
                  
$systemId);
            return
false;
        }
        while (
$data = fread($fp, 4096)) {
            if (!
xml_parse($parser, $data, feof($fp))) {
               
printf("XML error: %s at line %d while parsing entity %s\n",
                      
xml_error_string(xml_get_error_code($parser)),
                      
xml_get_current_line_number($parser), $openEntityNames);
               
xml_parser_free($parser);
                return
false;
            }
        }
       
xml_parser_free($parser);
        return
true;
    }
    return
false;
}

function
new_xml_parser($file)
{
    global
$parser_file;

   
$xml_parser = xml_parser_create();
   
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 1);
   
xml_set_element_handler($xml_parser, "startElement", "endElement");
   
xml_set_character_data_handler($xml_parser, "characterData");
   
xml_set_processing_instruction_handler($xml_parser, "PIHandler");
   
xml_set_default_handler($xml_parser, "defaultHandler");
   
xml_set_external_entity_ref_handler($xml_parser, "externalEntityRefHandler");
   
    if (!(
$fp = @fopen($file, "r"))) {
        return
false;
    }
    if (!
is_array($parser_file)) {
       
settype($parser_file, "array");
    }
   
$parser_file[$xml_parser] = $file;
    return array(
$xml_parser, $fp);
}

if (!(list(
$xml_parser, $fp) = new_xml_parser($file))) {
    die(
"could not open XML input");
}

echo
"<pre>";
while (
$data = fread($fp, 4096)) {
    if (!
xml_parse($xml_parser, $data, feof($fp))) {
        die(
sprintf("XML error: %s at line %d\n",
                   
xml_error_string(xml_get_error_code($xml_parser)),
                   
xml_get_current_line_number($xml_parser)));
    }
}
echo
"</pre>";
echo
"parse complete\n";
xml_parser_free($xml_parser);

?>

Пример 4. xmltest.xml

<?xml version='1.0'?>
<!DOCTYPE chapter SYSTEM "/just/a/test.dtd" [
<!ENTITY plainEntity "FOO entity">
<!ENTITY systemEntity SYSTEM "xmltest2.xml">
]>
<chapter>
 <TITLE>Title &plainEntity;</TITLE>
 <para>
  <informaltable>
   <tgroup cols="3">
    <tbody>
     <row><entry>a1</entry><entry morerows="1">b1</entry><entry>c1</entry></row>
     <row><entry>a2</entry><entry>c2</entry></row>
     <row><entry>a3</entry><entry>b3</entry><entry>c3</entry></row>
    </tbody>
   </tgroup>
  </informaltable>
 </para>
 &systemEntity;
 <section id="about">
  <title>About this Document</title>
  <para>
   <!-- this is a comment -->
   <?php echo 'Hi!  This is PHP version ' . phpversion(); ?>
  </para>
 </section>
</chapter>

This file is included from xmltest.xml:

Пример 5. xmltest2.xml

<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY testEnt "test entity">
]>
<foo>
   <element attrib="value"/>
   &testEnt;
   <?php echo "This is some more PHP code being executed."; ?>
</foo>

Содержание
utf8_decode --  Converts a string with ISO-8859-1 characters encoded with UTF-8 to single-byte ISO-8859-1
utf8_encode -- Encodes an ISO-8859-1 string to UTF-8
xml_error_string -- Get XML parser error string
xml_get_current_byte_index -- Get current byte index for an XML parser
xml_get_current_column_number --  Get current column number for an XML parser
xml_get_current_line_number -- Get current line number for an XML parser
xml_get_error_code -- Get XML parser error code
xml_parse_into_struct -- Parse XML data into an array structure
xml_parse -- Start parsing an XML document
xml_parser_create_ns -- Create an XML parser with namespace support
xml_parser_create -- Create an XML parser
xml_parser_free -- Free an XML parser
xml_parser_get_option -- Get options from an XML parser
xml_parser_set_option -- Set options in an XML parser
xml_set_character_data_handler -- Set up character data handler
xml_set_default_handler -- Set up default handler
xml_set_element_handler -- Set up start and end element handlers
xml_set_end_namespace_decl_handler -- Set up end namespace declaration handler
xml_set_external_entity_ref_handler -- Set up external entity reference handler
xml_set_notation_decl_handler -- Set up notation declaration handler
xml_set_object -- Use XML Parser within an object
xml_set_processing_instruction_handler --  Set up processing instruction (PI) handler
xml_set_start_namespace_decl_handler --  Set up start namespace declaration handler
xml_set_unparsed_entity_decl_handler --  Set up unparsed entity declaration handler


utf8_decode> <xdiff_string_patch
Last updated: Sat, 27 Jan 2007
 
add a note add a note User Contributed Notes
XML Parser Functions
demonpants at gmail dot com
22-Oct-2007 08:59
I wanted to access the ISBN database, and was previously parsing the HTML string generated from their main page, that is until I discovered they have an API that returns XML.

So, if anyone wants to get some information from the ISBN database, all you need to do is the following.

<?php
//Search the ISBN database for the book.
           
$url = "http://www.isbndb.com/api/books.xml? access_key=KEY&index1=isbn&value1=$_GET[ISBN]";
           
$p = xml_parser_create();
           
xml_parse_into_struct($p,file_get_contents($url),$results,$index);
           
xml_parser_free($p);

           
$title = $results[$index[TITLELONG][0]][value];
           
$author = $results[$index[AUTHORSTEXT][0]][value];
           
$publisher = $results[$index[PUBLISHERTEXT][0]][value];
?>

You will need to get an access key from isbndb.com, but it takes two seconds and is free. When you get it, replace KEY in the URL with your own key. Also, my code above will search for the book that fits the ISBN number stored in the GET variable ISBN - you can search by other parameters and return more than one result, but my example is  for a simple ISBN search.
TeerachaiJ at GMail dot com
15-Oct-2007 02:17
I enhance xml2array (can't remember who author) to work with duplicate key index by change "tagData" function with this ->

<?
  function tagData($parser, $tagData) {  

    // set the latest open tag equal to the tag data

    $strEval = "\$this->arrOutput";
    foreach ($this->arrName as $value) {
      $strEval .= "[" . $value . "]";
      $arr .= "[" . $value . "]";        //*Enhance by T•J (array when dup)
    }

    eval("\$x=\$this->arrOutput" . $arr . ";");        //*Enhance by T•J (array when dup)
    if($x) { $strEval = $strEval . "[" . ++$this->arrOutput[$arr] . "] = \$tagData;"; }        //*Enhance by T•J (array when dup)
     else { $strEval = $strEval . " = \$tagData;"; }
   
    eval ($strEval);
  }
?>

I not sure have another do it now.
Hope!!! It will help your work.
Zvjezdan Patz
09-Sep-2007 08:22
The problem I had was I needed to generate xml on the screen for users to actually see and copy to a file. 

I'm generating the xml manually from a php file and the browser kept interpreting the xml...not very helpful. 

This is how you get around it:

<?

$file  = file_get_contents("http://fileurl/xml.php?whatever=$whatever");
print nl2br(htmlentities($file));

?>

Prints all my xml quite nicely.
v9 at fakehalo dot us
13-Jul-2007 08:04
I needed this for work/personal use.  Sometimes you'll have a XML string generated as one long string and no line breaks...nusoap in the case of today/work, but there are any other number of possible things that will generate these.  Anyways, this simply takes a long XML string and returns an indented/line-breaked version of the string for display/readability.

<?
function xmlIndent($str){
    $ret = "";
    $indent = 0;
    $indentInc = 3;
    $noIndent = false;
    while(($l = strpos($str,"<",$i))!==false){
        if($l!=$r && $indent>0){ $ret .= "\n" . str_repeat(" ",$indent) . substr($str,$r,($l-$r)); }
        $i = $l+1;
        $r = strpos($str,">",$i)+1;
        $t = substr($str,$l,($r-$l));
        if(strpos($t,"/")==1){
            $indent -= $indentInc;
            $noIndent = true;
        }
        else if(($r-$l-strpos($t,"/"))==2 || substr($t,0,2)=="<?"){ $noIndent = true; }
        if($indent<0){ $indent = 0; }
        if($ret){ $ret .= "\n"; }
        $ret .= str_repeat(" ",$indent);
        $ret .= $t;
        if(!$noIndent){ $indent += $indentInc; }
        $noIndent = false;
    }
    $ret .= "\n";
    return($ret);
}
?>

(...this was only tested for what i needed at work, could POSSIBLY need additions)
ricardo at sismeiro dot com
08-Jun-2007 04:29
<?php

/**
 * correction of the previous code
 */

/**
 * Converts XML into Array
 *
 * @param array $result
 * @param object  $root
 * @param string $rootname
 */
function convert_xml2array(&$result,$root,$rootname='root'){
   
   
$n=count($root->children());

    if (
$n>0){

       
/**
         * start of the correction
         */
       
if (!isset($result[$rootname]['@attributes'])){
           
$result[$rootname]['@attributes']=array();
            foreach (
$root->attributes() as $atr=>$value){
               
$result[$rootname]['@attributes'][$atr]=(string)$value;
            }           
        }
       
/**
         *  end of the correction
         */
       
        
foreach ($root->children() as $child){
            
$name=$child->getName();    
            
convert_xml2array($result[$rootname][],$child,$name);                         
         }
    } else {       
       
$result[$rootname]= (array) $root;
        if (!isset(
$result[$rootname]['@attributes'])){
           
$result[$rootname]['@attributes']=array();
        }
    }
}

/**
 * Example how to use the function convert_xml2array
 */

/**
 * Return  Array from a xml string
 *
 * @param string $xml
 * @return array
 */
function get_array_fromXML($xml){       
   
   
$result=array();   
   
   
$doc=simplexml_load_string($xml);    
   
   
convert_xml2array($result,$doc);    
   
    return
$result['root'];   
}

?>
adamaflynn at criticaldevelopment dot net
14-Apr-2007 11:50
Here is an example of another XML parsing script that parses the document into an array/object structure instead of relying on startElement, endElement, etc handlers.

You can find the documentation at:
http://www.criticaldevelopment.net/xml/doc.php

And the code (both PHP4 and PHP5 versions):
http://www.criticaldevelopment.net/xml/parser_php4.phps
http://www.criticaldevelopment.net/xml/parser_php5.phps

If you have any questions about it, just drop me an e-mail.
phpzmurf[at]yahoo.com
12-Apr-2007 04:19
/*
 * Parse rss news, quotes etc.
 *
 * author : phpZmurf <phpzmurf[at]yahoo.com>
 * created: 12.04.2007
 * ver    : 1.0
 *
*/

$data = implode("", file("http://feeds.feedburner.com/quotationspage/qotd/"));
$parser = xml_parser_create();
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
xml_parse_into_struct($parser, $data, $values, $tags);
xml_parser_free($parser);

# data saved here
$arrQuotes = array();
# at the beginig - the tag is set colsed
$tagOpen = false;

foreach($values as $key => $item) {
    if(!$tagOpen and $item['tag'] == 'item' and $item['type'] == 'open') {
        # item tag opens
        $tagOpen = true;
        # empty temporary variables
        $temp_title = '';
        $temp_description = '';
        $temp_guid = '';
        $temp_link = '';
    } elseif($item['tag'] == 'item' and $item['type'] == 'close') {
        # item tag ends
        $tagOpen = false;
        # if all 4 tags contain data... add them to output array
        if($temp_title != '' and $temp_description != '' and $temp_guid != '' and $temp_link != '') {
            $arrQuotes[] = array(
                'title' => $temp_title,
                'description' => $temp_description,
                'guid' => $temp_guid,
                'link' => $temp_link
            );
        }
    } else {
        # save data into temporary variables
        switch($item['tag']) {
            case 'title':
                $temp_title = $item['value'];
            break;
            case 'description':
                # this here quz there was a fuggin <p> at the end of the desription
                #$temp_description = $item['value'];
                $temp_description = substr($item['value'], 0, strpos($item['value'], '<'));
            break;
            case 'guid':
                $temp_guid = $item['value'];
            break;
            case 'link':
                $temp_link = $item['value'];
            break;
            default: break;
        }
    }
}

foreach($arrQuotes as $key => $item) {
    print_r($item);
}
Sheer Pullen
14-Mar-2007 07:27
I took the code posted by forqoun and modified it to be somewhat more readable (by me), somewhat more friendly to the idea of parsing multiple files with the same object, and to be compatable with a HTTP POST of XML data. Anyone who's interested in my version of associated array output can check it out at http://www.sheer.us/code/php/xml-parse-to-associative-array.phpsrc

Be nice to me, this is my first published php code
geoffers [at] gmail [dot] com
30-Dec-2006 03:27
Time to add my attempt at a very simple script that parses XML into a structure:

<?php

class Simple_Parser
{
    var
$parser;
    var
$error_code;
    var
$error_string;
    var
$current_line;
    var
$current_column;
    var
$data = array();
    var
$datas = array();
   
    function
parse($data)
    {
       
$this->parser = xml_parser_create('UTF-8');
       
xml_set_object($this->parser, $this);
       
xml_parser_set_option($this->parser, XML_OPTION_SKIP_WHITE, 1);
       
xml_set_element_handler($this->parser, 'tag_open', 'tag_close');
       
xml_set_character_data_handler($this->parser, 'cdata');
        if (!
xml_parse($this->parser, $data))
        {
           
$this->data = array();
           
$this->error_code = xml_get_error_code($this->parser);
           
$this->error_string = xml_error_string($this->error_code);
           
$this->current_line = xml_get_current_line_number($this->parser);
           
$this->current_column = xml_get_current_column_number($this->parser);
        }
        else
        {
           
$this->data = $this->data['child'];
        }
       
xml_parser_free($this->parser);
    }

    function
tag_open($parser, $tag, $attribs)
    {
       
$this->data['child'][$tag][] = array('data' => '', 'attribs' => $attribs, 'child' => array());
       
$this->datas[] =& $this->data;
       
$this->data =& $this->data['child'][$tag][count($this->data['child'][$tag])-1];
    }

    function
cdata($parser, $cdata)
    {
       
$this->data['data'] .= $cdata;
    }

    function
tag_close($parser, $tag)
    {
       
$this->data =& $this->datas[count($this->datas)-1];
       
array_pop($this->datas);
    }
}

$xml_parser = new Simple_Parser;
$xml_parser->parse('<foo><bar>test</bar></foo>');

?>
Didier: dlvb ** free * fr
24-Dec-2006 09:53
Hi !

After parsing the XML and modifying it, I just add a method to rebuild the XML form the internal structure (xmlp->document).
The method xmlp->toXML writes into xmlp->XML attributes. Then, you just have to output it.
I hope it helps.

class XMLParser {

var $parser;
var $filePath;
var $document;
var $currTag;
var $tagStack;
var $XML;
var $_tag_to_close = false;
var $TAG_ATTRIBUT = 'attr';
var $TAG_DATA = 'data';

function XMLParser($path) {
    $this->parser = xml_parser_create();
    $this->filePath = $path;
    $this->document = array();
    $this->currTag =& $this->document;
    $this->tagStack = array();
    $this->XML = "";
}

function parse() {
    xml_set_object($this->parser, $this);
    xml_set_character_data_handler($this->parser, 'dataHandler');
    xml_set_element_handler($this->parser, 'startHandler', 'endHandler');

   if(!($fp = fopen($this->filePath, "r"))) {
       die("Cannot open XML data file: $this->filePath");
       return false;
     }

    while($data = fread($fp, 4096)) {
        if(!xml_parse($this->parser, $data, feof($fp))) {
            die(sprintf("XML error: %s at line %d",
                xml_error_string(xml_get_error_code($this->parser)),
             xml_get_current_line_number($this->parser)));
      }
    }

    fclose($fp);
    xml_parser_free($this->parser);

    return true;
}

function startHandler($parser, $name, $attribs) {
     if(!isset($this->currTag[$name]))
          $this->currTag[$name] = array();

     $newTag = array();
     if(!empty($attribs))
          $newTag[$this->TAG_ATTRIBUT] = $attribs;
     array_push($this->currTag[$name], $newTag);

     $t =& $this->currTag[$name];
     $this->currTag =& $t[count($t)-1];
     array_push($this->tagStack, $name);
}

function dataHandler($parser, $data) {
    $data = trim($data);

    if(!empty($data)) {
      if(isset($this->currTag[$this->TAG_DATA]))
            $this->currTag[$this->TAG_DATA] .= $data;
      else
            $this->currTag[$this->TAG_DATA] = $data;
    }
}

function endHandler($parser, $name) {
     $this->currTag =& $this->document;
     array_pop($this->tagStack);

     for($i = 0; $i < count($this->tagStack); $i++) {
          $t =& $this->currTag[$this->tagStack[$i]];
          $this->currTag =& $t[count($t)-1];
     }
}

function clearOutput () {
    $this->XML = "";
}

function openTag ($tag) {
    $this->XML.="<".strtolower ($tag);
    $this->_tag_to_close = true;
}

function closeTag () {
    if ($this->_tag_to_close) {
        $this->XML.=">";
        $this->_tag_to_close = false;
    }
}

function closingTag ($tag) {
    $this->XML.="</".strtolower ($tag).">";
}

function output_attributes ($contenu_fils) {
    foreach ($contenu_fils[$this->TAG_ATTRIBUT] as $nomAttribut => $valeur) {
        $this->XML.= " ".strtolower($nomAttribut)."=\"".$valeur."\"";
    }
}

function addData ($texte) {
// to be completed
    $ca  = array ("
Новости
11 июля 2007
Сайт запущен
© 2007 info@grandviewstudio.com
Z058440144362 Z348613067571