Parsing Media RSS with PHP SimpleXML

Parsing XML docs with PHP SimpleXML is pretty straightforward. Yesterday i lost around 5 minutes to parse a Media RSS XML, and that was weird because normally with SimpleXML you take like 30 seconds… A Media RSS (MRSS) document is just a RSS with media extensions:

<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/">
  <channel>
    <title>RSS Title</title>
    <link>http://www.domain.com/mylink</link>
    <description>My description</description>
    <item>
      <title>Title item 1</title>
      <link>http://www.domain.com/item_1.html</link>
      <description>Item 1 description</description>
      <guid>http://www.domain.com/item_1.html</guid>
      <media:content url="http://www.domain.com/item_1.jpg" height="240" width="320" />
    </item>
    <item>
      <title>Title item 2</title>
      <link>http://www.domain.com/item_2.html</link>
      <description>Item 2 description</description>
      <guid>http://www.domain.com/item_2.html</guid>
      <media:content url="http://www.domain.com/item_2.jpg" height="240" width="320" />
    </item>
    .... etc 
  </channel>
</rss>

The “problem” is to access the media:content or the other media:* elements. But don’t worry I’m going to show you how to do it 🙂

$xml = simplexml_load_file('http://domain.com/mrss.xml');
$namespaces = $xml->getNamespaces(true); // get namespaces

// iterate items and store in an array of objects
$items = array();
foreach ($xml->channel->item as $item) {

  $tmp = new stdClass(); 
  $tmp->title = trim((string) $item->title);
  $tmp->link  = trim((string) $item->link);
  // etc... 
  // now for the url in media:content
  //
  $tmp->media_url = trim((string) 
                    $item->children($namespaces['media'])->content->attributes()->url);

  // add parsed data to the array
  $items[] = $tmp;
}

There, a piece of cake!

UPDATE

I received a comment about Picasa RSS feed, where you have to dig just a bit deeper, as the media:url is inside a media:group. The XML feed is as follows

<?xml version='1.0' encoding='UTF-8'?>
<rss xmlns:atom='http://www.w3.org/2005/Atom' 
xmlns:media='http://search.yahoo.com/mrss/' 
xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' version='2.0'>
  <channel>
    <atom:id>https://picasaweb.google.com/data/feed/base/user/103218581909188195000</atom:id>
    <lastBuildDate>Wed, 16 Apr 2014 07:28:42 +0000</lastBuildDate>
    <title>Galerie fotografií uživatele Jiřetín JINAK</title>
    .... etc
    <item>
      <pubDate>Thu, 10 Apr 2014 07:16:22 +0000</pubDate>
      <atom:updated>2014-04-16T07:28:42.202Z</atom:updated>
      <author>Jiřetín JINAK</author>
      .... etc
      <media:group>
        <media:content url='https://lh6.googleusercontent.com/-C6WmXjRnV8Y/U0ZFRnm-ujE/AAAAAAAAAPQ/AbwIc0Ycugk/s100-c/RizikovaMistaVHornimJiretine.jpg' type='image/jpeg' medium='image'/>
        <media:credit>Jiřetín JINAK</media:credit>
        <media:description type='plain'/>
        <media:keywords/>
        <media:thumbnail url='https://lh6.googleusercontent.com/-C6WmXjRnV8Y/U0ZFRnm-ujE/AAAAAAAAAPQ/AbwIc0Ycugk/s160-c/RizikovaMistaVHornimJiretine.jpg' height='160' width='160'/>
        <media:title type='plain'>Riziková místa v Horním Jiřetíně</media:title>
      </media:group>
    </item>
    .... etc
  </channel>
</rss>

The PHP code follows the same logic, just add another step to take into account media:group

$xml = simplexml_load_file('http://picasaweb.google.com/data/feed/...&prettyprint=true');
$namespaces = $xml->getNamespaces(true); // get namespaces

$items = array();
foreach ($xml->channel->item as $item) {

  $tmp = new stdClass();
  $tmp->title = trim((string) $item->title);
  $tmp->link  = trim((string) $item->link);
  // etc...

  // now for the data in the media:group
  //
  $media_group = $item->children($namespaces['media'])->group;

  $tmp->media_url =    trim((string)
                       $media_group->children($namespaces['media'])->content->attributes()->url);
  $tmp->media_credit = trim((string)
                       $media_group->children($namespaces['media'])->credit);
  // etc

  // add parsed data to the array
  $items[] = $tmp;
}

DNS server with djbdns (VegaDNS GUI + bonus replication)

djbdnsThis is my personal guide to setup djbdns tinydns DNS server to publish domain name information to the Internets. If djbdns, tinydns, name server, dns are strange words just move along, move along…

Continue reading “DNS server with djbdns (VegaDNS GUI + bonus replication)”

Setting up SSH access with server keys (no password) in FreeBSD

You want to login from user@host-a to user@host-b automatically (with no password prompt).

Install ssh-copy-id in the host-a. This little handy script takes care of all the dirty details from your back.

cd /usr/ports/security/ssh-copy-id
make install clean

then run (still in host-a)

ssh-copy-id user@host-b

If you get the error “ERROR: No identities found” then you must generate your keys first and then re-run ssh-copy-id. To generate a pair of private/public SSH keys you must issue:

mkdir ~/.ssh
chmod 700 ~/.ssh
ssh-keygen -t rsa

You can leave the pass-phrase empty for automatic logins (no password prompt) or the more secure but less practical password prompt each and every time that you use the newly generated keys.

Next login from host-a to user@host-b will be made with SSH keys.

The dirty details

  • the user@host-a public key, usually ~/.ssh/id_rsa.pub is copied to host-b user/.ssh/authorized_keys
  • the host-b public host key (/etc/ssh/ssh_host_rsa_key.pub) is copied to host-a known hosts

The not so quiet revolution

How many times did i hear… the “ahh…good old times” rant. Sure, sometimes the world as we know it now is complicated, sometimes unfair and even cruel and bad. But if you stop and zoom out a bit, like 20 years (don’t need to go all the way to the dark ages), one realizes the leap forward. And in technology the leap is nothing short of massive – thank you Mr. Moore. I’m really glad and lucky to be apart of this.

You can get a Raspberry PI a fully functional (and power efficient) computer running Linux for about 30€. You can get a TV stick running Android OS for about 50€ (there are Linux distributions for this kind of device). Linux is free, BSD OS family is free. Most of the SDKs are free. MySQL is free (as other fully capable Relational Database Systems). Many compilers are free. Open Office is free. Heck, even Adobe CS2 can be freely downloaded from Adobe…

Transit Price Drops

Also the price of bandwidth and networking has gone South over the years as the speed and quality has gone North. I remember to dial-up with a 28.8 kbps modem, downloading a single mp3 file was task for one hour, loading a simple webpage was eternity, etc… and in the end of the month the phone bill was obscene… Nowadays, i can download pristine high resolution full movie (in Itunes or other payed service of course) in less than an hour for a fraction of the cost that the mp3.

Documentation, tutorials, examples, e-books, howto’s all over the place. Information (for all levels) is freely available to anyone, you just need time and the right mindset, to read, test and educate yourself about any technology that you want to learn.

So in the web business capital is not the main factor, it’s knowledge and labor. The funny thing is that capitalism did this, an industry that moves billions of dollars and for start capital is not the most important factor (by far). Some kid can (and probably is) somewhere in some room build the next big website or mobile app costing him (or her) nothing more than time.

There is a bright future in this model. You don’t need some guys in suits that are sitting on top of the money to believe in your idea. You are the only one that needs to believe (can you picture the scared faces?) and learn, learn, learn:

Personally i wish i had much more time and piece of mind to learn and thinker with new technologies and projects because now is the time.

FreeBSD migrating user accounts

FreeBSDQuick and dirty way to migrate user accounts from one FreeBSD box to another. From the source box you will only need two files:

/etc/master.passwd
/etc/group

copy them to the target box, but DON’T overwrite (yet) the existing files there. Put them in /root/master.passwd and /root/group. Compare the copied files with the existing ones for new system users that may exist. If there are any new users/groups add them to the copied files.

Then move /root/group to /etc/group and run this magical command

pwd_mkdb -p /root/master.passwd

It will install in /etc/master.passd and recreate all the needed files (/etc/pwd.db, /etc/spwd.db and /etc/passwd).