Помощь в навигации по файлу XML с несколькими пространствами имен с помощью simplexml

Я работаю над программой для сбора метеорологических данных из файла XML. В частности, я хотел бы просмотреть файл, подобный указанному ниже, и получить статистику ветра для определенных мест.

Местоположение указано в метаданных тега Observation в элементе name="station_name". Данные о ветре содержатся в Observation -> elements.

Использование нескольких пространств имен, похоже, мешает моим ограниченным знаниям о том, как использовать simplexml для анализа файла xml.

XML-файл, который я пытаюсь разобрать: http://dd.weatheroffice.gc.ca/observations/xml/MB/hourly/hourly_mb_2011050723_e.xml

Я сократил это для тестирования до одного наблюдения (см. ниже):

    <?xml version="1.0" encoding="UTF-8"?>
    <om:ObservationCollection xmlns:om="http://www.opengis.net/om/1.0" xmlns="http://dms.ec.gc.ca/schema/point-observation/2.0" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<om:member>
    <om:Observation>
        <om:metadata>
            <set><general><author name="MSC-DMS-PG-WXO-HOURLY" version="1.5"/><dataset name="msc/observation/atmospheric/surface_weather/wxo-2.0-ascii"/><phase name="product-hourly_en-xml-2.0"/><id xlink:href="/data/msc/observation/atmospheric/surface_weather/wxo-2.0-ascii/product-hourly_en-xml-2.0/201105072356/mb"/><parent xlink:href="/data/msc/observation/atmospheric/surface_weather/cs-1.0-binary/decoded-xml-2.0/201105072300/cpgh"/></general>
            <identification-elements>
                <element name="station_name" uom="unitless" value="Gimli"/>
                <element name="latitude" uom="degree" value="50.63"/>
                <element name="longitude" uom="degree" value="-97.05"/>
                <element name="transport_canada_id" uom="unitless" value="PGH"/>
                <element name="observation_date_utc" uom="unitless" value="2011-05-07T23:00:00.000Z"/>
                <element name="observation_date_local_time" uom="unitless" value="2011-05-07T18:00:00.000 CDT"/>
                <element name="climate_station_number" uom="unitless" value="5031042"/>
                <element name="wmo_station_number" uom="unitless" value="71748"/>
            </identification-elements>
            </set>
        </om:metadata>
        <om:samplingTime><gml:TimeInstant><gml:timePosition>2011-05-07T23:00:00.000Z</gml:timePosition></gml:TimeInstant></om:samplingTime>
        <om:resultTime><gml:TimeInstant><gml:timePosition>2011-05-07T23:56:09.099Z</gml:timePosition></gml:TimeInstant></om:resultTime>
        <om:procedure xlink:href=""/>
        <om:observedProperty gml:remoteSchema="/schema/point-observation/2.0.xsd"/>
        <om:featureOfInterest>
            <gml:FeatureCollection>
                <gml:location><gml:Point><gml:pos>50.63333333333333 -97.05</gml:pos></gml:Point></gml:location>
            </gml:FeatureCollection>
        </om:featureOfInterest>
        <om:result>
        <orig-header/>
        <elements>
            <element name="present_weather" uom="code" value=""/>
            <element name="mean_sea_level" uom="kPa" value="100.89"/>
            <element name="tendency_amount" uom="kPa" value="0.07"/>
            <element name="tendency_characteristic" uom="code" value="rising"/>
            <element name="horizontal_visibility" uom="km" value=""/>
            <element name="air_temperature" uom="Celsius" value="11.4"/>
            <element name="dew_point" uom="Celsius" value="8.2"/>
            <element name="relative_humidity" uom="percent" value="81.0"/>
            <element name="wind_speed" uom="km/h" value="24.8"/>
            <element name="wind_direction" uom="code" value="SW"/>
            <element name="wind_gust_speed" uom="km/h" value="36.4"/>
            <element name="total_cloud_cover" uom="code" value=""/>
            <element name="wind_chill" uom="unitless" value=""/>
            <element name="humidex" uom="unitless" value=""/>
        </elements>
        </om:result>
    </om:Observation>
</om:member>
    </om:ObservationCollection>

Это то, что у меня есть до сих пор, и это официально никуда меня не приведет...

    <?php
$xml = simplexml_load_file("weather.xml");
foreach($xml->item as $item){
    $collection = $item->children("http://www.opengis.net/om/1.0");
}

print_r($collection->member);

    ?>

person dirknibleck    schedule 08.05.2011    source источник


Ответы (2)


Попробуйте использовать язык XPath для запроса ваших данных с помощью xpath из SimpleXMLElement.

person Andrey Adamovich    schedule 08.05.2011
comment
Хорошо, я пытался использовать xpath, но, похоже, это меня никуда не привело. У меня есть следующий код: $xml = simplexml_load_file("weather.xml"); $xml->registerXPathNamespace("om", "http://www.opengis.net/om/1.0"); $elements = $xml->xpath("//om:Observation"); $location = $xml->xpath("/om:ObservationCollection/om:member/om:Observation/om:metadata"); $test[0] = $location->xpath("/set"); foreach($test as $k=>$v){ echo "<br/>$k=$v"; } который, по крайней мере, дает мне массив для $elements, но я ничего не получаю из $test. - person dirknibleck; 08.05.2011
comment
/set означает установить из корня документа, попробуйте использовать ./set или даже просто установите как ваш xpath. также почему вы присваиваете результат $test[0], почему не просто $test? - person Andrey Adamovich; 09.05.2011
comment
Нет веской причины для $test[0], я считаю, что это пережиток того, когда я предполагал, что $test возвращает массив. Когда я делаю $location->xpath(./set), я получаю эту ошибку: Неустранимая ошибка: вызов функции-члена xpath() для не-объекта в simple_xml.php в строке 9. Если я делаю $xml->xpath (./set) на страницу ничего не выводится. Какой код вы бы использовали для возврата атрибута значения ‹имя элемента=имя_станции uom=безразмерное значение=Гимли/› из файла xml? - person dirknibleck; 09.05.2011

В конечном итоге я использовал str_replace для замены om: в исходной строке xml. Это избавило от необходимости применять пространство имен и упростило навигацию по xml с помощью simplexml.

person dirknibleck    schedule 10.05.2011
comment
Иронично! Когда я извлекаю данные из веб-сервисов, например, сценарий last.fm, который я написал на прошлой неделе, я всегда использую регулярное выражение для добавления временного пространства имен к корневому узлу, если его нет, поэтому что я могу легко различать элементы, когда объединяю документы и использую XSLT. - person Nicholas Wilson; 10.05.2011