PHP & XML

creep3007

Mitglied
XML Bearbeitungsproblem mir PHP

Hallo zusammen,
sitze seit einigen Tagen daran, XML Dateien mittels PHP zu öffnen, bearbeiten, und wieder abzuspeichern.

Naja, was soll ich sagen es funktioniert nicht wirklich wie erhofft, aber wahrscheinlich stehe ich nur mal wieder mit meinen "Quatradlatschen" auf dem Schlauch.

Vorne weg, ja ich kenne Google und Gidf und die Suchfunktion im Forum :), sonst würd ich nicht fragen :D.
Und ja habe vieles zu dem Thema gefunden, nur die Beispiele brachten nie das erhoffte Resultat.

So, ich suche ein Beispiel, dass mir bei meinem Problem weiterhilft.

Ich möchte in folgender XML Datei einen bestimmten Wert ändern, aber die Eltern und Kinder genauso belassen wie sie im Moment sind.

HTML:
<?xml version="1.0"?>
<system>
    <item preis="3.99">
        <name>Gurke</name>
        <art>Gemüse</art>
        <beschreibung>Kann man Essen!</beschreibung>
    </item>
    <item preis="4.99">
        <name>Tomate</name>
        <art>Frucht</art>
        <beschreibung>Kann man auch Essen!</beschreibung>
    </item>
    <item preis="5.99">
        <name>Melone</name>
        <art>Gemüse</art>
        <beschreibung>Kann man bestimmt auch Essen!</beschreibung>
    </item>
</system>

Beispiel: Ich suche das Item mit dem Preis 4.99 --
Code:
XPath: //item[@preis="4.99"]
-- dort möchte ich nun die <art /> ändern, weil bekanntlich sind Tomaten keine Früchte.
--->Bitte nicht kommentieren<---

Wie könnte ich dies bewerkstelligen, ohne einen vollständigen Block zu ersetzen?
Natürlich sollte die XML Datei gespeichert werden, da sie im späteren Verlauf via Schnittstelle weitergeleitet wird.

Bin für alle Ansätze und Vorschläge sehr dankbar!

Vielen Dank!
Alexander
 
Zuletzt bearbeitet:
Aw: Php & xml

Hi,

eigentlich sollte es mittels SimpleXML recht einfach sein:

PHP:
$sxml = new SimpleXMLElement(file_get_contents('test1.xml'));

$item = $sxml->xpath('//item[@preis="4.99"]');

$item[0]->art = 'Gemüse';

$sxml->asXML('test2.xml');
 
Aw: Php & xml

Öhm, Danke! ...

Also ehrlich, habe das dem SimpleXML Object sooft ausprobiert aber es kam nieee! wirklich nie dieses Resultat raus.
Habe es auch mit DOM (eine schwäche von mir, ... leider) probiert aber das funktionierte auch nie wirklich.
Warum funktioniert das jetzt ? :D

Danke !

LG, Alexander
 
Aw: Php & xml

Vermutlich wegen dieser Zeile:

$item[0]->art = 'Gemüse';

Ich war auch zuerst in der Versuchung, es so zu machen:

$item->art = 'Gemüse';

was eine Fehlermeldung (Attempt to assign property of non-object) sowie der var_dump von $item zeigte, nicht korrekt ist. $item ist nach der XPath-Suche offensichtlich ein Array von Elementen, auch wenn nur ein Eintrag gefunden wurde. Prinzipiell ist das sogar logisch.
 
Aw: Php & xml

Achsooo, stimmt ...

Ist doch auch klar, ich suche ja nur nach dem <item preis="4.99" /> darunter verbergen sich doch [0]=>'name', [1]=>'art', [2]=>'beschreibung';


Nun ist die Frage, ob ich direkt mit
Code:
 XPath ////item[@preis="4.99"]/art
auf den nodeText zugreifen kann ...
 
Aw: Php & xml

Ähm, nein, so ganz ist das nicht gemeint. Die Elemente Name, Art, Beschreibung sind effektiv Eigenschaften eines Objekts und _nicht_ Elemente eines Arrays.

Was ich meinte ist:

- Ich starte eine Suche in einer Menge (XPath ist die Suche)
- In der Menge gibt es genau ein Element, das den Eigenschaften meiner Suche entspricht
- XPath gibt aber trotzdem nicht dieses eine Element zurück sondern eine Liste (Array), das nur einen Eintrag enthält. Dieser Eintrag hat den Listen(Array)-Index 0. Eigentlich wäre folgender Code richtiger:

PHP:
$sxml = new SimpleXMLElement(file_get_contents('test1.xml'));
 
// Referenzen auf Suchergebnisse (egal, wie viele) werden in $itemListe abgelegt
$itemListe = $sxml->xpath('//item[@preis="4.99"]'); // Hier könnten rein theoretisch auch 
// mehrere Elemente zurück geliefert werden, nämlich dann, wenn dein XML mehr also nur ein Element "item" enthält, was einen Preis von 4.99 hat

// Jetzt holen wir uns eine Referenz auf das erste Element in der Ergebnisliste aus der XPath-Suche
$item = $itemListe[0]; 
// und stellen die Item-Art um
$item->art = 'Gemüse';

// Nun noch Speichern
$sxml->asXML('test2.xml');
 
Aw: Php & xml

Ah okay,

HTML:
     <itemlist preis="4.99">
        <item>
            <name>Gurke</name>
            <art>Gemuese</art>
            <beschreibung>Kann man Essen!</beschreibung>
        </item>
        <item>
            <name>Tomate</name>
            <art>Tomate</art>
            <beschreibung>Kann man auch Essen!</beschreibung>
        </item>
        <item>
            <name>Melone</name>
            <art>Gemuese</art>
            <beschreibung>Kann man bestimmt auch Essen</beschreibung>
        </item>
    </itemlist>

Hier hätte ich jetzt eine Itemliste mit 3 Items, die alle den Preis 4.99 haben.

Suche ich nun mit--

Code:
XPath //itemlist[@preis="4.99"]

-- und lasse mir alles ausgeben --

PHP:
$itemliste = $sxml->xpath('//itemlist[@preis="4.99"]');
print_r($itemliste);

Code:
 Array
(
    [0] => SimpleXMLElement Object
        (
            [@attributes] => Array
                (
                    [preis] => 4.99
                )
 
            [item] => Array
                (
                    [0] => SimpleXMLElement Object
                        (
                            [name] => Gurke
                            [art] => Gemuese
                            [beschreibung] => Kann man Essen!
                        )
 
                    [1] => SimpleXMLElement Object
                        (
                            [name] => Tomate
                            [art] => Tomate
                            [beschreibung] => Kann man auch Essen!
                        )
 
                    [2] => SimpleXMLElement Object
                        (
                            [name] => Melone
                            [art] => Gemuese
                            [beschreibung] => Kann man bestimmt auch Essen
                        )
 
                )
 
        )
 
)

-- ist es auch klarer und verständlicher.

PHP:
        $file = './xml_folder/test.xml'
        
        //XML Laden ...
        $sxml = new SimpleXMLElement(file_get_contents($file));
        
        //<itemliste> suchen mit Attribut = PREIS= 4.99
        $itemliste = $sxml->xpath('//itemlist[@preis="4.99"]');
        #print_r($itemlist);
        
        //s.u. *
        $item = $itemlist[0]->item[1];
        
        //Item -> Art in Gemuese umstellen
        $item->art = "Gemuese"; 
        #print_r($item);
        
        // XML Speichern ...
        $sxml->asXML($file);

*
Code:
$itemlist[0] ==  
Array
(
    [0] => SimpleXMLElement Object

->item[0-2] ==
            [item] => Array
                (
                    [0] => SimpleXMLElement Object
                        (
                            [name] => Gurke
                            [art] => Gemuese
                            [beschreibung] => Kann man Essen!
                        )
 
                    [1] => SimpleXMLElement Object
                        (
                            [name] => Tomate
                            [art] => Tomate
                            [beschreibung] => Kann man auch Essen!
                        )
 
                    [2] => SimpleXMLElement Object
                        (
                            [name] => Melone
                            [art] => Gemuese
                            [beschreibung] => Kann man bestimmt auch Essen
                        )
 
                )

Habe es verstanden, vielleicht nicht sooo toll erklärt, wie du, aber verstanden :D, das ist die hauptsache (für mich).

Saftmeister, danke, das hat mir sehr!! geholfen.

*Danke*

So, nun wende ich mein neu gewonnenes Wissen auf mein "Monster" XML an und melde mich spätestens beim nächsten Problem wieder.

Vielen Dank!

Alexander

PS: Wenn man es verstanden hat, ist relativ einfach :D
 
Zuletzt bearbeitet:
...
Habe es auch mit DOM (eine schwäche von mir, ... leider) probiert aber ...
Hallo,

hier mal noch dazu eine Beispiellösung:
PHP:
$domxml = new DOMDocument();
$domxml->load('obst-und-gemuese.xml');

$domxpath = new DOMXPath($domxml);
$xpathquery = '//item[@preis="4.99"]';

$domItemsPreis499 = $domxpath->query($xpathquery);  /* DomNodeList */
$firstItemPreis499 = $domItemsPreis499->item(0);    /* DomNode */

$firstItemPreis499->getElementsByTagName('art')->item(0)->nodeValue = "keine Frucht";

$domxml->save('obst-und-gemuese-neu.xml');
Witzig ist, dass hier der Elementindex mit "item" und runder Klammer angegeben wird.
 
Aw: Php & xml

Hey hela,
vielen Dank!
Ja, werde und muss mir die DOM in den nächsten Tagen / Wochen genauer anschauen.

versteh ich das Richtig:?
Ich gehe jetzt von meiner, im Eingangspost erwähnten, XML aus:

Damit greife ich auf mein erstes gefundenes Element zu --
PHP:
$firstItemPreis499 = $domItemsPreis499->item(0);

-- hole mir <art /> raus --
PHP:
$firstItemPreis499->getElementsByTagName('art')

und ändere diese.
PHP:
->item(0)->nodeValue = "keine Frucht; biologisch gesehen schon, nur im EH ein Gemuese!";
 
Ja genau. Die Verfahrensweise ist eigentlich die gleiche, wie sie saftmeister für simpleXML wirklich gut beschrieben hat: KnotenListe -> Knoten -> machIrgendwas.
 
Zurück