0

Here I am trying to read a few elements which contain <xCal:x-calconnect> in them.

Here is the structure of item node inside an xml file(irrelevant nodes omitted):

<item>
                    <xCal:location>http://www.eventbrite.com/e/11610813255?aff=es2</xCal:location>
                    <xCal:x-calconnect-venue>
                        <xCal:adr>
                                <xCal:x-calconnect-venue-name>Colony Bar</xCal:x-calconnect-venue-name>
                                <xCal:x-calconnect-street>24 Hertford Street</xCal:x-calconnect-street>
                                <xCal:x-calconnect-region>Gt Lon</xCal:x-calconnect-region>
                                <xCal:x-calconnect-city>London</xCal:x-calconnect-city>
                                <xCal:x-calconnect-country>GB</xCal:x-calconnect-country>
                        </xCal:adr>
                    </xCal:x-calconnect-venue>
                    <xCal:url type="Event Website">http://www.eventbrite.com/e/11610813255?aff=es2</xCal:url>
                        <xCal:x-calconnect-organizer>
                            <xCal:x-calconnect-organizer-name>Young Professionals London</xCal:x-calconnect-organizer-name>
                        </xCal:x-calconnect-organizer>
                </item>

And here is my best try to read them:

$rawFeed = file_get_contents($url);
$xml = simplexml_load_string($rawFeed);

foreach($xml->channel->item as $item)
{
    $itemxcal=$item->children('xCal', true)->location;
    $itemx=$item->children('xCal:x-calconnect', true)->organizer->children('xCal:x-calconnect-organizer', true)->name;
    $itemvenue=$item->children('xCal:x-calconnect', true)->venue->children('xCal', true)->adr->children('xCal:x-calconnect', true)->street;
    echo $itemx, $itemxcal"<br />";
}

I can read the location node without a problem, but things start getting interesting when I try to read either organizer name or any information about the venue. I get errors like "Warning: main(): Node no longer exists" OR I get totally nothing when removing the part after "->organizer". As I mentioned there's no problem with reading location. Works perfectly. All help is appreciated!

  • You should be interested to enable error reporting to the highest level and try to trouble-shoot all notices as you can only learn about the errors you have in your code, see: [How to get useful error messages in PHP?](http://stackoverflow.com/q/845021/367456) – hakre Jun 23 '14 at 13:20

1 Answers1

0

You mix with the namespaces here, looks a bit you're trying at free will w/o further guidance:

<xCal:location>
 ^^^^ ********

$item->children('xCal', true)->location;
                ^^^^^^         ********

This is okay, it represents all children in in the xCal (as prefixed) namespace and therein you access the one that has the name location.

However with the other element:

<xCal:x-calconnect-organizer>
 ^^^^ **********************

$item->children('xCal:x-calconnect', true)->organizer
                 ^^^^ ????????????          ?????????

This PHP code is a total mismatch. children() needs the prefix only and the prefix is "xCal" but you used "xCal:x-calconnect" which is not a valid namespace prefix in your document.

You added partially from the element name to the prefix. The error continues then as you add the rest of the element name as the field name.

The correct version to get the namespace and the element then would look like:

<xCal:x-calconnect-organizer>
 ^^^^ **********************

 $item->children('xCal', true)->x-calconnect-organizer
                  ^^^^          **********************

However this produces notices in PHP. Something like:

Notice: Use of undefined constant calconnect - assumed 'calconnect' in /path/to/file.php on line 36

Notice: Use of undefined constant organizer - assumed 'organizer' in /path/to/file.php on line 36

That is because "x-calconnect-organizer" is not a valid expression for a field-name in PHP. PHP tries to parse this differently (substracting strings from each other, it's a minus sign there in).

This is a common problem with SimpleXMLElement and explained and outlined in the PHP manual:

See especially here Example #3 Getting <line> and the paragraph above (the whole page is a good read and a nice example to try your own).

We also have reference material here on site as this is more common:

And here a final tip: You can assign these children to a variable, and with that variable, you're sticking to that namespace:

$xcal     = $item->children('xCal', true);
$location = $xcal->location;
$name = $xcal->{'x-calconnect-organizer'}->{'x-calconnect-organizer-name'};

Gives:

http://www.eventbrite.com/e/11610813255?aff=es2 (by Young Professionals London)

In this full example:

<?php
/*
 * @link https://stackoverflow.com/questions/24365460/parsing-xcal-elements-in-php
 */

$buffer = <<<XML
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"
      xmlns:xCal="urn:ietf:params:xml:ns:xcal">
    <item>
        <xCal:location>http://www.eventbrite.com/e/11610813255?aff=es2</xCal:location>
        <xCal:x-calconnect-venue>
            <xCal:adr>
                <xCal:x-calconnect-venue-name>Colony Bar</xCal:x-calconnect-venue-name>
                <xCal:x-calconnect-street>24 Hertford Street</xCal:x-calconnect-street>
                <xCal:x-calconnect-region>Gt Lon</xCal:x-calconnect-region>
                <xCal:x-calconnect-city>London</xCal:x-calconnect-city>
                <xCal:x-calconnect-country>GB</xCal:x-calconnect-country>
            </xCal:adr>
        </xCal:x-calconnect-venue>
        <xCal:url type="Event Website">http://www.eventbrite.com/e/11610813255?aff=es2</xCal:url>
        <xCal:x-calconnect-organizer>
            <xCal:x-calconnect-organizer-name>Young Professionals London</xCal:x-calconnect-organizer-name>
        </xCal:x-calconnect-organizer>
    </item>
</feed>
XML;


$xml = simplexml_load_string($buffer);

foreach ($xml as $item) {
    $xcal     = $item->children('xCal', true);
    $location = $xcal->location;
    $name = $xcal->{'x-calconnect-organizer'}->{'x-calconnect-organizer-name'};

    echo "$location (by $name)\n";
}
Community
  • 1
  • 1
hakre
  • 193,403
  • 52
  • 435
  • 836