Jump to content

help with PHP that reads a simple XML file


dpace32

Recommended Posts

Hello -

 

First time poster and pretty new to PHP. I have tried to research this before posting but I couldn't find any tutorials with this exact scenario.

 

I am trying to create a PHP file that reads an XML file with the following layout:

 

<Root>

-

<Vehicle="Red">

<Trip>1108</Trip>

<Platform>123RFIES</Platform>

<InformationType>Slow</InformationType>

</Red>

-

<Vehicle="Red">

<Trip>1108</Trip>

<Platform>123RSHAS</Platform>

<InformationType>Fast</InformationType>

</Red>

 

I am using the following PHP:

 

<?php

$file = "Vehicle.xml";

 

function contents($parser, $data){

echo $data;

}

 

function startTag($parser, $data){

echo "<b>";

}

 

function endTag($parser, $data){

echo "</b><br />";

}

 

$xml_parser = xml_parser_create();

 

xml_set_element_handler($xml_parser, "startTag", "endTag");

 

xml_set_character_data_handler($xml_parser, "contents");

 

$fp = fopen($file, "r");

 

$data = fread($fp, 80000);

 

if(!(xml_parse($xml_parser, $data, feof($fp)))){

die("Error on line " . xml_get_current_line_number($xml_parser));

}

 

xml_parser_free($xml_parser);

 

fclose($fp);

?>

 

Using this code I can read the entire XML and display it on the webpage. What I am trying to do is filter it so it only displays when InformationType = Fast and only display the Trip and the InformationType. Where do I add this filter logic?

 

Thank you in advance!  :D

-Adam

 

Because the three call-back functions - startTag, endTag, and contents are completely independent and the xml_parser_ does not provide any way to communicate the current state between the functions, it is better if you wrap your code with an OOP/Class so that you can use class variables to communicate the current state between the functions.

 

Once you do this, you can set a flag(s) when you detect the correct startTag value(s) so that you only process the data that matches the tag(s) you are looking for.

Because the three call-back functions - startTag, endTag, and contents are completely independent and the xml_parser_ does not provide any way to communicate the current state between the functions, it is better if you wrap your code with an OOP/Class so that you can use class variables to communicate the current state between the functions.

 

Once you do this, you can set a flag(s) when you detect the correct startTag value(s) so that you only process the data that matches the tag(s) you are looking for.

 

hmmm can you give me an example?

 

Thanks!

<?php
// use OOP so that the call-back fucntions can share values

// The real advantage of the xml_parser is that it parses the file line by line. This does however require that you "remember"
// the current tag if you are not directly outputing content in order to associate the correct data with it

class xml_class {
private $parser; // instance of the xml_parser
private $current = array(); // current set of values
private $tag; // current tag

function __construct(){
	$this->parser = xml_parser_create();
	xml_set_element_handler($this->parser, array('xml_class', 'start'),array('xml_class', 'stop'));
	xml_set_character_data_handler($this->parser, array('xml_class', 'char'));
}

function doit($file){
	$fp=fopen($file,"r");
	while ($data=fread($fp,4096)){
		xml_parse($this->parser,$data,feof($fp)) or die (sprintf("XML Error: %s at line %d",xml_error_string(xml_get_error_code($this->parser)),xml_get_current_line_number($this->parser)));
	}
	xml_parser_free($this->parser);
}

function start($parser, $element_name, $element_attrs){
	//echo 's' . $element_name . 's';
	$this->tag = $element_name; // remember the current tag
	switch($element_name){
		case "RED":
			// this is the start of a set of data
			$this->current = array(); // create an empty set
		break;
		default:
	}
}

function stop($parser, $element_name){
	//echo 'e' . $element_name . 'e';
	switch($element_name){
		case "RED":
			// this is the tag that is after the end of the stated set of data, complete and execute the query here -
			// code to build the whole query statement and your mysql_query() goes here ...
			print_r($this->current); // contains the values for [TRIP], [PLATFORM], and [iNFORMATIONTYPE]
			echo "<br />";
		break;
		default:
	}
}

function char($parser,$data){
	$data = trim($data);
	if($data != ''){
		$this->current[$this->tag] = $data;
		// echo "Tag: {$this->tag}, Value: $data<br />";
	}
}
} // end of class

$file = 'vehicle.xml';
$xml = new xml_class();
$xml->doit($file);
?>

<?php
// use OOP so that the call-back fucntions can share values

// The real advantage of the xml_parser is that it parses the file line by line. This does however require that you "remember"
// the current tag if you are not directly outputing content in order to associate the correct data with it

class xml_class {
private $parser; // instance of the xml_parser
private $current = array(); // current set of values
private $tag; // current tag

function __construct(){
	$this->parser = xml_parser_create();
	xml_set_element_handler($this->parser, array('xml_class', 'start'),array('xml_class', 'stop'));
	xml_set_character_data_handler($this->parser, array('xml_class', 'char'));
}

function doit($file){
	$fp=fopen($file,"r");
	while ($data=fread($fp,4096)){
		xml_parse($this->parser,$data,feof($fp)) or die (sprintf("XML Error: %s at line %d",xml_error_string(xml_get_error_code($this->parser)),xml_get_current_line_number($this->parser)));
	}
	xml_parser_free($this->parser);
}

function start($parser, $element_name, $element_attrs){
	//echo 's' . $element_name . 's';
	$this->tag = $element_name; // remember the current tag
	switch($element_name){
		case "RED":
			// this is the start of a set of data
			$this->current = array(); // create an empty set
		break;
		default:
	}
}

function stop($parser, $element_name){
	//echo 'e' . $element_name . 'e';
	switch($element_name){
		case "RED":
			// this is the tag that is after the end of the stated set of data, complete and execute the query here -
			// code to build the whole query statement and your mysql_query() goes here ...
			print_r($this->current); // contains the values for [TRIP], [PLATFORM], and [iNFORMATIONTYPE]
			echo "<br />";
		break;
		default:
	}
}

function char($parser,$data){
	$data = trim($data);
	if($data != ''){
		$this->current[$this->tag] = $data;
		// echo "Tag: {$this->tag}, Value: $data<br />";
	}
}
} // end of class

$file = 'vehicle.xml';
$xml = new xml_class();
$xml->doit($file);
?>

 

 

Thank you for the quick reply - I tried this but it is still displaying all the data and now it is wrapping array around the output.

 

I think this part is producing the output:

 

   function stop($parser, $element_name){
      //echo 'e' . $element_name . 'e';
      switch($element_name){
         case "RED":
            // this is the tag that is after the end of the stated set of data, complete and execute the query here -
            // code to build the whole query statement and your mysql_query() goes here ...
            print_r($this->current); // contains the values for [TRIP], [PLATFORM], and [iNFORMATIONTYPE]
            echo "<br />";
         break;
         default:
      }

 

How do I filter this so it only shows where INFORMATIONTYPE = FAST and only display the Trip and the InformationType?

 

Thank you again.

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.