• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Problem mit SimpleXML

Status
Für weitere Antworten geschlossen.
G

Gelöschtes Mitglied 2703

Guest
prophet und ich haben einen komischen fehler entdeckt bei den objekten die SimpleXML erzeut.
[php:1:2e0ec81521]
$navigation = simplexml_load_file('content.xml');
echo var_dump($navigation);
echo var_dump($navigation->a);
[/php:1:2e0ec81521]
Code:
<main>
   <a>
       <b/>
   </a>
   <a>
       <b/>
   </a>
   <a>
       <b/>
   </a>
</main>
Code:
object(SimpleXMLElement)#1 (1) {
  ["a"]=>
  array(3) {
    [0]=>
    object(SimpleXMLElement)#2 (1) {
      ["b"]=>
      object(SimpleXMLElement)#5 (0) {
      }
    }
    [1]=>
    object(SimpleXMLElement)#3 (1) {
      ["b"]=>
      object(SimpleXMLElement)#6 (0) {
      }
    }
    [2]=>
    object(SimpleXMLElement)#4 (1) {
      ["b"]=>
      object(SimpleXMLElement)#7 (0) {
      }
    }
  }
}
Code:
object(SimpleXMLElement)#8 (1) {
  ["b"]=>
  object(SimpleXMLElement)#10 (0) {
  }
}
kann mir da jemand weiterhelfen?? ich finde das total unlogisch
 
Werbung:
Code abschnitt 3 zeigt ja den strukturellen aufbau der objekt hirarchie der verarbeiteten xml datei. ansich sieht das ja gut aus. jedoch:

wenn ich nun folgendes versuch:
[php:1:62c7acaacf]<?php
echo count($main->a);
?>[/php:1:62c7acaacf]
müsste jatheoretisch 3 herauskommen da diese variable ein array ist jedoch erhalten wir 0.

mein problem war nun das ich meine seiten verwaltung in form einer xml datei machen wollte. meine schleifen aus diesem grund zwar funktionieren jedoch wenn ich anfang und ende bestimmen will (also $index == 0 oder $index == count($main->a)-1) falsche ergebnisse kommen und mein algorhytmus falsch arbeitet.

for schleifen fallen daher weg da ich zu dessen verarbeitung diese parameter brauche. und bei foreach schleicfen gibt er mir eine warnuung $main->a wäre ein falscher parameter. grundesätzlich funktionieren sie dann zwar aber die inneren abragen sind halt hin. ich poste heute mahmittag nochmal meinen code.
 
Werbung:
oh das verändetr ja alles ich werde es sofort testen!

EDIT selbst wenn ich die sachen mit children aufrufe kommt beim count nur mist hier all mein code:

XML-Dokument:
Code:
<?xml version="1.0" encoding="ISO-8859-1" ?>

<navigation>
	<gruppe name="Home" datei="home/home.php" code="home">
		<seite name="Willkommen" datei="webdesign/html/einfuehrung.php" code="willkommen" />
		<seite name="G%auml;stebuch" datei="webdesign/html/elemente.php" code="gaestebuch" />
		<seite name="Kontakt" datei="webdesign/html/attribute.php" code="kontakt" />
		<seite name="Partner" datei="xxx" code="partner" />
		<seite name="Danksagung" datei="xxx" code="danksagung" />
		<seite name="Impressum" datei="xxx" code="impressum" />
		<seite name="Disclaimer" datei="xxx" code="disclaimer" />
	</gruppe>
	<gruppe name="Webdesign" datei="webdesign/webdesign.php" code="webdesign">
		<seite name="Farben %amp; Gr%ouml;%szlig;en" datei="webdesign/farben_groesen.php" code="farben_groesen" />
		<seite name="HTML" datei="webdesign/html/html.php" code="html" />
		<seite name="Einf%uuml;hrung" datei="webdesign/html/einfuehrung.php" code="html_einfuehrung" />
		<seite name="Elemente" datei="webdesign/html/elemente.php" code="html_elemente" />
		<seite name="Attribute" datei="webdesign/html/attribute.php" code="html_attribute" />
		<seite name="Sonderzeichen" datei="webdesign/html/sonderzeichen.php" code="html_sonderzeichen" />
		<seite name="CSS" datei="webdesign/css/css.php" code="css" />
		<seite name="Einf%uuml;hrung" datei="" code="css_einfuehrung" />
		<seite name="Referenz" datei="webdesign/css/referenz.php" code="css_referenz" />
	</gruppe>
	<gruppe name="Programmieren" datei="#" code="programmieren">
		<seite name="C/C++" datei="xxx" code="cpp" />
		<seite name="Delphi/Pascal" datei="xxx" code="delphi" />
		<seite name="Java" datei="xxx" code="java" />
	</gruppe>
	<gruppe name="Mitglieder" datei="#" code="mitglieder">
		<seite name="Einstellungen" datei="xxx" code="einstellungen" />
		<seite name="Administration" datei="xxx" code="administration" />
	</gruppe>
	<gruppe name="Forum" datei="#" code="forum">
		<seite name="Abonnemonts" datei="xxx" code="abonnemonts" />
	</gruppe>
</navigation>

Verarbeitung:
[php:1:283dd21ffc]<?php
function ReplaceEntities($string)
{
$new_str = str_replace('%uuml;', '&uuml;', $string);
$new_str = str_replace('%Uuml;', '&Uuml;', $new_str);
$new_str = str_replace('%ouml;', '&ouml;', $new_str);
$new_str = str_replace('%Ouml;', '&Ouml;', $new_str);
$new_str = str_replace('%auml;', '&auml;', $new_str);
$new_str = str_replace('%Auml;', '&Auml;', $new_str);
$new_str = str_replace('%szlig;', '&szlig;', $new_str);
$new_str = str_replace('%amp;', '&amp;', $new_str);

return $new_str;
}

function ListNavigation($root, $akt_site, $url_site)
{
foreach($root->children() as $group_id=>$group)
{
$group_attributes = $group->attributes();

if($group_id == 0)
echo "<div class=\"top\">\n";
elseif($group_id == count($root->children())-1)
echo "<div class=\"bottom\">\n";
else
echo "<div>\n";
echo "<a class=\"h1\" href=\"index.php?seite=".$group_attributes['code']."\">".ReplaceEntities($group_attributes['name'])."</a>\n";

if($group_attributes['code'] == $url_site)
$akt_site = $group_attributes;

foreach($group->children() as $site_id=>$site)
{
$site_attributes = $site->attributes();

if($site_id == count($group->children())-1)
echo "<a class=\"bottom\" ";
else
echo "<a ";

echo "href=\"index.php?seite=".$site_attributes['code']."\"> &gt; ".ReplaceEntities($site_attributes['name'])."</a>\n";

if($site_attributes['code'] == $url_site)
$akt_site = $site_attributes;
}

echo "</div>\n";
}
}

$navigation = simplexml_load_file('source/content.xml');
$include_site = array();
ListNavigation($navigation, $include_site, $seite);
?>[/php:1:283dd21ffc]

ihr könnt es ja mal testen das hauptproblem ist das der index nach var_dump eine zahl ist aber jeglicher zugriff darauf scheitert weil man eine falschen wert erhält...
 
So wie ich das verstehe, gibt children() nur einen Iterator zurück, d.h. ein count darauf liefert ein falsches Ergebnis. Durch XPath-Abfragen kannst du Dir alle entsprechenden Kinder zurückgeben lassen und die dann zählen. Also so:
[php:1:727e2674d2] $children = $group->xpath('seite');
$childcount = count($children);

foreach($children as $site_id => $site)
{
$site_attributes = $site->attributes();

if($site_id == $childcount-1)
echo "<a class=\"bottom\" ";
else
echo "<a ";
[/php:1:727e2674d2]
Das muss statt der inneren foreach-Schleife hin, dann klappt bei mir.

Laut PHP-Doku existiert für xpath() noch keine Versionsinfo, keine Ahnung also, ab welcher PHP Version das funzt.

Warum count nicht geht, foreach aber schon verstehe ich auch nicht. Ich dachte, bei dem neuen Iterator Interface würde das gehen. Weiss da jemand mehr?
 
Werbung:
was genau ist ein iterator? diesen begriff habe ich schonmal gehört kann aber nichts damit anfangen. ich werde es versuchen...
 
Ein Iterator ist sowas wie ein Zeiger auf eine Menge von Elementen. Man kann ihn vorwärts und evtl. rückwärts bewegen um zum nächsten, bzw. vorherigen Element zu kommen. Den Iterator kann man quasi direkt als Element benutzen und muss nicht, wie bei einem Index, einen Umweg über die Datenstruktur machen um das Element zu erhalten.

In Java und C++ mit STL wird häufig mit Iteratoren gearbeitet, weil es sauberer und meist schneller ist.
 
Wieder was gelernt ;)
Hab es grade mal nachgebaut funktioniert super :D
 
Werbung:
Ja stimmt jetzt funktioniert alles. danke charlie07!

Zum Iterator:

Ein Zeiger? Ok zeiger verstehe ich aber ich verstehe nicht was hier ein Zeiger zu suchen hat und wie das teil funktionieren soll.
 
Ein Iterator ist ein sog. Entwurfsmuster. Es handelt sich nicht direkt um einen Zeiger wie aus C++ bekannt, sondern meist um ein Objekt o.Ä. Vorteil ist, dass der Programmierer, der den Iterator benutzt, nicht wissen muss, wie die zugrundeliegende Datenstruktur aussieht. Ob Liste, Array, Baum oder sonstwas ist egal, da das Zugriffs-Interface feststeht. Die PHP SPL bringt ein paar Iteratoren mit (http://www.php.net/manual/en/ref.spl.php).

Ein vielverwendetes Beispiel sind die Rückgaben von mysql_query. Man bekommt quasi einen Iterator, mit dem man die einzelnen Elemente der Ergebnismenge durchgehen kann. Wie PHP die Daten von MySql bekommt und wie es die intern speichert kann dem Programmierer somit egal sein.

Bei SimpleXML wird scheinbar sowas ähnliches gemacht. Statt den kompletten DOM-Baum aufzubauen, was bei großen XML-Dateien mit ein paar hundert MB schnell zu Problemen führt, stellt SimpleXML scheinbar nur Iteratoren zur Verfügung und holt sich die Daten dynamisch. Wie die dann XPath-Abfragen realisieren, keine Ahnung, aber nett, dass es geht.

Alles klar? 8)
 
Werbung:
... wobei sie da dann ja auch irgendwie die Anzahl der Kinder bereitstellen könnten, so dass man nicht den Umweg über XPath nehmen muss.
 
Ich habe meine Funktion jetzt mit xpath angelegt damit ich das ebnde und den anfang der kindelemente finden kann. es funktioniert jetzt auf jenden fall. :)

Ok sinn und prinzip eines iterators habe ich begriffen aber ich habe keine ahnung wie man solch ein komplexes Objekt welches man überall einsetzten kann und auf alle möglichen strukturen zugreifen kann intern erstellt / organisiert.
 
Status
Für weitere Antworten geschlossen.
Zurück
Oben