[PHP] xml parsen

Stex

Zeta Sagittarii
ID: 54415
L
11 Mai 2006
937
185
Guten Abend!

Ich versuche gerade, eine xml-Datei mit PHP zu parsen... das klappt insofern schonmal, dass er die Datei durchgeht und überprüft, ob ein Element geöffnet oder geschlossen wird und er erkennt auch, ob Fließtext drin steht.

Allerdings möchte ich nun je nachdem, in welchem Element er sich befindet, den Fließtext einer anderen Variable zuweisen. Das ganze sollte dann als globale Variable laufen, was eigentlich auch funktioniert. Schöner wäre es, wenn es anders ginge, aber mir fällt nichts ein (was nicht heißt, dass es nichts gibt).

Die xml-Datei sieht so aus: https://www.stexmedia.com/pads/poker.xml

Wenn ich nur eine Bedinung hinmache und sage, er soll, wenn $e_name == "program_name" ist, der Variable $ausgabe den Fließtext zuweisen, funktioniert das super. Nur, wenn ich das alles abarbeiten möchte, geht es nicht.

Als bisherigen Code hatte ich das hier:
PHP:
<?php

function startElement($parser, $element_name, $element_attribute) {
global $ausgabe, $e_name;
//Umwandeln in Kleinbuchstaben
$element_name = strtolower($element_name);
//Überprüfung des Elementnames
$e_name = $element_name;
}

function endElement($parser, $element_name) {
global $ausgabe, $e_name;
// in Kleinbuchstaben umwandeln
$element_name = strtolower($element_name);
// Überprüfung des Names eines Elementes
}

function cdata($parser, $element_inhalt) {
global $ausgabe, $e_name, $p_name, $p_website, $p_version, $p_type, $p_updatetype, $p_jahr, $p_monat, $p_tag, $p_lastchange, $p_os, $p_install, $p_filesize, $p_description, $p_desclong, $p_screenshot, $p_infosite, $p_xmlfile;
// Der normale Text wird an $ausgabe angehängt
        if ($e_name == "program_name") {
            $p_name = $element_inhalt;
            }
        if ($e_name == "company_website_url") {
            $p_website = $element_inhalt;
            }
        if ($e_name == "program_version") {
            $p_version = $element_inhalt;
            }
        if ($e_name == "program_type") {
            $p_type = $element_inhalt;
            }
        if ($e_name == "program_release_status") {
            $p_updatetype = $element_inhalt;
            }
        if ($e_name == "program_release_year") {
            $p_jahr = $element_inhalt;
            }
        if ($e_name == "program_release_month") {
            $p_monat = $element_inhalt;
            }
        if ($e_name == "program_release_day") {
            $p_tag = $element_inhalt;
            }
        if ($e_name == "program_change_info") {
            $p_website = $element_inhalt;
            }
        if ($e_name == "program_os_support") {
            $p_os = $element_inhalt;
            }
        if ($e_name == "program_install_support") {
            $p_website = $element_inhalt;
            }
        if ($e_name == "file_size_mb") {
            $p_website = $element_inhalt;
            }
        if ($e_name == "char_desc_80") {
            $p_description = $element_inhalt;
            }
        if ($e_name == "char_desc_2000") {
            $p_desclong = $element_inhalt;
            }
        if ($e_name == "application_screenshot_url") {
            $p_screenshot = $element_inhalt;
            }
        if ($e_name == "application_info_url") {
            $p_infosite = $element_inhalt;
            }
        if ($e_name == "application_xml_file_url") {
            $p_xmlfile = $element_inhalt;
            }
}



$xmlFile = file("./pads/poker.xml");
$parser = xml_parser_create();
xml_set_element_handler($parser, "startElement", "endElement");
xml_set_character_data_handler($parser, "cdata");

foreach($xmlFile as $elem)
{
xml_parse($parser, $elem);
}
xml_parser_free($parser);

echo "name des Programms: ".$p_name;

?>
Ist sicher wieder ein Dummheitsfehler, ist aber auch das erste mal, dass ich mit xml in PHP arbeite.

Schönen Abend noch!

Gruß,
Stex

edit: Ach so, bei mir auf der Server läuft wohl noch php4, daher kein simplexml -.-
 
Zuletzt bearbeitet:
Das ganze sollte dann als globale Variable laufen
Globale Variablen sind aus Sicherheitsgründen bedenklich. Aber das nur mal so nebenbei.

Aus deinen ganzen If-Abfragen würde ich ein Switch machen.
Die Ergebnisse könntest du in ein assoziatives Array packen. Das reduziert die Menge an Variablen, die du hast.

Warum es nicht geht, weiß ich auch nicht. Und vor allem weiß ich nicht, welche Bedeutung $ausgabe haben soll. Diese Variable kommt nur in Zeile 19 vor. Ansonsten nirgends. Dürfte also in deinem Bsp leer sein.
 

Danke erstmal für die Antwort.

ich gehe die Punkte mal durch:

1. Globale Variablen waren das erste, was mir da einfiel, daher hab ichs genommen, dass es ein Sicherheitsrisiko ist, weiß ich.

2. Es war vorher ein Switch, ich dachte nur, das könnte aus irgendwelchen Gründen der Fehler sein und habs durch if-anweisungen ersetzt.

3. Die Variable $ausgabe habe ich vorher verwendet, um zu testen, ob überhaupt alles ausgelesen wird und habe sie pro durchlauf mit $ausgabe .= erweitert und zum schluss ausgegeben. Sie hat im Moment wirklich keine Bedeutung, aber sie dürfte auch nicht schaden.

Das mit dem Array ist eine gute Idee, aber es dürfte das Problem an sich nicht ändern.

in $e_name steht in der funktion cdata scheinbar immer dasselbe...
 
So. Habs jetzt einfach mal selber getestet. Und zwar habe ich in die Funktion CData folgendes eingefügt:
PHP:
// Der normale Text wird an $ausgabe angehängt
echo("$e_name - $element_inhalt<br>");

Als Ausgabe bekomme ich folgende 3 Zeilen für den Programm-Namen:
Code:
program_name - Pokeranalyse f
program_name - ür Onlinepoker
program_name -

Mir ist allerdings nicht klar, warum er aus einem Tag jetzt 3 Stück macht.
Um das ganze zu umgehen (wenn es nur 1 Programm pro XML-Datei gibt), könnte man vorher alle $p_ - Variablen initialisieren und dann den Element-Inhalt mit .= anfügen. In Auszügen so:
PHP:
<?php
$p_name = "";
...
if ($e_name == "program_name") {
            $p_name .= $element_inhalt;
            }
...
Dann gibt er das richtige aus.
 
Hm... mit .= funktioniert es, danke dafür erstmal.

Fällt dir noch eine andere Möglichkeit ein, das ohne globale Variablen zu lösen? Ich habe bisher auch noch nie wirklich mit denen gearbeitet, da meine Funktionen ohne auskamen, deshalb habe ich auch keine Erfahrung, was die Lösung dieses Problems anging
 
Ich benutze für PHP<5 eigentlich immer die folgende Klasse. Stammt ursprünglich aus den Comments bei php.net, wenn ich mich nicht täusche:
PHP:
<?php
class XMLParser
{
	var $parser;
	var $document;
	var $currTag;
	var $tagStack;
	var $data;

	function XMLParser($data)
	{
		$this->parser = xml_parser_create();
		$this->data = $data;
		$this->document = array();
		$this->currTag =& $this->document;
		$this->tagStack = array();
    }

	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(!xml_parse($this->parser, $this->data))
		{
			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);

		return true;
	}

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

		$newTag = array();
		if(!empty($attribs))
			$newTag['attr'] = $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['data']))
				$this->currTag['data'] .= $data;
			else
				$this->currTag['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];
		}
	}
}
?>
Benutzung folgendermassen:
PHP:
<?php
  require_once('./classes/XMLParser.class.php');
  $xml = new XMLParser(file_get_contents('inputfile.xml'));
  $xml->parse();
  echo '<pre>',print_r($xml->document, true),'</pre>';
?>
 
Sind doch beides Angaben von Klassen für PHP4 ;)

Richtig, dankeschön euch beiden!

Ich habe das jetzt aber erstmal einfach so gelöst, wie ich es am anfang hatte, nur dass ich am anfang den Variablen bzw. den Array-Elementen "" zugewiesen und sie dann im datahandler nur noch "erweitert" habe.

Warum das so ist, weiß ich nicht, normalerweise kann man ja auch globale Variablen in Funktionen erstellen, habe ich zumindest so gelesen.

Edit:
Studieren bringts wohl doch, Umgebungsmodell lässt grüßen.
 
Zuletzt bearbeitet: