[PHP/XML] SimpleXML childeren uitlezen en in DB stoppen *

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • maxtz0r
  • Registratie: Februari 2007
  • Laatst online: 17-12-2022
Beste,

Ik heb een XML bestand die er als volgt uitziet:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<pinnacle_line_feed>
    <PinnacleFeedTime>1296555078546</PinnacleFeedTime>
    <lastContest>5615732</lastContest>
    <lastGame>63477998</lastGame>
<events>
<event>
    <event_datetimeGMT>2011-02-02 18:00</event_datetimeGMT>
    <gamenumber>192888718</gamenumber>
    <sporttype>Bandy</sporttype>
    <league>Sweden Elits</league>
    <IsLive>No</IsLive>
    <participants>
        <participant>
            <participant_name>Tillberga</participant_name>
            <contestantnum>1251</contestantnum>
            <rotnum>1251</rotnum>
            <visiting_home_draw>Home</visiting_home_draw>
        </participant>
        <participant>
            <participant_name>IFK Kungälv</participant_name>
            <contestantnum>1252</contestantnum>
            <rotnum>1252</rotnum>
            <visiting_home_draw>Visiting</visiting_home_draw>
        </participant>
    </participants>
    <periods>
        <period>
            <period_number>0</period_number>
            <period_description>Game</period_description>
            <periodcutoff_datetimeGMT>2011-02-02 18:00</periodcutoff_datetimeGMT>
            <period_status>I</period_status>
            <period_update>open</period_update>
            <spread_maximum>250</spread_maximum>
            <moneyline_maximum>250</moneyline_maximum>
            <total_maximum>250</total_maximum>
            <moneyline>
                <moneyline_visiting>123</moneyline_visiting>
                <moneyline_home>-136</moneyline_home>
            </moneyline>
            <spread>
                <spread_visiting>1.5</spread_visiting>
                <spread_adjust_visiting>-198</spread_adjust_visiting>
                <spread_home>-1.5</spread_home>
                <spread_adjust_home>178</spread_adjust_home>
            </spread>
            <total>
                <total_points>8.5</total_points>
                <over_adjust>102</over_adjust>
                <under_adjust>-113</under_adjust>
            </total>
        </period>
    </periods>
</event>
</events>
</pinnacle_line_feed>


Wat ik nu wil doen is per event alle gegevens eruit halen en deze in een database stoppen. Ik vraag mij alleen af wat handig is om nu te doen. Zojuist heb ik geprobeerd met een foreach loopje er door heen te gaan maar omdat er zoveel niveaus zijn krijg ik veel loopjes in een loop.
Waar ik nu aan zit te denken is om voor elk stukje informatie wat ik wil hebben een functie te schrijven die door middel van xpath(zodat ik op de juiste niveau zit) informatie uit de xml haalt. Ik zou dan in 1 for each loopje deze functies kunnen aanroepen om vervolgens de gegevens in een variable te stoppen en vervolgens in de database te stoppen.

Omdat dit mijn eerste keer is dat ik met php/xml/simplexml werk en geen ervaren programmeur ben vroeg ik mij af of mijn gedachtegang goed is. Vooral omdat ik een beginnende programmeur ben en dus ongeveer 3-4 uur duurt voordat ik erachter kom dat dit wellicht niet de manier is om het te doen.

Dying is God's way of telling you, you've been FIRED.


Acties:
  • 0 Henk 'm!

  • dev10
  • Registratie: April 2005
  • Laatst online: 09-09 15:21
Hoe ziet je datamodel er precies uit? Ik hoop dat je netjes genormaliseerd hebt en dus een tabel hebt met events, participants en periods. De participants en periods tabel hebben dan een foreign key die verwijst naar de tabel met events.

Ik denk dat je het beste gebruik kunt maken van SimpleXML en door middel van een foreach loop de data in de database kunt stoppen.

Dus iets als dit:

PHP:
1
2
3
4
5
$xmlFile = new SimpleXML(file_get_contents('file.xml'));

foreach($xmlFile->events as $event) {
  // Insert data in database
}

[ Voor 18% gewijzigd door dev10 op 01-02-2011 14:02 ]


Acties:
  • 0 Henk 'm!

  • maxtz0r
  • Registratie: Februari 2007
  • Laatst online: 17-12-2022
dev10 schreef op dinsdag 01 februari 2011 @ 13:59:
Hoe ziet je datamodel er precies uit? Ik hoop dat je netjes genormaliseerd hebt en dus een tabel hebt met events, participants en periods. De participants en periods tabel hebben dan een foreign key die verwijst naar de tabel met events.

Ik denk dat je het beste gebruik kunt maken van SimpleXML en door middel van een foreach loop de data in de database kunt stoppen.

Dus iets als dit:

PHP:
1
2
3
4
5
$xmlFile = new SimpleXML(file_get_contents('file.xml'));

foreach($xmlFile->events as $event) {
  // Insert data in database
}
Dat had ik inderdaad al gedaan maar stom van me dat ik vergat dat ik de array nu gewoon kan uitlezen. Ik ga even zoeken hoe ik de array nu op een juiste manier kan uitlezen want dat ziet er nu nogal uit als een chaos.

Dying is God's way of telling you, you've been FIRED.


Acties:
  • 0 Henk 'm!

  • maxtz0r
  • Registratie: Februari 2007
  • Laatst online: 17-12-2022
Ik zou nu toch door middel van het volgende stukje code de gamenumber moeten kunnen vinden?
PHP:
1
2
3
4
5
6
7
8
9
<?php
$xml = simplexml_load_file("pinnacleFeed.xml");

foreach($xml->events as $event)
{
    //print_r($event);
    echo $event->gamenumber. "<br />";
} 
?>

Dying is God's way of telling you, you've been FIRED.


Acties:
  • 0 Henk 'm!

  • WouZz
  • Registratie: Mei 2000
  • Niet online

WouZz

Elvis is alive!

Ik zou dit proberen (uit mn hoofd):
PHP:
1
2
3
4
5
6
7
$xml = simplexml_load_file("pinnacleFeed.xml"); 

foreach($xml->events[0]->event as $event) 
{ 
    //print_r($event); 
    echo (string) $event->gamenumber[0]. "<br />"; 
}

On track


Acties:
  • 0 Henk 'm!

  • Manuel
  • Registratie: Maart 2008
  • Laatst online: 17:22
maxtz0r schreef op dinsdag 01 februari 2011 @ 14:47:
Ik zou nu toch door middel van het volgende stukje code de gamenumber moeten kunnen vinden?
PHP:
1
2
3
4
5
6
7
8
9
<?php
$xml = simplexml_load_file("pinnacleFeed.xml");

foreach($xml->events as $event)
{
    //print_r($event);
    echo $event->gamenumber. "<br />";
} 
?>
Waarom probeer je het niet eerst en als je er dan niet uitkomt dat je het hier meldt zodat wij eventueel opmerkingen / hints / tips kunnen geven. Nu vraag je (in mijn ogen) of wij eerst dat stukje code kunnen testen voordat jij het daadwerkelijk wilt proberen.

Het is trouwens standaard dat $event (in jouw voorbeeld) een SimpleXMLElement object teruggeeft die je dan zelf moet casten naar string, int, float, double, ...... :)

Zie ook WouZz zijn code.
dev10 schreef op dinsdag 01 februari 2011 @ 13:59:
Hoe ziet je datamodel er precies uit? Ik hoop dat je netjes genormaliseerd hebt en dus een tabel hebt met events, participants en periods. De participants en periods tabel hebben dan een foreign key die verwijst naar de tabel met events.
Tabellen zijn in dit geval nog niet eens aan de orde. De TS moet eerst de data uit het XML bestand zien te halen, daarna komen tabellen pas aan de orde. Jij loopt in dit geval een aantal stappen voor. :)

PS: Dit valt ook prima te doen zonder foreign keys.

[ Voor 26% gewijzigd door Manuel op 01-02-2011 16:23 ]


Acties:
  • 0 Henk 'm!

  • maxtz0r
  • Registratie: Februari 2007
  • Laatst online: 17-12-2022
WouZz schreef op dinsdag 01 februari 2011 @ 16:12:
Ik zou dit proberen (uit mn hoofd):
PHP:
1
2
3
4
5
6
7
$xml = simplexml_load_file("pinnacleFeed.xml"); 

foreach($xml->events[0]->event as $event) 
{ 
    //print_r($event); 
    echo (string) $event->gamenumber[0]. "<br />"; 
}
Thnx dat blijkt inderdaad te werken, nou had ik het (string) gedeelte zelf ook gevonden maar zou iemand mij kunnen uitleggen waar die [0] precies voor dient?

Dying is God's way of telling you, you've been FIRED.


Acties:
  • 0 Henk 'm!

  • maxtz0r
  • Registratie: Februari 2007
  • Laatst online: 17-12-2022
Manuel schreef op dinsdag 01 februari 2011 @ 16:18:
[...]

Waarom probeer je het niet eerst en als je er dan niet uitkomt dat je het hier meldt zodat wij eventueel opmerkingen / hints / tips kunnen geven. Nu vraag je (in mijn ogen) of wij eerst dat stukje code kunnen testen voordat jij het daadwerkelijk wilt proberen.

Het is trouwens standaard dat $event (in jouw voorbeeld) een SimpleXMLElement object teruggeeft die je dan zelf moet casten naar string, int, float, double, ...... :)

Zie ook WouZz zijn code.


[...]

Tabellen zijn in dit geval nog niet eens aan de orde. De TS moet eerst de data uit het XML bestand zien te halen, daarna komen tabellen pas aan de orde. Jij loopt in dit geval een aantal stappen voor. :)

PS: Dit valt ook prima te doen zonder foreign keys.
Ik had het uiteraard zelf geprobeerd, ging er van uit dat iedereen dat zou begrijpen. Zal volgende keer duidelijker zijn.

Dying is God's way of telling you, you've been FIRED.


Acties:
  • 0 Henk 'm!

  • Manuel
  • Registratie: Maart 2008
  • Laatst online: 17:22
maxtz0r schreef op dinsdag 01 februari 2011 @ 16:23:
[...]


Thnx dat blijkt inderdaad te werken, nou had ik het (string) gedeelte zelf ook gevonden maar zou iemand mij kunnen uitleggen waar die [0] precies voor dient?
Die 0 is in dit geval overbodig. Je gebruikt de 0 alleen als je het niet wilt casten (SimpleXMLElement specifiek).

Zie ook var_dump:
PHP:
1
var_dump($event->gamenumber, (string)$event->gamenumber)

Resultaat:
object(SimpleXMLElement)#5 (1) {
[0]=>
string(9) "192888718"
}
string(9) "192888718"

Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 23:04

MueR

Admin Tweakers Discord

is niet lief

Zou je de Afbeeldingslocatie: http://tweakimg.net/g/forum/images/icons/edit.gif knop willen gebruiken wanneer je nog wat wil toevoegen? We hebben die waarschuwing niet voor niets onder topics staan.

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • WouZz
  • Registratie: Mei 2000
  • Niet online

WouZz

Elvis is alive!

maxtz0r schreef op dinsdag 01 februari 2011 @ 16:23:
[...]


Thnx dat blijkt inderdaad te werken, nou had ik het (string) gedeelte zelf ook gevonden maar zou iemand mij kunnen uitleggen waar die [0] precies voor dient?
Het idee is dat je met SimpleXML door een XML boom structuur kan navigeren. Nu kunnen er in XML meerdere child elementen met dezelfde naam onder een parent element zitten. Bv: meerdere 'event' elementen onder 'events'. Daarom wordt voor iedere element naam op een bepaald niveau een Array aangemaakt in de object representatie (je php variabele). Met [0] geef je aan dat je het eerste item uit de array wil hebben.

Nou is SimpleXML nogal makkelijk, dus soms hoef je dat niet expliciet te doen, maar geeft SimpleXML meteen het eerste element terug.

(Waarschijnlijk is het onder water nog iets anders, namelijk dat je een object terug krijgt, maar dat de string representatie daarvan het eerste element is van een Array met 1 item.)

On track


Acties:
  • 0 Henk 'm!

  • maxtz0r
  • Registratie: Februari 2007
  • Laatst online: 17-12-2022
MueR schreef op dinsdag 01 februari 2011 @ 16:33:
Zou je de [afbeelding] knop willen gebruiken wanneer je nog wat wil toevoegen? We hebben die waarschuwing niet voor niets onder topics staan.
excuus
WouZz schreef op dinsdag 01 februari 2011 @ 16:47:
[...]


Het idee is dat je met SimpleXML door een XML boom structuur kan navigeren. Nu kunnen er in XML meerdere child elementen met dezelfde naam onder een parent element zitten. Bv: meerdere 'event' elementen onder 'events'. Daarom wordt voor iedere element naam op een bepaald niveau een Array aangemaakt in de object representatie (je php variabele). Met \[0] geef je aan dat je het eerste item uit de array wil hebben.

Nou is SimpleXML nogal makkelijk, dus soms hoef je dat niet expliciet te doen, maar geeft SimpleXML meteen het eerste element terug.

(Waarschijnlijk is het onder water nog iets anders, namelijk dat je een object terug krijgt, maar dat de string representatie daarvan het eerste element is van een Array met 1 item.)
Ok duidelijk, ik dacht het volgende te doen:
PHP:
1
2
3
4
5
foreach($event->participants->participant as $participant) 
    {
$team_een = (string) $participant[0]->participant_name;
$team_twee = (string) $participant[1]->participant_name;
}

Dit blijkt echter niet te werken maar de foreach haalt natuurlijk maar 1 record op en dus is het bovenstaande niet mogelijk. Daarom het volgende gedaan en dat lijkt te werken:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    //Get Participants
    foreach($event->participants->participant as $participant)
    {

        //check who is home team
        if((string) $participant->visiting_home_draw == "Home")
        {
            //Set hometeam parameters
            $hometeam = (string) $participant->participant_name;
            $homecontestantnum = (string) $participant->contestantnum;
            $homerotnum = (string) $participant->rotnum;

        }else {
            //Set awayteam parameters
            $awayteam = (string) $participant->participant_name;
            $awaycontestantnum = (string) $participant->contestantnum;
            $awayrotnum = (string) $participant->rotnum;
        }
    }

Niet echt toegevoegde waarde voor dit topic maar ach 8)7

Dying is God's way of telling you, you've been FIRED.


Acties:
  • 0 Henk 'm!

  • WouZz
  • Registratie: Mei 2000
  • Niet online

WouZz

Elvis is alive!

PHP:
1
2
3
4
5
6
7
8
9
10
$participants = $event->participants->participant;  

$team_een_naam = (string) $participants[0]->participant_name; 
$team_twee_naam = (string) $participants[1]->participant_name;

// of
$team_een = $participants[0]; 
$team_twee = $participants[1];

print $team_een->participant_name;

;)

On track


Acties:
  • 0 Henk 'm!

Verwijderd

Naast simplexml zou je ook gebruik kunnen maken van DomDocument, deze ondersteund ook xpath functies om gerichter je xml nodes te kunnen selecteren en dit maakt het ook makkelijker om het parsen van de XML file op te delen in lossen methods.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class PinacleFeedParser 
{
  private $_oDomDoc;

  private $_aResult;

  function __construct($sFile)
  { 
    $this->_oDomDoc = new DomDocument();
    $this->_oDomDoc->preserveWhitespace = false;
    $this->_oDomDoc->loadXML(file_get_contents($sFile));
  }

  function parseDocument()
  {
    $xmlEvents = $this->_oDomDoc->getElementsByTagName('event');
    foreach($xmlEvents as $xmlEventNode)
    {
      $this->parseEvent($xmlEvents);
    }
    return $this->_aResult;
    
  }

  function parseEvent($xmlEvent)
  {
    // parse een event en plaats deze in de $_aResult array; 
  }

}


Iets in die geest in ieder geval ... dan kun je alle methods los schrijven krijg je geen loop in loop in loop constructie die slecht beheerbaar wordt en waarbij het erg lastig wordt als er wijzigingen in het XML formaat komen.

Acties:
  • 0 Henk 'm!

  • maxtz0r
  • Registratie: Februari 2007
  • Laatst online: 17-12-2022
Verwijderd schreef op dinsdag 01 februari 2011 @ 20:35:
Naast simplexml zou je ook gebruik kunnen maken van DomDocument, deze ondersteund ook xpath functies om gerichter je xml nodes te kunnen selecteren en dit maakt het ook makkelijker om het parsen van de XML file op te delen in lossen methods.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class PinacleFeedParser 
{
  private $_oDomDoc;

  private $_aResult;

  function __construct($sFile)
  { 
    $this->_oDomDoc = new DomDocument();
    $this->_oDomDoc->preserveWhitespace = false;
    $this->_oDomDoc->loadXML(file_get_contents($sFile));
  }

  function parseDocument()
  {
    $xmlEvents = $this->_oDomDoc->getElementsByTagName('event');
    foreach($xmlEvents as $xmlEventNode)
    {
      $this->parseEvent($xmlEvents);
    }
    return $this->_aResult;
    
  }

  function parseEvent($xmlEvent)
  {
    // parse een event en plaats deze in de $_aResult array; 
  }

}


Iets in die geest in ieder geval ... dan kun je alle methods los schrijven krijg je geen loop in loop in loop constructie die slecht beheerbaar wordt en waarbij het erg lastig wordt als er wijzigingen in het XML formaat komen.
Kijk dat bedoelde ik dus eigenlijk ook in mijn eerste post. Al gebruik ik nu maar 1 loop door stukje code van WouZz te gebruiken maar ik ben wel geïnteresseerd in de classe die jij hebt want dat is ook iets wat ik onder de knie moet krijgen. Ik ga ermee aan de slag, dankje voor de tip!

Dying is God's way of telling you, you've been FIRED.


Acties:
  • 0 Henk 'm!

Verwijderd

Wat een toeval, heb toevallig in november precies dezelfde feed gebruikt voor een project inclusief database normalisatie. Dikke lach bij dit topic.

Lees je bovenaan in de feed ook even uit wat er met de incremental moet gebeuren? Anders heb je vrij snel een ban aan je broek.

[ Voor 11% gewijzigd door Verwijderd op 02-02-2011 01:02 ]


Acties:
  • 0 Henk 'm!

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 10-09 18:14

alienfruit

the alien you never expected

Grappig, ik moest laatst een vergelijkbare XML feed parsen alleen was alles in het Frans. XML elementnamen in Frans. Brrrr. Gelukkig bestaan er woordenboeken :X

[ Voor 14% gewijzigd door alienfruit op 02-02-2011 09:01 ]


Acties:
  • 0 Henk 'm!

  • maxtz0r
  • Registratie: Februari 2007
  • Laatst online: 17-12-2022
Verwijderd schreef op woensdag 02 februari 2011 @ 01:02:
Wat een toeval, heb toevallig in november precies dezelfde feed gebruikt voor een project inclusief database normalisatie. Dikke lach bij dit topic.

Lees je bovenaan in de feed ook even uit wat er met de incremental moet gebeuren? Anders heb je vrij snel een ban aan je broek.
Je bedoelt dat je maimaal 1 keer per 2 minuten de feed mag opvragen? Daar was ik inderdaad al van op de hoogte :-)

Enige idee of er ook een feed is met uitslagen? aangezien je er toch al mee bezig bent geweest.

Dying is God's way of telling you, you've been FIRED.

Pagina: 1