#!/usr/bin/perl ####################################################################### # $Id: opml2snow 1083 2005-06-05 09:56:01Z kiza $ # # Snownews - A lightweight console RSS newsreader # # Copyright 2003-2004 Oliver Feiler # http://kiza.kcore.de/software/snownews/ # # opml2snow # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ####################################################################### use strict; use XML::LibXML; use Data::Dumper; use English; ####################################################################### # Help if (index($ARGV[0], "-h") >= 0) { print "Snownews opml2snow - subsription file import/export utility\n\n". "Creative usage examples:\n". "Importing an OPML file:\n". " opml2snow urls\n". " opml2snow list.opml >urls\n". " cat list.opml | opml2snow >urls\n\n". "Exporting to OPML:\n". " opml2snow --export [urls file] >MySubscriptions.opml\n". " Alternatively you may run snow2opml [urls file] >file.opml\n\n". "The program will print to stdout by default. If you want to append the output\n". "to your subsription list, redirect to >>~/.snownews/url instead.\n"; exit (0); } ####################################################################### # Importing if (($PROGRAM_NAME =~ "snow2opml") || ($ARGV[0] eq "--export")) { OPMLexport(); } else { my $parser = XML::LibXML->new(); $parser->validation(0); # Turn off validation from libxml $parser->recover(1); # And ignore any errors while parsing my(@lines) = <>; my($input) = join ("\n", @lines); my($doc) = $parser->parse_string($input); my($root) = $doc->documentElement(); # Parsing the document tree using xpath my(@items) = $root->findnodes("//outline"); foreach (@items) { my(@attrs) = $_->attributes(); foreach (@attrs) { # Only print attribute xmlUrl="" if ($_->nodeName =~ /xmlUrl/i) { print $_->value."\n"; } } } } ####################################################################### # Exporting sub OPMLexport { my($inputfile); if (defined($ARGV[1])) { $inputfile = $ARGV[1]; } else { $inputfile = "$ENV{'HOME'}/.snownews/urls" } open (URLS, "$inputfile"); my(@urls) = ; close (URLS); if (scalar(@urls) == 0) { print "Could not read anything from \"$inputfile\"!\nExiting.\n"; exit(1); } # Create bare OPML doc my($opml) = XML::LibXML::Document->new(); my($opml_root) = $opml->createElement('opml'); $opml->setDocumentElement($opml_root); my($opml_comment) = $opml->createComment(' File generated by opml2snow '); $opml_root->appendChild($opml_comment); my($opml_head) = $opml->createElement('head'); $opml_root->appendChild($opml_head); $opml_head->appendTextChild('title', 'MySubscriptions'); my($opml_body) = $opml->createElement('body'); $opml_root->appendChild($opml_body); foreach(@urls) { chomp; /^(.*)?\|(.*?)\|(.*?)\|(.*)$/; my($feed_url) = $1; my($feed_url_hash) = $feed_url; $feed_url_hash =~ tr/\//_/; if ($feed_url_hash =~ /^smartfeed/) { next; } my($feed_override_title) = $2; my($feed_category) = $3; my($feed_script) = 4; my($parser) = XML::LibXML->new(); my($feed_doc) = $parser->parse_file("$ENV{'HOME'}/.snownews/cache/$feed_url_hash"); my($feed_root) = $feed_doc->documentElement(); $feed_root->setNamespace('http://purl.org/rss/1.0/', 'rss', 1); # Make outline element. Actually I have absolutely no idea how # this should look like. I copied the layout from an OPML file # produced by NetNewsWire. The OPML "spec" is supposed to be at: # http://www.opml.org/spec my($opml_outline) = $opml->createElement('outline'); $opml_outline->setAttribute('text', $feed_root->findvalue('//rss:channel/rss:title')); $opml_outline->setAttribute('title', $feed_root->findvalue('//rss:channel/rss:title')); $opml_outline->setAttribute('description', $feed_root->findvalue('//rss:channel/rss:description')); $opml_outline->setAttribute('type', 'rss'); $opml_outline->setAttribute('version', 'RSS'); $opml_outline->setAttribute('htmlUrl', $feed_root->findvalue('/rss:channel/rss:link')); $opml_outline->setAttribute('xmlUrl', "$feed_url"); $opml_body->appendChild($opml_outline); } print $opml->serialize(1); }