XML feed uitlezen met PHP
Code (php)
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
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
<weatherdata>
<location>
<name>Gent</name>
<type/>
<country>BE</country>
<timezone/>
<location altitude="0" latitude="51.049999" longitude="3.71667" geobase="geonames" geobaseid="0"/>
</location>
<credit/>
<meta>
<lastupdate/>
<calctime>0.011</calctime>
<nextupdate/>
</meta>
<sun rise="2015-05-16T03:53:02" set="2015-05-16T19:29:58"/>
<forecast>
<time day="2015-05-16">
<symbol number="500" name="light rain" var="10d"/>
<precipitation value="0.5" type="rain"/>
<windDirection deg="322" code="NW" name="Northwest"/>
<windSpeed mps="4.76" name="Gentle Breeze"/>
<temperature day="13.83" min="5.78" max="14.01" night="5.78" eve="14.01" morn="13.83"/>
<pressure unit="hPa" value="1033.93"/>
<humidity value="93" unit="%"/>
<clouds value="overcast clouds" all="92" unit="%"/>
</time>
<time day="2015-05-17">
<symbol number="800" name="sky is clear" var="02d"/>
<precipitation/>
<windDirection deg="274" code="W" name="West"/>
<windSpeed mps="3.47" name="Gentle Breeze"/>
<temperature day="16.37" min="7.6" max="17.13" night="7.6" eve="15.53" morn="9.14"/>
<pressure unit="hPa" value="1034.56"/>
<humidity value="77" unit="%"/>
<clouds value="clear sky" all="8" unit="%"/>
</time>
</forecast>
</weatherdata>
<location>
<name>Gent</name>
<type/>
<country>BE</country>
<timezone/>
<location altitude="0" latitude="51.049999" longitude="3.71667" geobase="geonames" geobaseid="0"/>
</location>
<credit/>
<meta>
<lastupdate/>
<calctime>0.011</calctime>
<nextupdate/>
</meta>
<sun rise="2015-05-16T03:53:02" set="2015-05-16T19:29:58"/>
<forecast>
<time day="2015-05-16">
<symbol number="500" name="light rain" var="10d"/>
<precipitation value="0.5" type="rain"/>
<windDirection deg="322" code="NW" name="Northwest"/>
<windSpeed mps="4.76" name="Gentle Breeze"/>
<temperature day="13.83" min="5.78" max="14.01" night="5.78" eve="14.01" morn="13.83"/>
<pressure unit="hPa" value="1033.93"/>
<humidity value="93" unit="%"/>
<clouds value="overcast clouds" all="92" unit="%"/>
</time>
<time day="2015-05-17">
<symbol number="800" name="sky is clear" var="02d"/>
<precipitation/>
<windDirection deg="274" code="W" name="West"/>
<windSpeed mps="3.47" name="Gentle Breeze"/>
<temperature day="16.37" min="7.6" max="17.13" night="7.6" eve="15.53" morn="9.14"/>
<pressure unit="hPa" value="1034.56"/>
<humidity value="77" unit="%"/>
<clouds value="clear sky" all="8" unit="%"/>
</time>
</forecast>
</weatherdata>
Ik lees die op de onderstaande manier uit:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
// Dit is de URL waarvan de output hierboven staat
$request_url1 = "http://api.openweathermap.org/data/2.5/forecast/daily?q=gent&mode=xml&units=metric&cnt=2";
$xml1 = simplexml_load_file($request_url1) or die("feed not loading");
foreach($xml1->time[0]->temperature->attributes() as $key => $test2) {
if($key == 'day') {
echo $test2.'C';
}
}
$request_url1 = "http://api.openweathermap.org/data/2.5/forecast/daily?q=gent&mode=xml&units=metric&cnt=2";
$xml1 = simplexml_load_file($request_url1) or die("feed not loading");
foreach($xml1->time[0]->temperature->attributes() as $key => $test2) {
if($key == 'day') {
echo $test2.'C';
}
}
Nu krijg ik geen resultaat. Waar heb ik een fout gemaakt?
Gewijzigd op 16/05/2015 20:35:10 door Brecht S
Op regel 6 ga je verder met $xml (zonder 1).
Thanks Eddy. Ik heb de code even aangepast. Werkt nog steeds niet.
Staat error_reporting(E_ALL); bovenaan?
Toevoeging op 16/05/2015 20:52:00:
Je mist ook een } aan het eind.
Ik kreeg geen foutmelding en ook geen resultaat.
http://zunflappie.nl/phphulp/xml1.php
En dat is:
Hetgeen wat fout ging is dat je een object wilt benaderen als string. Dat kan, maar dan eerst omzetten.
Zie http://php.net/manual/en/simplexmlelement.attributes.php
Sorry, ik had die laatste } niet meegekopieerd.
En dat is:
Code (php)
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
// altijd alle fouten tonen. Bij LIVE-gaan dit op 0 zetten.
error_reporting(E_ALL);
// wat halen we op?
$xml = simplexml_load_file("http://api.openweathermap.org/data/2.5/forecast/daily?q=gent&mode=xml&units=metric&cnt=2");
if (false === $xml)
{
echo 'Data kon niet geladen worden';
}
// benodigde functie. Kan ook ergens als include.
function xml_attribute($object, $attribute)
{
if (isset($object[$attribute]))
{
return (string)$object[$attribute];
}
}
// even een dump van de XML
echo '<pre>' . print_r($xml, true) . '<pre>';
echo 'Wat jij wilt hebben: '. (xml_attribute($xml -> forecast -> time[0] -> temperature, 'day'));
?>
// altijd alle fouten tonen. Bij LIVE-gaan dit op 0 zetten.
error_reporting(E_ALL);
// wat halen we op?
$xml = simplexml_load_file("http://api.openweathermap.org/data/2.5/forecast/daily?q=gent&mode=xml&units=metric&cnt=2");
if (false === $xml)
{
echo 'Data kon niet geladen worden';
}
// benodigde functie. Kan ook ergens als include.
function xml_attribute($object, $attribute)
{
if (isset($object[$attribute]))
{
return (string)$object[$attribute];
}
}
// even een dump van de XML
echo '<pre>' . print_r($xml, true) . '<pre>';
echo 'Wat jij wilt hebben: '. (xml_attribute($xml -> forecast -> time[0] -> temperature, 'day'));
?>
Hetgeen wat fout ging is dat je een object wilt benaderen als string. Dat kan, maar dan eerst omzetten.
Zie http://php.net/manual/en/simplexmlelement.attributes.php
Sorry, ik had die laatste } niet meegekopieerd.
Gewijzigd op 16/05/2015 21:02:28 door Eddy E
Fatal error: Call to a member function attributes() on a non-object
Dus het is niet heel moeilijk om de fout te achterhalen. Op regel 6 moet je hebben:
Je zou je code robuuster kunnen maken met extra checks of bepaalde objecten die je verwacht niet ineens NULL blijken te zijn.
Maaruhm, je weet wel zeker dat de API de temperatuur in graden Celcius (ipv. Fahrenheit) weergeeft? :-)
Nu wil ik een 2de URL feed doen en op dezelfde manier data eruit halen.
De url feed is nu http://api.openweathermap.org/data/2.5/weather?q=Gent&mode=xml&units=metric
Dit is een andere dan de eerste. Als ik die 2 achter elkaar zet loopt het fout en krijg ik op de eerste ook geen resultaat meer. Is dat normaal?
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$url = 'http://api.openweathermap.org/data/2.5/weather?q=Gent&mode=xml&units=metric';
$query = '//current/temperature';
$sxe = simplexml_load_file($url);
$imp = new DOMImplementation();
$dom = $imp->createDocument(null, '');
$dom->xmlVersion = '1.0';
$dom->encoding = 'UTF-8';
$xpath = new DOMXPath($dom);
$dom_sxe = dom_import_simplexml($sxe);
$dom_sxe = $dom->importNode($dom_sxe, true);
$dom_sxe = $dom->appendChild($dom_sxe);
$firstNode = $xpath->query($query)->item(0);
$temp = $firstNode->getAttribute('value') . ' graden '
. $firstNode->getAttribute('unit');
print $temp;
/* DEBUG
header('content-type:text/plain');
var_dump($dom->saveXML());
//*/
$query = '//current/temperature';
$sxe = simplexml_load_file($url);
$imp = new DOMImplementation();
$dom = $imp->createDocument(null, '');
$dom->xmlVersion = '1.0';
$dom->encoding = 'UTF-8';
$xpath = new DOMXPath($dom);
$dom_sxe = dom_import_simplexml($sxe);
$dom_sxe = $dom->importNode($dom_sxe, true);
$dom_sxe = $dom->appendChild($dom_sxe);
$firstNode = $xpath->query($query)->item(0);
$temp = $firstNode->getAttribute('value') . ' graden '
. $firstNode->getAttribute('unit');
print $temp;
/* DEBUG
header('content-type:text/plain');
var_dump($dom->saveXML());
//*/
En als ik beide url's door elkaar wil gebruiken? Lukt dit dan ook nog met XPath?
XPath is een soort querytaal om in hierarchische XML-structuren te zoeken. Je kunt bijvoorbeeld met de query '//temperature' in 1x zoeken op alle <temperature> nodes in beide URL's ja.
Kan je eens een voorbeeld posten van het gebruik in beide urls? Bvb de temperatuur van de eerste en de pressure van de 2de? Ik zie het niet voor mij hoe ik dit moet aanpakken.
Code (php)
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
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
define('EOL', "\n", true);
$urls = array(
'http://api.openweathermap.org/data/2.5/weather?q=Gent&mode=xml&units=metric',
'http://api.openweathermap.org/data/2.5/forecast/daily?q=gent&mode=xml&units=metric&cnt=2',
);
$query = '//temperature';
$units = ' graden celcius';
$imp = new DOMImplementation();
$dom = $imp->createDocument(null, '');
$dom->xmlVersion = '1.0';
$dom->encoding = 'UTF-8';
$xpath = new DOMXPath($dom);
foreach ($urls as $url) {
$sxe = simplexml_load_file($url);
$dom_sxe = dom_import_simplexml($sxe);
$dom_sxe = $dom->importNode($dom_sxe, true);
$dom_sxe = $dom->appendChild($dom_sxe);
}
header('content-type:text/plain');
foreach ($xpath->query($query) as $node) {
$temp = $node->getAttribute('value');
if (!is_numeric($temp)) $temp = $node->getAttribute('day');
print $temp . $units . EOL;
}
$urls = array(
'http://api.openweathermap.org/data/2.5/weather?q=Gent&mode=xml&units=metric',
'http://api.openweathermap.org/data/2.5/forecast/daily?q=gent&mode=xml&units=metric&cnt=2',
);
$query = '//temperature';
$units = ' graden celcius';
$imp = new DOMImplementation();
$dom = $imp->createDocument(null, '');
$dom->xmlVersion = '1.0';
$dom->encoding = 'UTF-8';
$xpath = new DOMXPath($dom);
foreach ($urls as $url) {
$sxe = simplexml_load_file($url);
$dom_sxe = dom_import_simplexml($sxe);
$dom_sxe = $dom->importNode($dom_sxe, true);
$dom_sxe = $dom->appendChild($dom_sxe);
}
header('content-type:text/plain');
foreach ($xpath->query($query) as $node) {
$temp = $node->getAttribute('value');
if (!is_numeric($temp)) $temp = $node->getAttribute('day');
print $temp . $units . EOL;
}
Werkt allemaal perfect. Hier en daar wel nog enkele aanpassingen moeten doen.