Permalänk
Medlem

XML problem i PHP

Hejsan,

efter att ha googlat och försökt förstå documentation så vänder jag mig tillslut till er.

Ska försöka göra en liten mini-chat där man kan skriva kommentarer på ett filmklipp, och allt ska sparas i en XML fil.
Jag har då lagt kommentarerna under det "game" som kommentarerna tillhör, vill gärna ha det i en fil.

Problemet är att jag inte riktigt vet hur jag ska lägga till ett nytt meddelande i filen, hade det varit under root vore det
inget problem, men när jag ska längre ner i XML-trädet så vet jag inte riktigt hur jag ska gå tillväga.

Har försökt med att gå ner igenom trädet med diverse "foreach()" loopar men får det inte att funka. Sedan så hittade jag en kod
från http://quest4knowledge.wordpress.com/2010/09/04/php-xml-creat....

Som jag sedan anpassade och fick det till detta:

function addMessage($message,$by,$id){ $dom = new DOMDocument(); $dataFilePath = 'xml/games.xml'; $dom->load($dataFilePath); $game = $dom->documentElement; $newMess = $dom->createElement('message',$message); $newMess->setAttribute('by',$by); $newMess->setAttribute('date',date("Y-m-d H:i:s")); $xpath = new DOMXPATH($dom); $result = $xpath->query('/games/game[@id="'.$id.'"/messages/message'); $game->childNodes->item(0)->parentNode->insertBefore($newMess,$result->item(0)); header("Content-type: text/xml"); echo $dom->saveXML(); }

Dold text

XML:

<?xml version='1.0' encoding='utf-8'?> <games> <game name="LV - GT" date="2012-10-07" result="6-1" id='1' path="upload/games/gt.zip" loc='Borta'> <messages> <message by='1' message='sup ppl'/> <message by='2' message='nothing, you then?'/> <message by='3' message='wazzup ppl'/> </messages> </game> <game name="LV - Mälarö" date="2012-10-12" result="3-6" id='2' path="upload/games/lvmal.zip" loc='Hemma'> <messages> <message by='1' message='test'/> <message by='2' message='test2'/> <message by='3' message='3333'/> </messages> </game> </games>

Dold text

Får följande error:
Warning: DOMXPath::query(): Invalid predicate in /customers/d/4/0/jakke.se/httpd.www/lvhc/php/gameChat.php on line 13 Warning: DOMXPath::query(): Invalid expression in /customers/d/4/0/jakke.se/httpd.www/lvhc/php/gameChat.php on line 13 Fatal error: Call to a member function item() on a non-object in /customers/d/4/0/jakke.se/httpd.www/lvhc/php/gameChat.php on line 14

Tack på förhand!
Mvh

Visa signatur

Citera för svar

Permalänk
Legendarisk

$result = $xpath->query('/games/game[@id="'.$id.'"/messages/message');

XPath är helt rätt metod för att navigera XML, att loopa igenom det nod för nod blir snabbt fullständigt ohanterligt. Felmeddelandet beror på att ditt predikat saknar avslutande klammer: game[@id="foo"]. Sedan vill du hitta listan av meddelanden som hör till spelet, och då blir frågan: /games/game[@id="foo"]/messages. När du väl har den, förutsatt att den alltid existerar, är det då bara att skapa ett nytt meddelande under denna.

<message by='1' message='test'/>

Meddelandets innehåll bör antagligen inte vara ett attribut, utan istället vara elementets innehåll. Se länken nedan för bra läsning:

Principles of XML design: When to use elements versus attributes

Skickades från m.sweclockers.com

Visa signatur

Abstractions all the way down.

Permalänk
Medlem
Skrivet av Tunnelsork:

$result = $xpath->query('/games/game[@id="'.$id.'"/messages/message');

XPath är helt rätt metod för att navigera XML, att loopa igenom det nod för nod blir snabbt fullständigt ohanterligt. Felmeddelandet beror på att ditt predikat saknar avslutande klammer: game[@id="foo"]. Sedan vill du hitta listan av meddelanden som hör till spelet, och då blir frågan: /games/game[@id="foo"]/messages. När du väl har den, förutsatt att den alltid existerar, är det då bara att skapa ett nytt meddelande under denna.

<message by='1' message='test'/>

Meddelandets innehåll bör antagligen inte vara ett attribut, utan istället vara elementets innehåll. Se länken nedan för bra läsning:

Principles of XML design: When to use elements versus attributes

Skickades från m.sweclockers.com

Tack för svar.

Ja meddelandet kommer läggas in som element med 'by' och 'date' som attribut, ser bara inte ut så nu.
Bra länk, tack.

Jag fixade till den, klantigt av mig hehe, men då får jag det error som jag egentligen kom hit för:

Fatal error: Uncaught exception 'DOMException' with message 'Hierarchy Request Error' in /customers/d/4/0/jakke.se/httpd.www/lvhc/php/gameChat.php:14 Stack trace: #0 /customers/d/4/0/jakke.se/httpd.www/lvhc/php/gameChat.php(14): DOMNode->insertBefore(Object(DOMElement), Object(DOMElement)) #1 /customers/d/4/0/jakke.se/httpd.www/lvhc/pages/viewgame.php(51): addMessage('test', 'Jakkes', '2') #2 /customers/d/4/0/jakke.se/httpd.www/lvhc/index.php(95): include_once('/customers/d/4/...') #3 {main} thrown in /customers/d/4/0/jakke.se/httpd.www/lvhc/php/gameChat.php on line 14.

Dold text

Jag misstänker att det har med "$game->childNodes->item(0)->parentNode->" att göra, att den pekar fel.
Testade att köra "$game->insertBefore" direkt men det gav samma error.

KOD:

function addMessage($message,$by,$id){ $dom = new DOMDocument(); $dataFilePath = 'xml/games.xml'; $dom->load($dataFilePath); $game = $dom->documentElement; $newMess = $dom->createElement('message',$message); $newMess->setAttribute('by',$by); $newMess->setAttribute('date',date("Y-m-d H:i:s")); $xpath = new DOMXPATH($dom); $result = $xpath->query('/games/game[@id="'.$id.'"]/messages'); $game->childNodes->item(0)->parentNode->insertBefore($newMess,$result->item(0)); header("Content-type: text/xml"); echo $dom->saveXML(); }

Dold text

XML:

<?xml version='1.0' encoding='utf-8'?> <games> <game name="LV - GT" date="2012-10-07" result="6-1" id='1' path="upload/games/gt.zip" loc='Borta'> <messages> <message by='1' message='sup ppl'/> <message by='2' message='nothing, you then?'/> <message by='3' message='wazzup ppl'/> </messages> </game> <game name="LV - Mälarö" date="2012-10-12" result="3-6" id='2' path="upload/games/lvmal.zip" loc='Hemma'> <messages> <message by='1' message='test'/> <message by='2' message='test2'/> <message by='3' message='3333'/> </messages> </game> </games>

Dold text

Tack
Mvh

Visa signatur

Citera för svar

Permalänk
Legendarisk

Det stämmer att $game->childNodes->item(0)->parentNode pekar till fel element. Det där kommer bara dig föräldern till en nods första undernod, och det är ju samma nod som du började med. $game->childNodes->item(0)->parentNode === $game. Dessutom innehåller $game din rootnod. Du försöker alltså infoga ett nytt element under rooten, men som syskon till en nod som inte är det. Därav felmeddelandet "Hierarchy Request Error".

Istället för att leta dig ner från rooten bör du använda dig av resultatet från sökfrågan, som ju innehåller din nya förälder (<messages>), och appenda det nya meddelandet direkt till den.

<?php $xml = <<<'EOT' <?xml version='1.0' encoding='utf-8'?> <games> <game name="LV - GT" date="2012-10-07" result="6-1" id='1' path="upload/games/gt.zip" loc='Borta'> <messages> <message by='1' message='sup ppl'/> <message by='2' message='nothing, you then?'/> <message by='3' message='wazzup ppl'/> </messages> </game> <game name="LV - Mälarö" date="2012-10-12" result="3-6" id='2' path="upload/games/lvmal.zip" loc='Hemma'> <messages> <message by='1' message='test'/> <message by='2' message='test2'/> <message by='3' message='3333'/> </messages> </game> </games> EOT; $dom = new DOMDocument(); $dom->loadXML($xml); $newMess = $dom->createElement('message', "hej"); $newMess->setAttribute('by', "me"); $newMess->setAttribute('date',date("Y-m-d H:i:s")); $xpath = new DOMXPath($dom); $result = $xpath->query('/games/game[@id="1"]/messages'); $parent = $result->item(0); $parent->appendChild($newMess); header("Content-type: text/xml"); echo $dom->saveXML();

Dold text

Skickades från m.sweclockers.com

Visa signatur

Abstractions all the way down.

Permalänk
Medlem
Skrivet av Tunnelsork:

Det stämmer att $game->childNodes->item(0)->parentNode pekar till fel element. Det där kommer bara dig föräldern till en nods första undernod, och det är ju samma nod som du började med. $game->childNodes->item(0)->parentNode === $game. Dessutom innehåller $game din rootnod. Du försöker alltså infoga ett nytt element under rooten, men som syskon till en nod som inte är det. Därav felmeddelandet "Hierarchy Request Error".

Istället för att leta dig ner från rooten bör du använda dig av resultatet från sökfrågan, som ju innehåller din nya förälder (<messages>), och appenda det nya meddelandet direkt till den.

<?php $xml = <<<'EOT' <?xml version='1.0' encoding='utf-8'?> <games> <game name="LV - GT" date="2012-10-07" result="6-1" id='1' path="upload/games/gt.zip" loc='Borta'> <messages> <message by='1' message='sup ppl'/> <message by='2' message='nothing, you then?'/> <message by='3' message='wazzup ppl'/> </messages> </game> <game name="LV - Mälarö" date="2012-10-12" result="3-6" id='2' path="upload/games/lvmal.zip" loc='Hemma'> <messages> <message by='1' message='test'/> <message by='2' message='test2'/> <message by='3' message='3333'/> </messages> </game> </games> EOT; $dom = new DOMDocument(); $dom->loadXML($xml); $newMess = $dom->createElement('message', "hej"); $newMess->setAttribute('by', "me"); $newMess->setAttribute('date',date("Y-m-d H:i:s")); $xpath = new DOMXPath($dom); $result = $xpath->query('/games/game[@id="1"]/messages'); $parent = $result->item(0); $parent->appendChild($newMess); header("Content-type: text/xml"); echo $dom->saveXML();

Dold text

Skickades från m.sweclockers.com

Tack så hemskt mycket för hjälpen, nu funkar allt bra.

Var tvungen att ta bort header("Content-type"); annars fick error.
Sedan så ändrade jag även "$dom->saveXML();" till "$dom->save($dataFilePath);".

Mvh

Visa signatur

Citera för svar