You can use it 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 still be filtered with predicates, which operate in the context of the step and make the selection with boolean expressions.
In the example XML you presented, you can select the city with:
/weatherdata/location/name
To latitude is inside a attribute, which can be selected with an additional step within a axle special (with prefix @
):
/weatherdata/location/location/@latitude
You can also use descending axes, which select several elements without taking into account intermediate contexts:
//location
returns a set containing two elements: the location
who is the son of weatherdata
(/weatherdata/location
), and the other location
who is the grandson of weatherdata
and son of the first location
(/weatherdata/location/location
).
A predicate can be used to filter these results. The expression:
(//location)[2]
filters the set to select only the second element. The parentheses ensure that the position is absolute for all elements located (and not for the position of location
within its context, which is default)
In the example you posted, you can recover all the objects time
with a very simple expression:
//time
This expression returns a set of nodes, which you can manipulate into a for-each and extract whatever you want from them: attribute values, child elements, etc. You can also perform Xpath expressions contextual. Once within of the context of the element time
, you can use expressions like precipitation/@value
(that do not begin with /
) to obtain the attribute value value
of the element precipitation
of the object time
selected.
The following example reads the document in the URL you passed, selects all elements time
, and assembles an HTML table containing the attributes to
and from
, in addition to two attributes of the child element temperature
: max
and min
.
<?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";
?>
The elements were selected with Xpath, but the attributes used the function getAttribute()
XML DOM. You could have done everything with Xpath as well, for example:
$tempMax = $xpath->evaluate('temperature/@max', $time);
The elements are always returned as a set, even if unitary, why they need the ->item(0)
to extract the first. Attributes do not need. When the expression returns a node that has a value (like a text node), you can assign this value to a string using ->nodeValue
.
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