You can use XPath . In XPath you can express a path within an XML as a sequence of steps . Each step creates a context for the next step. The last step contains the elements you want to select. Contexts and selection can also be filtered with predicates, which operate in the context of the step and make the selection with Boolean expressions.
In the example XML you submitted, you can select the city with:
/weatherdata/location/name
The latitude is inside an attribute , which can be selected with an additional step inside a special axis %):
/weatherdata/location/location/@latitude
You can also use descendant axes , which selects multiple elements without taking intermediate contexts into account:
//location
returns a set containing two elements: @
that is the child of location
( weatherdata
), and the other /weatherdata/location
that is net of location
and child of first weatherdata
( location
).
A predicate can be used to filter these results. The expression:
(//location)[2]
filters the set so that only the second element is selected. The parentheses ensure that the position is absolute relative to all localized elements (and not to the position of /weatherdata/location/location
within its context, which is default )
In the example you posted, you can retrieve all location
objects with a very simple expression:
//time
This expression returns a set of nodes, which you can manipulate in a for-each and extract what you want from them: attribute values, child elements, and so on. You can also perform contextual XPath expressions . Once in the context of the time
element, you can use expressions like time
(which do not start with precipitation/@value
) to get the value of the /
attribute of the value
element object% with% selected.
The following example reads the document in the URL you passed, selects all elements precipitation
, and assembles an HTML table containing the time
and time
attributes, plus two attributes of the to
: from
and temperature
.
<?php
$doc = new DOMDocument();
$doc->load( "http://api.openweathermap.org/data/2.5/forecast?q=Tubar%C3%A3o,br&mode=xml" );
$xpath = new DOMXpath($doc);
echo '<table border="1">'."\n";
echo '<tr><th>From</th><th>To</th><th>Temp min</th><th>Temp max</th></tr>'."\n";
foreach ($xpath->evaluate("//time") as $time) {
echo '<tr>'."\n";
echo '<td>'.$time->getAttribute('from').'</td>'."\n";
echo '<td>'.$time->getAttribute('to').'</td>'."\n";
$temp = $xpath->evaluate('temperature', $time)->item(0);
echo '<td>'.$temp->getAttribute('min').' '.$temp->getAttribute('unit').'</td>'."\n";
echo '<td>'.$temp->getAttribute('max').' '.$temp->getAttribute('unit').'</td>'."\n";
echo '<tr>'."\n";
}
echo '</table>'."\n";
?>
Elements were selected with XPath, but the attributes used the max
function of the XML DOM. You could have done everything with XPath too, for example:
$tempMax = $xpath->evaluate('temperature/@max', $time);
Elements are always returned as a set , even if unary, so they need min
to extract the first. Attributes do not need to. When the expression returns a node that has a value (such as a text node), you can assign that value to a string using getAttribute()
.
The above example should serve as a starting point for what you want to do. See it working in real time on this Fiddle PHP