1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* test/rss/test_xml-stylesheet.rb: added tests for xml-stylesheet.

* lib/rss/xml-stylesheet.rb: added xml-stylesheet parsing
  function.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5989 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
kou 2004-03-21 09:20:47 +00:00
parent 2639d6dc80
commit 7ead69e5b3
15 changed files with 385 additions and 85 deletions

View file

@ -10,6 +10,8 @@ module RSS
class Rss < Element
include RSS09
include RootElementMixin
include XMLStyleSheetMixin
[
["channel", nil],
@ -24,18 +26,9 @@ module RSS
attr_accessor :rss_version, :version, :encoding, :standalone
def initialize(rss_version, version=nil, encoding=nil, standalone=nil)
super()
@rss_version = rss_version
@version = version || '1.0'
@encoding = encoding
@standalone = standalone
super
end
def output_encoding=(enc)
@output_encoding = enc
self.converter = Converter.new(@output_encoding, @encoding)
end
def items
if @channel
@channel.items
@ -55,7 +48,7 @@ module RSS
def to_s(convert=true)
rv = <<-EOR
#{xmldecl}
<rss version="#{@rss_version}"#{ns_declaration}>
#{xml_stylesheet_pi}<rss version="#{@rss_version}"#{ns_declaration}>
#{channel_element(false)}
#{other_element(false, "\t")}
</rss>
@ -65,25 +58,6 @@ EOR
end
private
def xmldecl
rv = "<?xml version='#{@version}'"
if @output_encoding or @encoding
rv << " encoding='#{@output_encoding or @encoding}'"
end
rv << " standalone='#{@standalone}'" if @standalone
rv << '?>'
rv
end
def ns_declaration
rv = ''
NSPOOL.each do |prefix, uri|
prefix = ":#{prefix}" unless prefix.empty?
rv << %Q|\n\txmlns#{prefix}="#{uri}"|
end
rv
end
def children
[@channel]
end
@ -423,6 +397,7 @@ EOT
check_ns(tag_name, prefix, ns, nil)
@rss = Rss.new(attrs['version'], @version, @encoding, @standalone)
@rss.xml_stylesheets = @xml_stylesheets
@last_element = @rss
@proc_stack.push Proc.new { |text, tags|
@rss.validate_for_stream(tags) if @do_validate

View file

@ -10,6 +10,8 @@ module RSS
class RDF < Element
include RSS10
include RootElementMixin
include XMLStyleSheetMixin
class << self
@ -45,23 +47,13 @@ module RSS
attr_accessor :rss_version, :version, :encoding, :standalone
def initialize(version=nil, encoding=nil, standalone=nil)
super()
@rss_version = '1.0'
@version = version || '1.0'
@encoding = encoding
@standalone = standalone
@output_encoding = nil
end
def output_encoding=(enc)
@output_encoding = enc
self.converter = Converter.new(@output_encoding, @encoding)
super('1.0', version, encoding, standalone)
end
def to_s(convert=true)
rv = <<-EORDF
#{xmldecl}
<#{PREFIX}:RDF#{ns_declaration}>
#{xml_stylesheet_pi}<#{PREFIX}:RDF#{ns_declaration}>
#{channel_element(false)}
#{image_element(false)}
#{item_elements(false)}
@ -74,25 +66,6 @@ EORDF
end
private
def xmldecl
rv = %Q[<?xml version="#{@version}"]
if @output_encoding or @encoding
rv << %Q[ encoding="#{@output_encoding or @encoding}"]
end
rv << %Q[ standalone="#{@standalone}"] if @standalone
rv << '?>'
rv
end
def ns_declaration
rv = ''
self.class::NSPOOL.each do |prefix, uri|
prefix = ":#{prefix}" unless prefix.empty?
rv << %Q|\n\txmlns#{prefix}="#{html_escape(uri)}"|
end
rv
end
def rdf_validate(tags)
_validate(tags, [])
end
@ -647,4 +620,19 @@ EOT
BaseListener.install_get_text_element(x, URI, "#{x}=")
end
module ListenerMixin
private
def start_RDF(tag_name, prefix, attrs, ns)
check_ns(tag_name, prefix, ns, RDF::URI)
@rss = RDF.new(@version, @encoding, @standalone)
@rss.do_validate = @do_validate
@rss.xml_stylesheets = @xml_stylesheets
@last_element = @rss
@proc_stack.push Proc.new { |text, tags|
@rss.validate_for_stream(tags) if @do_validate
}
end
end
end

View file

@ -135,6 +135,7 @@ EOT
# check_ns(tag_name, prefix, ns, Rss::URI)
@rss = Rss.new(attrs['version'], @version, @encoding, @standalone)
@rss.xml_stylesheets = @xml_stylesheets
@last_element = @rss
@proc_stack.push Proc.new { |text, tags|
@rss.validate_for_stream(tags) if @do_validate

View file

@ -25,8 +25,8 @@ module RSS
value
end
def def_convert()
instance_eval(<<-EOC, *get_file_and_line_from_caller(0))
def def_convert(depth=0)
instance_eval(<<-EOC, *get_file_and_line_from_caller(depth))
def convert(value)
if value.kind_of?(String)
#{yield('value')}
@ -37,10 +37,10 @@ module RSS
EOC
end
def def_iconv_convert(to_enc, from_enc)
def def_iconv_convert(to_enc, from_enc, depth=0)
begin
require "iconv"
def_convert do |value|
def_convert(depth+1) do |value|
<<-EOC
@iconv ||= Iconv.new("#{to_enc}", "#{from_enc}")
begin
@ -68,7 +68,7 @@ module RSS
def def_uconv_convert_if_can(meth, to_enc, from_enc)
begin
require "uconv"
def_convert do |value|
def_convert(1) do |value|
<<-EOC
begin
Uconv.#{meth}(#{value})
@ -78,7 +78,7 @@ module RSS
EOC
end
rescue LoadError
def_iconv_convert(to_enc, from_enc)
def_iconv_convert(to_enc, from_enc, 1)
end
end

View file

@ -191,12 +191,22 @@ module RSS
@proc_stack = []
@last_element = nil
@version = @encoding = @standalone = nil
@xml_stylesheets = []
end
def xmldecl(version, encoding, standalone)
@version, @encoding, @standalone = version, encoding, standalone
end
def instruction(name, content)
if name == "xml-stylesheet"
params = parse_pi_content(content)
if params.has_key?("href")
@xml_stylesheets << XMLStyleSheet.new(*params)
end
end
end
def tag_start(name, attributes)
@text_stack.push('')
@ -204,7 +214,7 @@ module RSS
attrs = {}
attributes.each do |n, v|
if n =~ /\Axmlns:?/
ns[$'] = v # $' is post match
ns[$POSTMATCH] = v
else
attrs[n] = v
end
@ -238,15 +248,13 @@ module RSS
private
def start_RDF(tag_name, prefix, attrs, ns)
check_ns(tag_name, prefix, ns, RDF::URI)
@rss = RDF.new(@version, @encoding, @standalone)
@rss.do_validate = @do_validate
@last_element = @rss
@proc_stack.push Proc.new { |text, tags|
@rss.validate_for_stream(tags) if @do_validate
}
CONTENT_PATTERN = /\s*([^=]+)=(["'])([^\2]+?)\2/
def parse_pi_content(content)
params = {}
content.scan(CONTENT_PATTERN) do |name, quote, value|
params[name] = value
end
params
end
def start_else_element(local, prefix, attrs, ns)

View file

@ -1,7 +1,9 @@
require "time"
require "English"
require "rss/utils"
require "rss/converter"
require "rss/xml-stylesheet"
module RSS
@ -365,7 +367,6 @@ EOC
def initialize(do_validate=true)
@converter = nil
@output_encoding = nil
@do_validate = do_validate
initialize_variables
end
@ -561,4 +562,44 @@ EOC
end
module RootElementMixin
attr_reader :output_encoding
def initialize(rss_version, version=nil, encoding=nil, standalone=nil)
super()
@rss_version = rss_version
@version = version || '1.0'
@encoding = encoding
@standalone = standalone
@output_encoding = nil
end
def output_encoding=(enc)
@output_encoding = enc
self.converter = Converter.new(@output_encoding, @encoding)
end
private
def xmldecl
rv = %Q[<?xml version="#{@version}"]
if @output_encoding or @encoding
rv << %Q[ encoding="#{@output_encoding or @encoding}"]
end
rv << %Q[ standalone="#{@standalone}"] if @standalone
rv << '?>'
rv
end
def ns_declaration
rv = ''
self.class::NSPOOL.each do |prefix, uri|
prefix = ":#{prefix}" unless prefix.empty?
rv << %Q|\n\txmlns#{prefix}="#{html_escape(uri)}"|
end
rv
end
end
end

View file

@ -3,10 +3,8 @@ module RSS
module Utils
def get_file_and_line_from_caller(i=0)
tmp = caller[i].split(':')
line = tmp.pop.to_i
file = tmp.join(':')
[file, line]
file, line, = caller[i].split(':')
[file, line.to_i]
end
def html_escape(s)

94
lib/rss/xml-stylesheet.rb Normal file
View file

@ -0,0 +1,94 @@
require "rss/utils"
module RSS
module XMLStyleSheetMixin
attr_accessor :xml_stylesheets
def initialize(*args)
super
@xml_stylesheets = []
end
private
def xml_stylesheet_pi
xsss = @xml_stylesheets.collect do |xss|
pi = xss.to_s
pi = nil if /\A\s*\z/ =~ pi
pi
end.compact
xsss.push("") unless xsss.empty?
xsss.join("\n")
end
end
class XMLStyleSheet
include Utils
ATTRIBUTES = %w(href type title media charset alternate)
GUESS_TABLE = {
"xsl" => "text/xsl",
"css" => "text/css",
}
attr_accessor(*ATTRIBUTES)
attr_accessor(:do_validate)
def initialize(*attrs)
@do_validate = true
ATTRIBUTES.each do |attr|
self.send("#{attr}=", nil)
end
vars = ATTRIBUTES.dup
vars.unshift(:do_validate)
attrs.each do |name, value|
if vars.include?(name.to_s)
self.send("#{name}=", value)
end
end
end
def to_s
rv = ""
if @href
rv << %Q[<?xml-stylesheet]
ATTRIBUTES.each do |name|
if self.send(name)
rv << %Q[ #{name}="#{h self.send(name)}"]
end
end
rv << %Q[?>]
end
rv
end
remove_method(:href=)
def href=(value)
@href = value
if @href and @type.nil?
@type = guess_type(@href)
end
@href
end
remove_method(:alternate=)
def alternate=(value)
if value.nil? or /\A(?:yes|no)\z/ =~ value
@alternate = value
else
if @do_validate
args = ["?xml-stylesheet?", %Q[alternate="#{value}"]]
raise NotAvailableValueError.new(*args)
end
end
@alternate
end
private
def guess_type(filename)
/\.([^.]+)/ =~ filename
GUESS_TABLE[$1]
end
end
end

View file

@ -1,3 +1,9 @@
begin
require "xml/parser"
rescue LoadError
require "xmlparser"
end
begin
require "xml/encoding-ja"
rescue LoadError
@ -15,7 +21,7 @@ module RSS
class REXMLLikeXMLParser < ::XML::Parser
include XML::Encoding_ja
include ::XML::Encoding_ja
def listener=(listener)
@listener = listener
@ -37,6 +43,10 @@ module RSS
@listener.xmldecl(version, encoding, standalone == 1)
end
def processingInstruction(target, content)
@listener.instruction(target, content)
end
end
class XMLParserParser < BaseParser
@ -51,7 +61,7 @@ module RSS
parser = REXMLLikeXMLParser.new
parser.listener = @listener
parser.parse(@rss)
rescue XMLParserError => e
rescue ::XML::Parser::Error => e
raise NotWellFormedError.new(parser.line){e.message}
end
end

View file

@ -48,6 +48,7 @@ module RSS
xmldecl(@version, @encoding, @standalone)
end
alias_method(:on_pi, :instruction)
alias_method(:on_chardata, :text)
alias_method(:on_cdata, :text)