rukursion, datenstuktur in xml baum wandeln
flobee
- php
hallo
ich sitze mal wieder vor dem gleichen problem wie alle paar monate.
ich möchte rekursiv durch ein mehrdimensionales array laufen und nun die datenstrucktur in ein xml zurückgeben.
insbesondere wenn es in die tiefe geht blicke ich nicht mehr durch welche "schalter" ich in einer klasse benötige um den zu öffneden tag bzw den schliessenden tag nach dem durchlauf von N children einzu setzen.
vielleich habe ich auch zu wenig methoden oder vergesse gewisse dinge bis ich mich dann dabei erwische wie ich die rekursion gar nicht verwende da ich fast für jede ebene eine neu schleife schreibe :-(
mein array sieht wie folgt aus:
<code>$data;
</code>
$data = array(
array('nodeName'=>'music',
'nodeAttr'=>array('id'=>199,'name'=>'FirstName'),
'nodeValues'=>false,
'children'=>array(
array(
'nodeName'=>'album',
'nodeValues'=>false,
'nodeAttr'=>array('albumid'=>'1234',
'albumname'=>'The King'),
'children'=>array(
array(
'nodeName'=>'tracks',
'nodeValues'=>false,
'nodeAttr'=>array('albumid'=>'1234'),
'children'=>array(
'nodeName'=>'track',
'nodeValues'=>array(array('VALUE1',$attributes),
array('VALUE2',$attributes)
),
'nodeAttr'=>$attributes,
'children'=>false
),
),
array(
'nodeName'=>'information',
'nodeValues'=>array(array('artist',$attributes),
array('autor',$attributes),
array('lenght',$attributes),
array('size',$attributes)
),
'nodeAttr'=>array('albumid'=>'1234'),
'children'=>false
),
),
)
)
)
);
ich habe hier insgesammt 3 grund methoden
vielleicht kann mir ja jemend schritt weise erkläre was ich beachten muss.
lieben gruß
florian
hallo florian
zur Grundstruktur:
function mach_xml($a)
{
Definition von benötigkten Variablen
$br="\n";
$S =' ';
Aufbau des Elements
$element.=$br.'<'.$a['nodeName'];
Aufbau der Attribute
if(isset($a['nodeAttr']))
{
foreach($a['nodeAttr'] as $k=>$v)
{
$element.=$S.$k.'="'.$v.'"';
}
}
Bestimmung des Inhalts
if($a['nodeValues'])
{
# Bestimmung Welche Art Inhalt vorliegt
if(is_array($a['nodeValues']))
{
# Aufbau der Kindelemente
foreach($a['nodeValues'] as $v)
{
# Rekursion auf die Kindelemente
$element.='>'.mach_xml($v);
$element.='</'.$a['nodeName'].'>'.$br;
}
}
elseif($a['nodeValues'])
{
# Kindelement ist ein Textnode
$element.='>'.$a['nodeValues'];
$element.='</'.$a['nodeName'].'>'.$br;
}
else
{
# Element ist leer
$element.=$S.'/>'.$br;
}
}
}
Mit obiger nicht geprüfter Funktion müßte Dein Datenfeld durchlaufen werden können. Allerdings bin ich anders, als Du, davon ausgegangen nodeValues beinhaltet Kindelemente!
nodeValues=children
Der Wert FALSE für nodeValues drückt ein leeres Element aus
Gruß aus Berlin!
eddi
hallo florian
habe mir meinen Müll nochmals zur Brust genommen und folgendes ist nun funktionstüchtig herausgekommen:
<?php
function mach_xml($a,$b=array('',TRUE))
{
Definition von benötigkten Variablen
$br="\n";
$S =' ';
Aufbau des Elements
$element= $b[1] ? '<?xml version="1.0" ?>' : '';
$element.=$br.$b[0].'<'.$a['nodeName'];
Aufbau der Attribute
if(is_array($a['nodeAttr']))
{
foreach($a['nodeAttr'] as $k=>$v)
{
$element.=$S.$k.'="'.$v.'"';
}
}
Bestimmung des Inhalts
if($a['nodeValues']!==FALSE)
{
# Bestimmung Welche Art Inhalt vorliegt
if(is_array($a['nodeValues']))
{
$element.='>';
# Aufbau der Kindelemente
foreach($a['nodeValues'] as $v)
{
# Rekursion auf die Kindelemente
$element.=mach_xml($v,array($b[0]."\t",FALSE));
}
$element.=$br.$b[0].'</'.$a['nodeName'].'>';
}
else
{
# Kindelement ist ein Textnode
$element.='>'.$a['nodeValues'];
$element.=$br.$b[0].'</'.$a['nodeName'].'>';
}
}
else
{
# Element ist leer
$element.=$S.'/>';
}
return($element);
#unset($element,$k,$v);
}
Das Datenfeld muß anders aufgebeut werden!
$a=array(
'nodeName' =>'music',
'nodeAttr' =>array(
'id' =>199,
'name' =>'FirstName'),
'nodeValues' =>array(
array(
'nodeName' =>'album',
'nodeAttr' =>array(
'albumid' =>'1234',
'albumname' =>'The King'),
'nodeValues' =>array(
array(
'nodeName' =>'tracks',
'nodeAttr' =>array(
'albumid'=>'1234'),
'nodeValues' =>array(
array(
'nodeName' =>'track',
'nodeAttr' =>array('albumid'=>'1234'),
'nodeValues' =>false),
array(
'nodeName' =>'information',
'nodeAttr' =>array('albumid'=>'1234'),
'nodeValues'=>false),
),
)
)
)
)
);
echo mach_xml($a);
?>
Gruß aus Berlin!
eddi
hallo florian
Hallo eddi
vielen dank für deine mühe!
ja, ich habe absichtlich children und nodeValues von einander getrennt da ich anfänglich die übersicht verlohren habe!
auf der anderen seite hatte ich es mit der prüfung der eingehenden daten leichter: values sind immer "string" oder "empty" und children sind immer "array" oder "empty"
ich arbeite deine funktion mal ab/aus und melde mich definitiv noch mal!
Gruß aus Berlin!
eddi
gruß florian
-:: flobee :: -´
-.
Hallo eddi
leichter: values sind immer "string" oder "empty" und children sind immer "array" oder "empty"
da habe ich sogar quatsch geschrieben! es sind immer arrays oder empty
getrennt habe ich es da sie ja anders aufgebaut werden! vielleicht ist ´mein einleitendes array auch falsch!?
-----------------------
.-´-:: flobee :: -´
-.
eddi
hallo eddi!
deine funktion geht nicht so ganz!
ziel ausgabe soll werden: ("root" gab es bei mir schon. mein array in der vorgabe war falsch! ich muss natürlich mit einem "root" beginnen.):
<?xml version="1.0" ?>
<root>
<music id="199" name="FirstName">
<album albumid="1234" albumname="The King">
<tracks albumid="1234">
<track albumid="1234">VALUE1</track>
<track albumid="1234">VALUE2</track>
</tracks>
<information albumid="1234">
<artist ... >Artist (fehlt in meinem array auch!!!</artist>
<autor ... ></autor>
<lenght ... ></lenght>
</information>
</album>
</music>
</root>
mit deinem array kommt folgendes raus (wobei du ein paar values vergessen hast):
<?xml version="1.0" ?>
<music id="199" name="FirstName">
<album albumid="1234" albumname="The King">
<tracks albumid="1234">
<track albumid="1234" />
<information albumid="1234" />
</tracks>
</album>
</music>
fügst du jetzt die fehlen daten hinzu wird es "wild" und ich glaube es ist die stelle wo die recursion ggf probleme bekommen wird und weshalb ich in meinem daten array 'children' eingeführt habe:
<tracks albumid="1234">
<t>t
</t>
<>
</>
<>
</>
</tracks>
gruß florian
-:: flobee :: -´
-.
hallo Florian!
Für mich persönlich wäre es einfacher Kindknoten/Strings/Empty als Value anzunehmen, aber das steht Dir natürlich frei. Habe nochmal ein wenig rumgemurchst und nun scheint mach_xml() aus einem anderen Datenfeld folgendes zu machen:
<?xml version="1.0" ?>
<root>
<music id="199" name="FirstName">
<album albumid="1234" albumname="The King">
<tracks albumid="1234">
<track albumid="1234">VALUE1</track>
<track albumid="1234">VALUE2</track>
</tracks>
<information albumid="1234">
<artist attr="0">Artist (fehlt in meinem array auch!!!</artist>
<author attr="0">Artist (fehlt in meinem array auch!!!</author>
<lenght attr="0">Läge würde ich als Attribut vergeben</lenght>
</information>
</album>
</music>
</root>
<?php
function mach_xml($a,$b=array('',TRUE))
{
# Definition von benötigkten Variablen
$br="\n";
$S =' ';
# Aufbau des Elements
$element= $b[1] ? '<?xml version="1.0" ?>' : '';
$element.=$br.$b[0].'<'.$a['nodeName'];
# Aufbau der Attribute
if(is_array($a['nodeAttr']))
{
foreach($a['nodeAttr'] as $k=>$v)
{
$element.=$S.$k.'="'.$v.'"';
}
}
# Bestimmung des Inhalts
if($a['nodeValues']!==FALSE)
{
# Bestimmung Welche Art Inhalt vorliegt
if(is_array($a['nodeValues']))
{
$element.='>';
# Aufbau der Kindelemente
foreach($a['nodeValues'] as $v)
{
# Rekursion auf die Kindelemente
$element.=mach_xml($v,array($b[0]."\t",FALSE));
}
$element.=$br.$b[0].'</'.$a['nodeName'].'>';
}
else
{
# Kindelement ist ein Textnode
$element.='>'.$a['nodeValues'];
$element.='</'.$a['nodeName'].'>';
}
}
else
{
# Element ist leer
$element.=$S.'/>';
}
return($element);
#unset($element,$k,$v);
}
$a=array(
'nodeName' =>'root',
'nodeValues' =>array(
array(
'nodeName' =>'music',
'nodeAttr' =>array(
'id' =>199,
'name' =>'FirstName'),
'nodeValues' =>array(
array(
'nodeName' =>'album',
'nodeAttr' =>array(
'albumid' =>'1234',
'albumname' =>'The King'),
'nodeValues' =>array(
array(
'nodeName' =>'tracks',
'nodeAttr' =>array(
'albumid'=>'1234'),
'nodeValues' =>array(
array(
'nodeName' =>'track',
'nodeAttr' =>array('albumid'=>'1234'),
'nodeValues' =>'VALUE1'),
array(
'nodeName' =>'track',
'nodeAttr' =>array('albumid'=>'1234'),
'nodeValues' =>'VALUE2')
)
),
array(
'nodeName' =>'information',
'nodeAttr' =>array(
'albumid'=>'1234'),
'nodeValues'=>array(
array(
'nodeName' =>'artist',
'nodeAttr' =>array(
'attr'=>0),
'nodeValues'=>'Artist (fehlt in meinem array auch!!!'),
array(
'nodeName' =>'author',
'nodeAttr' =>array(
'attr'=>0),
'nodeValues'=>'Artist (fehlt in meinem array auch!!!'),
array(
'nodeName' =>'lenght',
'nodeAttr' =>array(
'attr'=>0),
'nodeValues'=>'Länge würde ich als Attribut vergeben')
)
)
)
)
)
)
)
);
echo mach_xml($a);
?>
Gruß aus Berlin!
eddi
hallo Florian!
hallo!
bei deiner rekursion ist manchmal $v kein array
sehe (ungetestet) das gleiche problem!
was ist bei der funktion jetzt anders?
gruß flobee
Re:
bei deiner rekursion ist manchmal $v kein array
Das beruht darauf, daß ich das Datenfeld gänzlich anders aufgebaut habe. Ich habe es Dir angehangen, damit Du Dir die Veränderungen zu Deinem Datenfeld verdeutlichen kannst. Letztendlich basiert auch die Funktionsweise auf der veränderten Struktur des Datenfeldes.
Es gibt also zwei Möglichkeiten: Entweder Du schreibst Dir die Funktion um, daß sie Dein Datenfeld parst, oder Du folgst meinem Beispiel und veränderst den Aufbau des Datenfelds. Vielleicht kann man Dir eingehender helfen, wenn Du en Steuerfluß zum erstellen des Datenfeldes postest, oder erklärst, welche Passagen Dir bei der Umstellung auf Deine Struktur in mach_xml() probeme bereiten.
Gruß aus Berlin!
eddi
Vielleicht kann man Dir eingehender helfen, wenn Du en Steuerfluß zum erstellen des Datenfeldes postest, oder erklärst, welche Passagen Dir bei der Umstellung auf Deine Struktur in mach_xml() probeme bereiten.
hallo,
Steuerfluß zum erstellen des Datenfeldes
wie ich das array erzeuge?:
das ist ausgedacht!
so wie ich es mir am besten vorstellen könnte um überhaupt eine lösung zu finden!
Ich habe so einige scripte gefunden, aber die machen das entweder nur in 2D oder können keine extras wie attribute o.ä.
Letzt endlich kommen die Daten aus einer Datenbank. In der regel als assoziatives array
ich habe meine klasse gerade fertig aber das ist noch nicht komfortable genug und ggf nicht 100% sauber.
insbesondere finde ich die datenstruktur zu "komplex"/"fett", viel speicher für nix :-) also nicht wirklich zufrieden.
hier habe ich das script mal hin gestellt:
http://www.cgix.de/dev/php/class.ArrayToXml.phps
vielleicht hast du ja eine idee wie man das leichter lösen könnte!?
gruß florian
-:: flobee :: -´
-.