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

#php #xml #simplexml #xml-namespaces

#php #xml #simplexml #xml-пространства имен

Вопрос:

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

Местоположения идентифицируются в метаданных тега наблюдения в элементе с именем=»station_name». Данные wind содержатся в 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);

    ?>
  

Ответ №1:

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

Комментарии:

1. Хорошо, я пробовал использовать 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.

2. «/set» означает «установить» из корня документа, попробуйте использовать «./set» или даже просто «set» в качестве вашего xpath. также, почему вы присваиваете результат $test[0], почему не просто $ test?

3. Нет веской причины для $ test[0], я полагаю, что это остаток того времени, когда я предполагал, что $ test возвращает массив. Когда я делаю $location-> xpath(«./set») Я получаю эту ошибку: Неустранимая ошибка: вызов функции-члена xpath() для не-объекта в simple_xml.php в строке 9. Если я выполняю $xml-> xpath(«./set»), на страницу ничего не выводится. Какой код вы бы использовали для возврата атрибута value <имя элемента=»station_name» uom=»unitless» value=»Gimli»/> из xml-файла?

Ответ №2:

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

Комментарии:

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