Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial import from Amethyst codebase w/ necessary changes to stand a…

…lone.
  • Loading branch information...
commit a7fc439fe97b45748beb9f2129184f71b17e7496 0 parents
@AustinBlues authored
4 .gitignore
@@ -0,0 +1,4 @@
+*.gem
+.bundle
+Gemfile.lock
+pkg/*
4 Gemfile
@@ -0,0 +1,4 @@
+source "http://rubygems.org"
+
+# Specify your gem's dependencies in opml_speed_reader.gemspec
+gemspec
2  Rakefile
@@ -0,0 +1,2 @@
+require 'bundler'
+Bundler::GemHelper.install_tasks
93 lib/opml_speed_reader.rb
@@ -0,0 +1,93 @@
+#require 'libxml-ruby'
+require 'xml'
+require 'opml_speed_reader/version'
+
+
+module OpmlSpeedReader
+ #TRACE = [:all_elements]
+ TRACE = []
+
+ def OpmlSpeedReader.parse_header(reader, stack)
+ title = nil
+
+ begin
+ status = reader.read
+ rescue
+ return title
+ end
+
+ while status
+ case reader.node_type
+ when XML::Reader::TYPE_ELEMENT
+ stack << reader.name
+ path = stack.join('/')
+ ignore = false
+ case path
+ when 'opml/body'
+ break # end of header
+ else
+ ignore = true
+ end
+ if (OpmlSpeedReader::TRACE.include?(:essential_elements) && !ignore) ||
+ OpmlSpeedReader::TRACE.include?(:all_elements)
+ puts "HEADER(#{path})"
+ end
+ stack.pop if reader.empty_element?
+ when XML::Reader::TYPE_TEXT, XML::Reader::TYPE_CDATA
+ path = stack.join('/')
+ ignore = false
+ case path
+ when 'opml/head/title'
+ title = reader.value.strip
+ end
+ if (OpmlSpeedReader::TRACE.include?(:essential_values) && !ignore) ||
+ OpmlSpeedReader::TRACE.include?(:all_values)
+ puts "HEADER(#{path}): #{reader.value}"
+ end
+ when XML::Reader::TYPE_END_ELEMENT
+ stack.pop
+ end
+ status = reader.read
+ end
+ title
+ end
+
+
+ def self.parse_body(reader, stack)
+ libxml = {} # force scope
+ begin # post test loop
+ case reader.node_type
+ when XML::Reader::TYPE_ELEMENT
+ stack << reader.name
+ path = stack.join('/')
+ ignore = false
+ case path
+ when %r|opml/body(/outline)+|
+ libxml['title'] = reader['text'].strip
+ libxml['url'] = reader['xmlUrl'].strip if reader['xmlUrl']
+ if reader.empty_element? && libxml['url']
+ yield libxml
+ libxml = {}
+ end
+ else
+ ignore = true
+ end
+ if (OpmlSpeedReader::TRACE.include?(:essential_elements) && !ignore) ||
+ OpmlSpeedReader::TRACE.include?(:all_elements)
+ puts "BEGIN(#{path}): '#{libxml['title']}' '#{libxml['url']}'."
+ end
+ stack.pop if reader.empty_element?
+ when XML::Reader::TYPE_END_ELEMENT
+ path = stack.join('/')
+ case path
+ when %r|opml/body(/outline)+|
+ if libxml['url']
+ yield libxml
+ libxml = {}
+ end
+ end
+ stack.pop
+ end
+ end while reader.read
+ end
+end
3  lib/opml_speed_reader/version.rb
@@ -0,0 +1,3 @@
+module OpmlSpeedReader
+ VERSION = "0.0.1"
+end
23 opml_speed_reader.gemspec
@@ -0,0 +1,23 @@
+# -*- encoding: utf-8 -*-
+$:.push File.expand_path("../lib", __FILE__)
+require "opml_speed_reader/version"
+
+Gem::Specification.new do |s|
+ s.name = "opml_speed_reader"
+ s.version = OpmlSpeedReader::VERSION
+ s.platform = Gem::Platform::RUBY
+ s.authors = ["Jeffrey L. Taylor"]
+ s.email = ["jeff.taylor@ieee.org"]
+ s.homepage = ""
+ s.summary = %q{Fast OPML parser}
+ s.description = %q{Fast parsing of an OPML file using libxml-ruby wrapper around libxml.}
+ s.add_dependency('libxml-ruby', '~> 1.1.0')
+# s.add_development_dependency('test-unit')
+
+ s.rubyforge_project = "opml_speed_reader"
+
+ s.files = `git ls-files`.split("\n")
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
+ s.require_paths = ["lib"]
+end
11 test/opml/Thunderbird.xml
@@ -0,0 +1,11 @@
+<opml version="1.0">
+ <head>
+ <title>Forumzilla OPML Export</title>
+ <dateCreated>Fri, 06 Nov 2009 00:18:02 GMT</dateCreated>
+ </head>
+ <body>
+ <outline text="Distributing the Future" xmlUrl="test/opml/DistributingTheFuture.xml"/>
+ <outline text="Forums: Message List - Developer Tools" xmlUrl="test/opml/AmazonDeveloperTools.xml"/>
+ <outline text="The Roadhouse" xmlUrl="test/opml/TheRoadhouse.xml"/>
+ </body>
+</opml>
9 test/opml/Thunderbird.yml
@@ -0,0 +1,9 @@
+---
+title: Forumzilla OPML Export
+:items:
+- :title: Distributing the Future
+ :url: "test/opml/DistributingTheFuture.xml"
+- :title: 'Forums: Message List - Developer Tools'
+ :url: "test/opml/AmazonDeveloperTools.xml"
+- :title: The Roadhouse
+ :url: "test/opml/TheRoadhouse.xml"
22 test/opml/UserLandFrontier.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!-- OPML generated by UserLand Frontier v9.0 on Fri, 23 Jul 2004 23:41:33 GMT -->
+<opml version="1.1">
+ <head>
+ <title>ourFavoriteFeedsData.top100</title>
+ <dateCreated>Fri, 02 Jan 2004 12:59:58 GMT</dateCreated>
+ <dateModified>Fri, 23 Jul 2004 23:41:32 GMT</dateModified>
+ <ownerName>Dave Winer</ownerName>
+ <ownerEmail>dave@userland.com</ownerEmail>
+ <expansionState></expansionState>
+ <vertScrollState>1</vertScrollState>
+ <windowTop>20</windowTop>
+ <windowLeft>0</windowLeft>
+ <windowBottom>120</windowBottom>
+ <windowRight>147</windowRight>
+ </head>
+ <body>
+ <outline text="Scripting News" count="580" xmlUrl="test/opml/ScriptingNews.xml"/>
+ <outline text="Wired News" count="546" xmlUrl="test/opml/WiredNews.xml"/>
+ <outline text="Boing Boing Blog" count="519" xmlUrl="test/opml/BoingBoing.xml"/>
+ </body>
+</opml>
9 test/opml/UserLandFrontier.yml
@@ -0,0 +1,9 @@
+---
+title: ourFavoriteFeedsData.top100
+:items:
+- :title: Scripting News
+ :url: "test/opml/ScriptingNews.xml"
+- :title: Wired News
+ :url: "test/opml/WiredNews.xml"
+- :title: Boing Boing Blog
+ :url: "test/opml/BoingBoing.xml"
58 test/test_suite.rb
@@ -0,0 +1,58 @@
+#! /usr/bin/ruby
+#
+require 'test/unit'
+require 'xml'
+require 'opml_speed_reader'
+
+
+class TestOpml < Test::Unit::TestCase
+ def test_parsing
+ Dir['./test/opml/*.yml'].each do |filename|
+# puts "FILE: #{filename}."
+ expected = YAML::load( File.open( filename ) )
+ io = open(filename.gsub(/\.yml\Z/, '.xml'))
+ reader = XML::Reader.io(io)
+ opml = fetch(reader)
+# puts "ACTUAL: #{opml[:feeds].inspect}."
+# puts "ACTUAL: #{opml[:feeds].map{|a| "'#{a.title}'"}.join(", ")}."
+# puts "DETAILS: #{opml[:details].inspect}."
+ expected[:items].each do |item|
+# puts "ITEM: |#{item.inspect}|"
+ item[:title].gsub!(/&#x([0-9a-f]+);/i){ [$1.hex].pack("U*")}
+ a = opml[:feeds].detect{|i| item[:title] == i['title']}
+# a = opml.detect{|i| item[:title] == i.title}
+ if a.nil?
+ puts "MISSING EXPECTED: '#{item[:title]}'."
+ else
+ assert item[:title] == a['title'], "ITEM TITLE: '#{a['title']}' vs. '#{item[:title]}'."
+ assert a['url'] == item[:url], "ITEM URL: '#{a['url']}' vs. '#{item[:url]}'."
+
+ opml[:feeds].delete(a)
+ end
+ end
+# puts "OPML: |#{opml[:feeds].inspect}|"
+ assert(opml[:feeds].empty?,
+ "#{opml[:feeds].length} channels expected in #{filename.gsub(%r{.*/}, '')} not found.")
+ end
+ end
+
+
+ def fetch(reader)
+ title = ''
+# details = []
+ feeds = []
+ stack = []
+
+ begin
+ title = OpmlSpeedReader.parse_header(reader, stack)
+
+ stack.pop
+
+ OpmlSpeedReader.parse_body(reader, stack) do |libxml|
+ feeds << libxml
+ end
+
+ {:title => title, :feeds => feeds}
+ end
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.