Hi, the four attached files will run fine if you call them as they stand now.
If you uncomment the $this->Template->printer(); in the printItem function of
the eZNewsCustomerHH object, you'll get a "<b>Fatal error</b>: Call to a
member function on a non-object in <b>eznews/classes/eznewscustomerhh.php</b>
on line <b>157</b><br>".
What is going on?
For those of you who don't see how this slew of code is supposed to work,
here's a quick walk through.
Read this http://www.phpbuilder.com/columns/joe20000907.php3" on XML, then
ask your self, how can I do this dynamically and through objects...
Well, take file eznewsxmlparser.php, that file is the parser code, exactly as
Joe Stump describes it in his article. Each time you need some parsing done,
call that file. We need a global $data element floating around for this to
work.
Eznewsxmlparser.php includes eznewsxmlfunctions.php. This file has the
callback functions which we registered with the xml_parser object in the
first file. You can see that this one assumes that we have yet another
global, theXMLParser, which is an object which implements the interface of
eZNewsXML.
The functions in eznewsxmlfunctions.php has to be visible for the xml_parser,
since I've found no way of tricking functions in objects into the xml_parser.
Finally we have the eznewscustomerhh.php file. Inside that file there is a
couple of global tag definitions, which is used as pr. Joes tutorial. Then
there is a little phony class, which is used to illustrate my problem.
Finally we come to the eZNewsCustomerHH class, which is the class I wan't to
use.
Most of Joe's article has by this point be abstracted away, and everything
looks fine. That's until we get to any function in the eZNewsCustomerHH
object after we've included the eznewsxmlparser.php file.
After the xml parsing has been done, the object we're working on seems to
have lost all knowledge of the previously created drop object.
Where did it go? How is the scope, what on earth is happening.
I'm this close from making an elegant system for parsing XML, but this screws
it up.
eznewsxmlparser.php
<?
//
// $Id: $
//
// Definition of eZNewsXML support functions.
//
// Paul K Egell-Johnsen <pkej@ez.no>
// Created on: <28-Sep-2000 13:42:10 pkej>
//
include_once( "eznews/classes/eznewsxmlfunctions.php" );
global $theXMLParser;
global $data;
// declare the character set - UTF-8 is the default
$type = 'US-ASCII';
$type = 'ISO-8859-1';
$type = 'UTF-8';
// create our parser
$xml_parser = xml_parser_create($type);
// set some parser options
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false);
xml_parser_set_option($xml_parser, XML_OPTION_TARGET_ENCODING, $type);
// this tells PHP what functions to call when it finds an element
// these funcitons also handle the element s attributes
xml_set_element_handler($xml_parser, 'startElement','endElement');
// this tells PHP what function to use on the character data
xml_set_character_data_handler($xml_parser, 'characterData');
#if (!($fp = fopen($xml_file, 'r'))) {
die("Could not open $xml_file for parsing!\n");
#}
// loop through the file and parse baby!
if( !( $data = utf8_encode($data) ) )
{
}
if( !xml_parse( $xml_parser, $data ) )
{
die(sprintf( "XML error: %s at line %d\n\n",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}
xml_parser_free($xml_parser);
?>
eznewsxmlfunctions.php
<?php
global $data;
global $theXMLParser;
//!! eZNews
//! startElement global callback used by the XML parser.
/
This function is a callback. It requires a global instance of an object.
That object must have a function called startElement.
/
function startElement( $parser, $name, $attrs='' )
{
global $theXMLParser;
$theXMLParser->startElement( $parser, $name, $attrs='' );
}
//!! eZNews
//! endElement global callback used by the XML parser.
/
This function is a callback. It requires a global instance of an object.
That object must have a function called endElement.
/
function endElement($parser, $name, $attrs='')
{
global $theXMLParser;
$theXMLParser->endElement( $parser, $name, $attrs='' );
}
//!! eZNews
//! addToOldTag global callback used by the XML parser.
/
This function is a callback. It requires a global instance of an object.
That object must have a function called addToOldTag.
/
function addToOldTag( $data )
{
global $theXMLParser;
$theXMLParser->addToOldTag( $data );
}
//!! eZNews
//! characterData global callback used by the XML parser.
/
This function is a callback. It requires a global instance of an object.
That object must have a function called characterData.
/
function characterData($parser, $data)
{
global $theXMLParser;
$theXMLParser->characterData($parser, $data);
}
?>
eznewsxml.php
<?
//
// $Id: eznewsxml.php,v 1.2 2000/09/28 12:48:35 pkej-cvs Exp $
//
// Definition of eZNewsXML class and support functions.
//
// Paul K Egell-Johnsen <pkej@ez.no>
// Created on: <28-Sep-2000 13:42:10 pkej>
//
//!! eZNews
//! eZNewsXML handles XML callbacks.
/*!
Create a child class extending this class. Create two functions in the
child class, one called startElement the other endElement. Check out
the global callbacks startElement and checkElement for example of how
you use the functions in your object.
Your object file also needs to have opening tags and closing tags in
order to be usable.
The startElement and endElement in this base class are abstract. The
code inside it would have worked with the XML in example 1.
This code is based on this <A href="http://www.phpbuilder.com/columns/joe20000907.php3">
article</A> by Joe Stump.
Example:
\code
// Example 1 - XML
<?xml version="1.0"?>
<ezflower>
<product>
<name>
The name of the product.
</name>
<description>
Information about this product.
</description>
<price>
Any text over several lines.
</price>
<pictureid value="1"/>
<categoryid value="4"/>
</product>
</ezflower>
\endcode
*/
class eZNewsXML
{
/*!
Constructs a new eZNewsCommand object. This must be called from
base classes. ( eZNewsXML::eZNewsXML() in childs constructor )
*/
function eZNewsXML()
{
global $theXMLParser;
$theXMLParser = $this;
}
//!! eZNews
//! startElement takes care of the start tags in an XML document.
/*
This function is abstract, but you'll find example code inside
for how you could implement this in your own class.
*/
function startElement( $parser, $inName, $attrs='' )
{
die("Take care of startElement() in a subclass of eZNewsXML,
and make sure that you override the functions
startElement and endElement. ");
$this->currentTag = $inName;
if ( $format == $openTags[$inName] )
{
switch( $inName )
{
case 'pictureid':
$this->parsedXMLAttributes[ $this->currentTag ]["value"] = $attrs["value"];
break;
case 'categoryid':
$this->parsedXMLAttributes[ $this->currentTag ]["value"] = $attrs["value"];
break;
default:
break;
}
}
}
//!! eZNews
//! endElement takes care of the end tags in an XML document.
/*
This function is abstract, but you'll find example code inside
for how you could implement this in your own class.
*/
function endElement( $parser, $inName, $attrs='' )
{
die("Take care of endElement() in a subclass of eZNewsXML,
and make sure that you override the functions
startElement and endElement. ");
if( $format == $closeTags[ $inName ] )
{
switch( $inName )
{
case 'ezflower':
$this->printPage( );
$this->parsedXML = '';
break;
case 'product':
$this->printItem( );
$this->parsedXML = '';
break;
default:
break;
}
}
}
//!! eZNews
//! addToOldTag adds data from the stream to the last tag parsed.
/*
This function does the magic of ensuring that all character data
is stored in the correct data element of the $temp array.
*/
function addToOldTag( $data )
{
$data = utf8_decode( $data );
$this->parsedXML[ $this->lastTag ] = $this->parsedXML[ $this->lastTag ] . $data;
if( $data == "\n" || $data == "\r" )
{
$this->parsedXML[ $this->lastTag ] = $this->parsedXML[ $this->lastTag ] . "<br>\n";
}
if( $data == "\t" )
{
$this->parsedXML[ $this->lastTag ] = $this->parsedXML[ $this->lastTag ] . "\t";
}
}
//!! eZNews
//! characterData stores data in the value array.
/*
This function takes character data and stores it in an array where
the key is the tag name.
*/
function characterData( $parser, $data )
{
if( empty( $this->currentTag ) )
{
$this->addToOldTag( $data );
}
else
{
$this->parsedXML[ $this->currentTag ] = utf8_decode( $data );
$this->lastTag = $this->currentTag;
$this->currentTag = '';
}
}
/// This is used for storing XML data. The data for each tag can be found in this associative array.
var $parsedXML = array();
/// This is used for storing XML attributes. The attribute for each tag can be found in this associative array.
var $parsedXMLAttributes = array();
var $currentTag;
var $lastTag;
}
?>
eznewscustomerhh.php
<?php
//
// $Id: eznewscustomerhh.php,v 1.1 2000/09/28 13:07:22 pkej-cvs Exp $
//
// Definition of eZNewsCustomerHH class
//
// Paul K Egell-Johnsen <pkej@ez.no>
// Created on: <28-Sep-2000 13:03:00 pkej>
//
global $data;
global $theXMLParser;
//!! eZNews
//! $openTags handles the XML open tags.
/
This is the array of opening tags. All character data between an opening
and closing tag is stored in the global $parsedXML array, with the name
of the tag as the key to the data.
/
$openTags = array
(
'ezflower' => '<ezflower>',
'price' => '<price>',
'name' => '<name>',
'description' => '<description>',
'pictureid' => '<pictureid/>',
'categoryid' => '<categoryid/>',
'product' => '<product>',
'id' => '<id/>'
);
//!! eZNews
//! $closeTags handles the XML close tags.
/
This is the array of closing tags. All character data between an opening
and closing tag is stored in the global $parsedXML array, with the name
of the tag as the key to the data.
/
$closeTags = array
(
'ezflower' => '</ezflower>',
'price' => '</price>',
'name' => '</name>',
'description' => '</description>',
'product' => '</product>'
);
//!! eZNews
//! eZNewsCustomerHH handles parsing for our customer Heistad Hagesenter.
/!
/
include_once( "eznews/classes/eznewsxml.php" );
$data = <<<EOT
<?xml version="1.0"?>
<ezflower> <product> <name>Dekorasjoner</name>
<description>Vi kan også skaffe det meste av andre dekorasjoner til kiste og
kirke.</description> <price>På forespørsel</price> <pictureid value="90"/>
<categoryid value="8"/> </product> <product> <name>Kranser</name>
<description>Her er den enkleste typen kranser vi kan tilby: En enkelt
blomst!</description> <price>Kr. 10,-</price> <pictureid value="89"/>
<categoryid value="8"/> </product> <product> <name>Bla bla</name>
<description>asdfasdfa asdf asdf asdfasasdf as df asdf a sdf</description>
<price>200 300 400</price> <pictureid value="97"/> <categoryid value="8"/>
</product> </ezflower>
EOT;
class drop
{
function drop()
{
$this->Value1 = "bother not";
$this->Value2 = "bother too";
}
function printer()
{
echo "Value1: " . $this->Value1 . "<br>";
echo "Value2: " . $this->Value2 . "<br>";
}
var $Value1;
var $Value2;
};
class eZNewsCustomerHH extends eZNewsXML
{
function eZNewsCustomerHH( $URLArray )
{
}
function cheating()
{
eZNewsXML::eZNewsXML();
$template = new drop();
$this->Template = &$template;
$this->Template->printer();
include( "eznews/classes/eznewsxmlparser.php" );
}
function startElement( $parser, $inName, $attrs='' )
{
$this->currentTag = $inName;
if ( $format == $openTags[$inName] )
{
switch( $inName )
{
case 'pictureid':
$this->parsedXMLAttributes[ $this->currentTag ]["value"] = $attrs["value"];
break;
case 'categoryid':
$this->parsedXMLAttributes[ $this->currentTag ]["value"] = $attrs["value"];
break;
default:
break;
}
}
}
function endElement( $parser, $inName, $attrs='' )
{
if( $format == $closeTags[ $inName ] )
{
switch( $inName )
{
case 'ezflower':
$this->printPage( );
$this->parsedXML = '';
break;
case 'product':
$this->printItem( );
$this->parsedXML = '';
break;
default:
break;
}
}
}
function printItem()
{
echo "<h1>" . $this->parsedXML["name"] . "</h1>";
echo "<p>" . $this->parsedXML["description"] . "</p>";
echo "<p><b>" . $this->parsedXML["price"] . "</b></p>";
}
function printPage()
{
$this->Template->printer();
}
var $Item;
var $Template;
var $Ini;
};
?>