[PHP] RSS parser to array

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Rainmaker1987
  • Registratie: Juni 2005
  • Laatst online: 08-12-2024
Voor mijn scriptie ben ik bezig een site te maken waarin services automatisch aan elkaar gekoppeld worden. Een belangrijk gedeelte hiervoor is het standaardiseren van de output van de verschillende services. Gelukkig maken de meeste API's gebruik van simpele XML of JSON als output alleen sommige geven meer een RSS achtige feed terug. Bij deze feeds kom ik in de problemen om deze om te zetten richting een php array.

! Even om misverstanden te voorkomen ik ben een bedrijfskunde student en de site die ik wil maken is niets meer dan een tool om mijn experiment uit te voeren !

Voor de XML bestanden gebruik ik simplexml_load_string($data) en zet deze vervolgens om. Bij de RSS feeds kom ik echter in de problemen omdat deze gebruik maken van namespaces welke simplexml niet laat zien. Google Calendar doet dit bijvoorbeeld. Ik heb al geprobeerd om dit te tackelen door een aantal standaard parsers te gebruiken maar bijvoorbeeld rss_php.php (http://rssphp.net/) heeft het probleem dat hij dan alleen de laatste entry weergeeft. Magpie krijg ik niet aan de gang, daar zitten veel verwijzingsfouten in.

Voor simplexml hoopte ik dmv getDocNamespaces() en vervolgens registerXPathNamespace($key, $namespace); de namespaces duidelijk te maken mar dit is niet genoeg.

Wat ik probeer te bereiken is een generieke parser naar een array toe die elk willekeurig XML/RSS feed netjes omzet en daarbij ook de namespace variabelen meeneemt. Handmatig kan ik uiteraard wel precies aangeven welke namespaces er gebruikt moeten worden om bepaalde variabelen binnen te halen maar dit is nu net niet de bedoeling.

Hebben jullie nog ideeën hoe dit verder op te pakken?

Acties:
  • 0 Henk 'm!

  • alex3305
  • Registratie: Januari 2004
  • Laatst online: 15:48
Namespaces worden aangemaakt met een :, als je nu gewoon heel simpel:
PHP:
1
2
3
<?php  
    $newXml = str_replace(':', '', $xml);
?>

doet? Dan haal je alle namespaces eruit. Is misschien een workaround, maar was voor mij ruim voldoende om een oplossing te bereiken met de simplexml parser :). En anders zou kunnen proberen een
print_r($object)
of
var_dump($object)
te doen op het object zodat je inzicht krijgt in het gehele object :).

Vergeet niet bij die functies er <pre> tags omheen te zetten zodat ze netjes uitgelijnd weergegeven worden :)

Acties:
  • 0 Henk 'm!

  • Rainmaker1987
  • Registratie: Juni 2005
  • Laatst online: 08-12-2024
@Alex3305 bedankt voor je reactie. Ik heb het even iets netter opgelost aangezien je met jouw oplossing alle dubbele punten direct verwijderd, en dat is een beetje zonde om dat in je values ook te doen.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
          $xml_data_tmp = simplexml_load_string($xml_data);
          
          //Retrieve Namespaces
          $array = $xml_data_tmp->getDocNamespaces(true);
          
          //Strip namespaces from raw data (except for the empty key)
          foreach($array as $key => $namespace)
          {
              if($key != "")
                    $xml_data = str_replace($key.":", '', $xml_data);
          }
          $xml_data = simplexml_load_string($xml_data);


Mochten er nog wat elegantere oplossingen zijn dan hoor ik die uiteraard graag. Was waarschijnlijk tot nu toe wat te ingewikkeld aan het denken

De data wordt overigens niet direct weergegeven voor de user, dus <pre> tags zijn niet nodig. De data gaat indien nodig automatisch door naar een volgende service. In aparte XML bestanden worden deze services beschreven en verteld hoe de benodigde data uit de service kan worden gehaald. Volgende challenge: hoe te werken met meerdere outputs per service

[ Voor 17% gewijzigd door Rainmaker1987 op 07-09-2011 15:57 ]


Acties:
  • 0 Henk 'm!

  • alex3305
  • Registratie: Januari 2004
  • Laatst online: 15:48
Je kunt, even als tip, ook empty() gebruiken ipv != '' :). Daarnaast gooi je nu de key weg, is dat wel de bedoeling?

Acties:
  • 0 Henk 'm!

  • Rainmaker1987
  • Registratie: Juni 2005
  • Laatst online: 08-12-2024
Ik gooi niet de volledige key weg, alleen de namespace die erbij zat. En wat ik tot nu toe heb gezien zal dit geen probleem geven. Even als voorbeeld:

XML:
1
<gd:when endTime='2011-09-08T17:00:00.000+02:00' startTime='2011-09-08T14:30:00.000+02:00'>


komt eruit als:
PHP:
1
2
3
4
5
6
7
                    [when] => Array
                        (
                            [@attributes] => Array
                                (
                                    [endTime] => 2011-09-08T17:00:00.000+02:00
                                    [startTime] => 2011-09-08T14:30:00.000+02:00
                                )


de namespace gd is niet veelzeggend voor de menselijke lezer. Ik geef liever when dan gdwhen aan als keuze om een variabele te selecteren (dit is overigens een onderdeel van een afspraak binnen google calendar)

Acties:
  • 0 Henk 'm!

  • Ram0n
  • Registratie: Maart 2002
  • Laatst online: 20-04 16:44

Ram0n

Bierbrouwende nerd

Rainmaker1987 schreef op woensdag 07 september 2011 @ 15:54:
De data wordt overigens niet direct weergegeven voor de user, dus <pre> tags zijn niet nodig. De data gaat indien nodig automatisch door naar een volgende service. In aparte XML bestanden worden deze services beschreven en verteld hoe de benodigde data uit de service kan worden gehaald. Volgende challenge: hoe te werken met meerdere outputs per service
Het <pre>-verhaaltje noemde alex3305 voor het debuggen met print_r() en var_dump() :) Een handige tip, aangezien die functies flink wat info teruggeven met indenting, maar zonder <pre> gaat dat verloren en komt het weer op één regel te staan.

Eigenaar/brouwer Milky Road Brewery


Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 21:29
alex3305 schreef op woensdag 07 september 2011 @ 15:57:
Je kunt, even als tip, ook empty() gebruiken ipv != '' :). Daarnaast gooi je nu de key weg, is dat wel de bedoeling?
Dat is niet equivalent. Empty('0') is TRUE waar ('0' != '') naar FALSE evalueert.
Rainmaker1987 schreef op woensdag 07 september 2011 @ 16:02:
Ik gooi niet de volledige key weg, alleen de namespace die erbij zat. En wat ik tot nu toe heb gezien zal dit geen probleem geven. Even als voorbeeld:
En wat als je feed nu meerdere namespaces bevat met dezelfde tags? <ab:bla /> en <zx:bla>.

De "correcte" manier is om de namespaces uit te lezen. Googlen op simple_xml namespaces had je bijvoorbeeld deze blog geleverd waar wat tips staan. Wat ik eruit afleidt is dat jeiets als het volgende kunt doen om de namespaces intact te laten:
PHP:
1
2
3
4
5
6
7
8
$namespaces = $simple_xml_doc->getNameSpaces(true);

foreach($namespaces as $prefix => $url) {
    $children = $current_node->children($url]);
    foreach($children as $child) {
       $output[$prefix .':'. $child->getName()] = $child->__toString();
    }
}

Zoiets zul je dan dus moeten inbouwen voor je huidige xml->array conversiefunctie.

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • Y0ur1
  • Registratie: Oktober 2000
  • Niet online
Al eens gekeken naar http://developer.yahoo.com/yql/? Console: http://developer.yahoo.com/yql/console/

Volgens mij doet dat wat jij nu zelf aan het bouwen bent :) Misschien handig voor je scriptie?

Acties:
  • 0 Henk 'm!

  • moozzuzz
  • Registratie: Januari 2005
  • Niet online
Ik gebruik steeds domdocument voor dit soort RSS-gein.

  • iH8
  • Registratie: December 2001
  • Laatst online: 17-06-2024

iH8

Zend_Feed uit Zend Framework (component class is ook los te gebruiken) heeft ondersteuning voor custom namespaces.

http://framework.zend.com...end.feed.custom-feed.html
Finally, you can extend the Zend_Feed classes if you'd like to provide your own format or niceties like automatic handling of elements that should go into a custom namespace.

Aunt bunny is coming to get me!

Pagina: 1