Given an xml structure like this
<gesmes:Envelope>
<gesmes:subject>Reference rates</gesmes:subject>
<gesmes:Sender>
<gesmes:name>European Central Bank</gesmes:name>
</gesmes:Sender>
<Cube>
<Cube time="2010-03-26">开发者_开发问答;
<Cube currency="USD" rate="1.3353"/>
<Cube currency="JPY" rate="124.00"/>
<Cube currency="BGN" rate="1.9558"/>
<Cube currency="CZK" rate="25.418"/>
...
...
</Cube>
</Cube>
</gesmes:Envelope>
how can i go about getting the values stored in to a hashmap or similar structure in php?
Have been trying to do this for the last few hours now but cant manage it :D
It is homework so i guess no full solutuins please( tho the actual assignment is to use the web services, i am just stuck with parsing it :D ). Maybe someone could show me a brief example for a made up xml file that i could apply to mine?
Thanks
The easiest way is to use the DOMDocument
class. For example:
$src = <<<END
<Cube>
<Cube time="2010-03-26">
<Cube currency="USD" rate="1.3353"/>
<Cube currency="JPY" rate="124.00"/>
<Cube currency="BGN" rate="1.9558"/>
<Cube currency="CZK" rate="25.418"/>
</Cube>
</Cube>
END;
$xml = new DOMDocument;
$xml->loadXML($src);
$cubes = $xml->getElementsByTagName('Cube');
$currencies = array();
foreach ($cubes as $cube) {
$currency = $cube->getAttribute('currency');
$rate = $cube->getAttribute('rate');
if ($currency && $rate) {
$currencies[$currency] = $rate;
}
}
print_r($currencies);
Output:
Array
(
[USD] => 1.3353
[JPY] => 124.00
[BGN] => 1.9558
[CZK] => 25.418
)
<gesmes:Envelope>
is probably not the "whole truth". A prefix like gesmes:
needs to be associated with an uri. In your case it's probably
<gesmes:Envelope
xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01"
xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"
>
And now you have to deal with namespaces....
There is php's simplexml module. It has some shortcomings when namespaces are involved. But anyway... here it is:
$s = new SimpleXMLelement(getData());
foreach( $s->Cube as $cubeContainer) {
foreach( $cubeContainer as $cubeEntry) {
echo 'time: ', $cubeEntry['time'], "\n";
foreach( $cubeEntry->Cube as $cubeElement) {
echo ' ', $cubeElement['currency'], '=', $cubeElement['rate'], "\n";
}
}
}
// now that was easy ...now the fun of having namespaces/prefixes
foreach( $s->children("http://www.gesmes.org/xml/2002-08-01")->subject as $subject) {
echo 'subject: ', $subject, "\n";
}
foreach( $s->children("http://www.gesmes.org/xml/2002-08-01")->Sender as $sender) {
foreach( $sender->children("http://www.gesmes.org/xml/2002-08-01")->name as $name) {
echo 'sender/name: ', $name, "\n";
}
}
function getData() {
return '<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
<gesmes:subject>Reference rates</gesmes:subject>
<gesmes:Sender>
<gesmes:name>European Central Bank</gesmes:name>
</gesmes:Sender>
<Cube>
<Cube time="2010-03-26">
<Cube currency="USD" rate="1.3353"/>
<Cube currency="JPY" rate="124.00"/>
<Cube currency="BGN" rate="1.9558"/>
<Cube currency="CZK" rate="25.418"/>
</Cube>
</Cube>
</gesmes:Envelope>';
}
prints
time: 2010-03-26
USD=1.3353
JPY=124.00
BGN=1.9558
CZK=25.418
subject: Reference rates
sender/name: European Central Bank
If you want to use XPath to find specific elements/nodes (either SimpleXMLElement::xpath or DOMXPath which you would use with DOMDocument as pointed out by cletus) you have to register the namespace first.
e.g.
$s = new SimpleXMLelement(getData());
$s->registerXPathNamespace('gesmes', 'http://www.gesmes.org/xml/2002-08-01');
foreach($s->xpath('//gesmes:name[position()=1]') as $n){
echo $n, "\n";
}
prints European Central Bank
.
And there are other functions/methods to parse an XML document. E.g. XMLReader or (which is probably the closest to your your original quest "how can i go about getting the values stored in to a hashmap [...]?") xml_parse_into_struct()
精彩评论