TITLE: Updating pypodd to run .opml files
DATE: 2018-04-07
AUTHOR: John L. Godlee
====================================================================


Pypodd

OPML (Outline Processor Markup Language) is a type of .xml which is 
often used to hold information for RSS feeds. Lots of podcast 
aggregators use the OPML format to allow exporting of your list of 
podcasts, including the one that I use on my phone, PocketCasts. So 
I wanted to extend the functionality of my pypodd program so that 
it would be able to use an OPML list of subscriptions instead of 
the .csv that I put together in a quite ad hoc manner when I was 
writing the program.

  [PocketCasts]: https://play.pocketcasts.com

Here is a sample of what an OPML file looks like:

    <?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
    <opml version="1.0">
      <head>
        <title>Pocket Casts Feeds</title>
      </head>
      <body>
        <outline text="feeds">
          <outline type="rss" text="Hospital Records Podcast" 
xmlUrl="http://podcast.hospitalrecords.com/HospitalRecordsPodcast.xm
l" />
          <outline type="rss" text="Slow Radio" 
xmlUrl="https://podcasts.files.bbci.co.uk/p05k5bq0.rss" />
          <outline type="rss" text="The Heart" 
xmlUrl="http://feeds.theheartradio.org/TheHeartRadio" />
          <outline type="rss" text="Gardeners' Question Time" 
xmlUrl="https://podcasts.files.bbci.co.uk/b006qp2f.rss" />
        </outline>
      </body>
    </opml>

I found that actually, thanks to a package that has already been 
written called listparser, adding this feature was REALLY REALLY 
EASY!

  [listparser]: https://pythonhosted.org/listparser/

I wrapped the existing .csv import method in an if else statement, 
saying that if the file extension was csv proceed with the .csv 
import method, but if the file extension was .xml, use the other 
import method. The code looks like this:

    if subsLoc.endswith("csv"): 
      with open(subsLoc) as f:
        subs = csv.reader(f)
        subs = list(subs)
      # Split subs into URLs and titles
      urlList = [x[0] for x in subs]    
      subList = [x[1] for x in subs]
    elif subsLoc.endswith("xml"):
      with open(subsLoc) as f:
        subs = listparser.parse(f)
      urlList = [x.url for x in subs.feeds]
      subList = [x.title for x in subs.feeds] 
    else: 
      raw_input("Subscriptions list is not `.csv` or OPML `.xml`, 
exiting ...")
      sys.exit(0)

Also note the "quit" if the designated file doesn't include either 
of the two specified extensions. Maybe to be super bulletproof I 
should do a check to see if the .xml file includes <opml 
version="">, as I suppose there are lots of different .xml formats.