From 6175ca03be6d0d51359f9017123708987d0f5eb7 Mon Sep 17 00:00:00 2001 From: shyouhei Date: Wed, 15 Aug 2007 23:23:39 +0000 Subject: add tag v1_8_5_91 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/tags/v1_8_5_91@13046 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ruby_1_8_5/lib/xsd/charset.rb | 187 ++++ ruby_1_8_5/lib/xsd/codegen.rb | 12 + ruby_1_8_5/lib/xsd/codegen/classdef.rb | 203 +++++ ruby_1_8_5/lib/xsd/codegen/commentdef.rb | 34 + ruby_1_8_5/lib/xsd/codegen/gensupport.rb | 166 ++++ ruby_1_8_5/lib/xsd/codegen/methoddef.rb | 63 ++ ruby_1_8_5/lib/xsd/codegen/moduledef.rb | 191 ++++ ruby_1_8_5/lib/xsd/datatypes.rb | 1269 +++++++++++++++++++++++++++ ruby_1_8_5/lib/xsd/datatypes1999.rb | 20 + ruby_1_8_5/lib/xsd/iconvcharset.rb | 33 + ruby_1_8_5/lib/xsd/mapping.rb | 42 + ruby_1_8_5/lib/xsd/namedelements.rb | 95 ++ ruby_1_8_5/lib/xsd/ns.rb | 140 +++ ruby_1_8_5/lib/xsd/qname.rb | 78 ++ ruby_1_8_5/lib/xsd/xmlparser.rb | 61 ++ ruby_1_8_5/lib/xsd/xmlparser/parser.rb | 96 ++ ruby_1_8_5/lib/xsd/xmlparser/rexmlparser.rb | 54 ++ ruby_1_8_5/lib/xsd/xmlparser/xmlparser.rb | 50 ++ ruby_1_8_5/lib/xsd/xmlparser/xmlscanner.rb | 147 ++++ 19 files changed, 2941 insertions(+) create mode 100644 ruby_1_8_5/lib/xsd/charset.rb create mode 100644 ruby_1_8_5/lib/xsd/codegen.rb create mode 100644 ruby_1_8_5/lib/xsd/codegen/classdef.rb create mode 100644 ruby_1_8_5/lib/xsd/codegen/commentdef.rb create mode 100644 ruby_1_8_5/lib/xsd/codegen/gensupport.rb create mode 100644 ruby_1_8_5/lib/xsd/codegen/methoddef.rb create mode 100644 ruby_1_8_5/lib/xsd/codegen/moduledef.rb create mode 100644 ruby_1_8_5/lib/xsd/datatypes.rb create mode 100644 ruby_1_8_5/lib/xsd/datatypes1999.rb create mode 100644 ruby_1_8_5/lib/xsd/iconvcharset.rb create mode 100644 ruby_1_8_5/lib/xsd/mapping.rb create mode 100644 ruby_1_8_5/lib/xsd/namedelements.rb create mode 100644 ruby_1_8_5/lib/xsd/ns.rb create mode 100644 ruby_1_8_5/lib/xsd/qname.rb create mode 100644 ruby_1_8_5/lib/xsd/xmlparser.rb create mode 100644 ruby_1_8_5/lib/xsd/xmlparser/parser.rb create mode 100644 ruby_1_8_5/lib/xsd/xmlparser/rexmlparser.rb create mode 100644 ruby_1_8_5/lib/xsd/xmlparser/xmlparser.rb create mode 100644 ruby_1_8_5/lib/xsd/xmlparser/xmlscanner.rb (limited to 'ruby_1_8_5/lib/xsd') diff --git a/ruby_1_8_5/lib/xsd/charset.rb b/ruby_1_8_5/lib/xsd/charset.rb new file mode 100644 index 0000000000..15d5500fce --- /dev/null +++ b/ruby_1_8_5/lib/xsd/charset.rb @@ -0,0 +1,187 @@ +# XSD4R - Charset handling library. +# Copyright (C) 2001, 2003, 2005 NAKAMURA, Hiroshi . + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +module XSD + + +module Charset + @internal_encoding = $KCODE + + class XSDError < StandardError; end + class CharsetError < XSDError; end + class UnknownCharsetError < CharsetError; end + class CharsetConversionError < CharsetError; end + +public + + ### + ## Maps + # + EncodingConvertMap = {} + def Charset.init + EncodingConvertMap[['UTF8', 'X_ISO8859_1']] = + Proc.new { |str| str.unpack('U*').pack('C*') } + EncodingConvertMap[['X_ISO8859_1', 'UTF8']] = + Proc.new { |str| str.unpack('C*').pack('U*') } + begin + require 'xsd/iconvcharset' + @internal_encoding = 'UTF8' + sjtag = (/(mswin|bccwin|mingw|cygwin|emx)/ =~ RUBY_PLATFORM) ? 'cp932' : + 'shift_jis' + EncodingConvertMap[['UTF8', 'EUC' ]] = + Proc.new { |str| IconvCharset.safe_iconv("euc-jp", "utf-8", str) } + EncodingConvertMap[['EUC' , 'UTF8']] = + Proc.new { |str| IconvCharset.safe_iconv("utf-8", "euc-jp", str) } + EncodingConvertMap[['EUC' , 'SJIS']] = + Proc.new { |str| IconvCharset.safe_iconv(sjtag, "euc-jp", str) } + EncodingConvertMap[['UTF8', 'SJIS']] = + Proc.new { |str| IconvCharset.safe_iconv(sjtag, "utf-8", str) } + EncodingConvertMap[['SJIS', 'UTF8']] = + Proc.new { |str| IconvCharset.safe_iconv("utf-8", sjtag, str) } + EncodingConvertMap[['SJIS', 'EUC' ]] = + Proc.new { |str| IconvCharset.safe_iconv("euc-jp", sjtag, str) } + rescue LoadError + begin + require 'nkf' + EncodingConvertMap[['EUC' , 'SJIS']] = + Proc.new { |str| NKF.nkf('-sXm0', str) } + EncodingConvertMap[['SJIS', 'EUC' ]] = + Proc.new { |str| NKF.nkf('-eXm0', str) } + rescue LoadError + end + + begin + require 'uconv' + @internal_encoding = 'UTF8' + EncodingConvertMap[['UTF8', 'EUC' ]] = Uconv.method(:u8toeuc) + EncodingConvertMap[['UTF8', 'SJIS']] = Uconv.method(:u8tosjis) + EncodingConvertMap[['EUC' , 'UTF8']] = Uconv.method(:euctou8) + EncodingConvertMap[['SJIS', 'UTF8']] = Uconv.method(:sjistou8) + rescue LoadError + end + end + end + self.init + + CharsetMap = { + 'NONE' => 'us-ascii', + 'EUC' => 'euc-jp', + 'SJIS' => 'shift_jis', + 'UTF8' => 'utf-8', + 'X_ISO_8859_1' => 'iso-8859-1', + 'X_UNKNOWN' => nil, + } + + + ### + ## handlers + # + def Charset.encoding + @internal_encoding + end + + def Charset.encoding=(encoding) + warn("xsd charset is set to #{encoding}") if $DEBUG + @internal_encoding = encoding + end + + def Charset.xml_encoding_label + charset_label(@internal_encoding) + end + + def Charset.encoding_to_xml(str, charset) + encoding_conv(str, @internal_encoding, charset_str(charset)) + end + + def Charset.encoding_from_xml(str, charset) + encoding_conv(str, charset_str(charset), @internal_encoding) + end + + def Charset.encoding_conv(str, enc_from, enc_to) + if enc_from == enc_to or enc_from == 'NONE' or enc_to == 'NONE' + str + elsif converter = EncodingConvertMap[[enc_from, enc_to]] + converter.call(str) + else + raise CharsetConversionError.new( + "Converter not found: #{enc_from} -> #{enc_to}") + end + end + + def Charset.charset_label(encoding) + CharsetMap[encoding.upcase] + end + + def Charset.charset_str(label) + if CharsetMap.respond_to?(:key) + CharsetMap.key(label.downcase) || 'X_UNKNOWN' + else + CharsetMap.index(label.downcase) || 'X_UNKNOWN' + end + end + + # us_ascii = '[\x00-\x7F]' + us_ascii = '[\x9\xa\xd\x20-\x7F]' # XML 1.0 restricted. + USASCIIRegexp = Regexp.new("\\A#{us_ascii}*\\z", nil, "NONE") + + twobytes_euc = '(?:[\x8E\xA1-\xFE][\xA1-\xFE])' + threebytes_euc = '(?:\x8F[\xA1-\xFE][\xA1-\xFE])' + character_euc = "(?:#{us_ascii}|#{twobytes_euc}|#{threebytes_euc})" + EUCRegexp = Regexp.new("\\A#{character_euc}*\\z", nil, "NONE") + + # onebyte_sjis = '[\x00-\x7F\xA1-\xDF]' + onebyte_sjis = '[\x9\xa\xd\x20-\x7F\xA1-\xDF]' # XML 1.0 restricted. + twobytes_sjis = '(?:[\x81-\x9F\xE0-\xFC][\x40-\x7E\x80-\xFC])' + character_sjis = "(?:#{onebyte_sjis}|#{twobytes_sjis})" + SJISRegexp = Regexp.new("\\A#{character_sjis}*\\z", nil, "NONE") + + # 0xxxxxxx + # 110yyyyy 10xxxxxx + twobytes_utf8 = '(?:[\xC0-\xDF][\x80-\xBF])' + # 1110zzzz 10yyyyyy 10xxxxxx + threebytes_utf8 = '(?:[\xE0-\xEF][\x80-\xBF][\x80-\xBF])' + # 11110uuu 10uuuzzz 10yyyyyy 10xxxxxx + fourbytes_utf8 = '(?:[\xF0-\xF7][\x80-\xBF][\x80-\xBF][\x80-\xBF])' + character_utf8 = + "(?:#{us_ascii}|#{twobytes_utf8}|#{threebytes_utf8}|#{fourbytes_utf8})" + UTF8Regexp = Regexp.new("\\A#{character_utf8}*\\z", nil, "NONE") + + def Charset.is_us_ascii(str) + USASCIIRegexp =~ str + end + + def Charset.is_utf8(str) + UTF8Regexp =~ str + end + + def Charset.is_euc(str) + EUCRegexp =~ str + end + + def Charset.is_sjis(str) + SJISRegexp =~ str + end + + def Charset.is_ces(str, code = $KCODE) + case code + when 'NONE' + is_us_ascii(str) + when 'UTF8' + is_utf8(str) + when 'EUC' + is_euc(str) + when 'SJIS' + is_sjis(str) + else + raise UnknownCharsetError.new("Unknown charset: #{code}") + end + end +end + + +end diff --git a/ruby_1_8_5/lib/xsd/codegen.rb b/ruby_1_8_5/lib/xsd/codegen.rb new file mode 100644 index 0000000000..d820ebf1f2 --- /dev/null +++ b/ruby_1_8_5/lib/xsd/codegen.rb @@ -0,0 +1,12 @@ +# XSD4R - Generating code library +# Copyright (C) 2004 NAKAMURA, Hiroshi . + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'xsd/codegen/gensupport' +require 'xsd/codegen/moduledef' +require 'xsd/codegen/classdef' +require 'xsd/codegen/methoddef' diff --git a/ruby_1_8_5/lib/xsd/codegen/classdef.rb b/ruby_1_8_5/lib/xsd/codegen/classdef.rb new file mode 100644 index 0000000000..9eb1ce6607 --- /dev/null +++ b/ruby_1_8_5/lib/xsd/codegen/classdef.rb @@ -0,0 +1,203 @@ +# XSD4R - Generating class definition code +# Copyright (C) 2004 NAKAMURA, Hiroshi . + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'xsd/codegen/gensupport' +require 'xsd/codegen/moduledef' +require 'xsd/codegen/methoddef' + + +module XSD +module CodeGen + + +class ClassDef < ModuleDef + include GenSupport + + def initialize(name, baseclass = nil) + super(name) + @baseclass = baseclass + @classvar = [] + @attrdef = [] + end + + def def_classvar(var, value) + var = var.sub(/\A@@/, "") + unless safevarname?(var) + raise ArgumentError.new("#{var} seems to be unsafe") + end + @classvar << [var, value] + end + + def def_attr(attrname, writable = true, varname = nil) + unless safevarname?(varname || attrname) + raise ArgumentError.new("#{varname || attrname} seems to be unsafe") + end + @attrdef << [attrname, writable, varname] + end + + def dump + buf = "" + unless @requirepath.empty? + buf << dump_requirepath + end + buf << dump_emptyline unless buf.empty? + package = @name.split(/::/)[0..-2] + buf << dump_package_def(package) unless package.empty? + buf << dump_comment if @comment + buf << dump_class_def + spacer = false + unless @classvar.empty? + spacer = true + buf << dump_classvar + end + unless @const.empty? + buf << dump_emptyline if spacer + spacer = true + buf << dump_const + end + unless @code.empty? + buf << dump_emptyline if spacer + spacer = true + buf << dump_code + end + unless @attrdef.empty? + buf << dump_emptyline if spacer + spacer = true + buf << dump_attributes + end + unless @methoddef.empty? + buf << dump_emptyline if spacer + spacer = true + buf << dump_methods + end + buf << dump_class_def_end + buf << dump_package_def_end(package) unless package.empty? + buf.gsub(/^\s+$/, '') + end + +private + + def dump_class_def + name = @name.to_s.split(/::/) + if @baseclass + format("class #{name.last} < #{@baseclass}") + else + format("class #{name.last}") + end + end + + def dump_class_def_end + str = format("end") + end + + def dump_classvar + dump_static( + @classvar.collect { |var, value| + %Q(@@#{var.sub(/^@@/, "")} = #{dump_value(value)}) + }.join("\n") + ) + end + + def dump_attributes + str = "" + @attrdef.each do |attrname, writable, varname| + varname ||= attrname + if attrname == varname + str << format(dump_accessor(attrname, writable), 2) + end + end + @attrdef.each do |attrname, writable, varname| + varname ||= attrname + if attrname != varname + str << "\n" unless str.empty? + str << format(dump_attribute(attrname, writable, varname), 2) + end + end + str + end + + def dump_accessor(attrname, writable) + if writable + "attr_accessor :#{attrname}" + else + "attr_reader :#{attrname}" + end + end + + def dump_attribute(attrname, writable, varname) + str = nil + mr = MethodDef.new(attrname) + mr.definition = "@#{varname}" + str = mr.dump + if writable + mw = MethodDef.new(attrname + "=", 'value') + mw.definition = "@#{varname} = value" + str << "\n" + mw.dump + end + str + end +end + + +end +end + + +if __FILE__ == $0 + require 'xsd/codegen/classdef' + include XSD::CodeGen + c = ClassDef.new("Foo::Bar::HobbitName", String) + c.def_require("foo/bar") + c.comment = <<-EOD + foo + bar + baz + EOD + c.def_const("FOO", 1) + c.def_classvar("@@foo", "var".dump) + c.def_classvar("baz", "1".dump) + c.def_attr("Foo", true, "foo") + c.def_attr("bar") + c.def_attr("baz", true) + c.def_attr("Foo2", true, "foo2") + c.def_attr("foo3", false, "foo3") + c.def_method("foo") do + <<-EOD + foo.bar = 1 +\tbaz.each do |ele| +\t ele + end + EOD + end + c.def_method("baz", "qux") do + <<-EOD + [1, 2, 3].each do |i| + p i + end + EOD + end + + m = MethodDef.new("qux", "quxx", "quxxx") do + <<-EOD + p quxx + quxxx + EOD + end + m.comment = "hello world\n123" + c.add_method(m) + c.def_code <<-EOD + Foo.new + Bar.z + EOD + c.def_code <<-EOD + Foo.new + Bar.z + EOD + c.def_privatemethod("foo", "baz", "*arg", "&block") + + puts c.dump +end diff --git a/ruby_1_8_5/lib/xsd/codegen/commentdef.rb b/ruby_1_8_5/lib/xsd/codegen/commentdef.rb new file mode 100644 index 0000000000..c9493a1363 --- /dev/null +++ b/ruby_1_8_5/lib/xsd/codegen/commentdef.rb @@ -0,0 +1,34 @@ +# XSD4R - Generating comment definition code +# Copyright (C) 2004 NAKAMURA, Hiroshi . + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'xsd/codegen/gensupport' + + +module XSD +module CodeGen + + +module CommentDef + include GenSupport + + attr_accessor :comment + +private + + def dump_comment + if /\A#/ =~ @comment + format(@comment) + else + format(@comment).gsub(/^/, '# ') + end + end +end + + +end +end diff --git a/ruby_1_8_5/lib/xsd/codegen/gensupport.rb b/ruby_1_8_5/lib/xsd/codegen/gensupport.rb new file mode 100644 index 0000000000..1e85d3668f --- /dev/null +++ b/ruby_1_8_5/lib/xsd/codegen/gensupport.rb @@ -0,0 +1,166 @@ +# XSD4R - Code generation support +# Copyright (C) 2004, 2005 NAKAMURA, Hiroshi . + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +module XSD +module CodeGen + +# from the file 'keywords' in 1.9. +KEYWORD = {} +%w( +__LINE__ +__FILE__ +BEGIN +END +alias +and +begin +break +case +class +def +defined? +do +else +elsif +end +ensure +false +for +if +in +module +next +nil +not +or +redo +rescue +retry +return +self +super +then +true +undef +unless +until +when +while +yield +).each { |k| KEYWORD[k] = nil } + +module GenSupport + def capitalize(target) + target.sub(/^([a-z])/) { $1.tr!('[a-z]', '[A-Z]') } + end + module_function :capitalize + + def uncapitalize(target) + target.sub(/^([A-Z])/) { $1.tr!('[A-Z]', '[a-z]') } + end + module_function :uncapitalize + + def safeconstname(name) + safename = name.scan(/[a-zA-Z0-9_]+/).collect { |ele| + GenSupport.capitalize(ele) + }.join + if /^[A-Z]/ !~ safename or keyword?(safename) + safename = "C_#{safename}" + end + safename + end + module_function :safeconstname + + def safeconstname?(name) + /\A[A-Z][a-zA-Z0-9_]*\z/ =~ name and !keyword?(name) + end + module_function :safeconstname? + + def safemethodname(name) + safename = name.scan(/[a-zA-Z0-9_]+/).join('_') + safename = uncapitalize(safename) + if /^[a-z]/ !~ safename + safename = "m_#{safename}" + end + safename + end + module_function :safemethodname + + def safemethodname?(name) + /\A[a-zA-Z_][a-zA-Z0-9_]*[=!?]?\z/ =~ name + end + module_function :safemethodname? + + def safevarname(name) + safename = uncapitalize(name.scan(/[a-zA-Z0-9_]+/).join('_')) + if /^[a-z]/ !~ safename or keyword?(safename) + "v_#{safename}" + else + safename + end + end + module_function :safevarname + + def safevarname?(name) + /\A[a-z_][a-zA-Z0-9_]*\z/ =~ name and !keyword?(name) + end + module_function :safevarname? + + def keyword?(word) + KEYWORD.key?(word) + end + module_function :keyword? + + def format(str, indent = nil) + str = trim_eol(str) + str = trim_indent(str) + if indent + str.gsub(/^/, " " * indent) + else + str + end + end + +private + + def trim_eol(str) + str.collect { |line| + line.sub(/\r?\n\z/, "") + "\n" + }.join + end + + def trim_indent(str) + indent = nil + str = str.collect { |line| untab(line) }.join + str.each do |line| + head = line.index(/\S/) + if !head.nil? and (indent.nil? or head < indent) + indent = head + end + end + return str unless indent + str.collect { |line| + line.sub(/^ {0,#{indent}}/, "") + }.join + end + + def untab(line, ts = 8) + while pos = line.index(/\t/) + line = line.sub(/\t/, " " * (ts - (pos % ts))) + end + line + end + + def dump_emptyline + "\n" + end +end + + +end +end diff --git a/ruby_1_8_5/lib/xsd/codegen/methoddef.rb b/ruby_1_8_5/lib/xsd/codegen/methoddef.rb new file mode 100644 index 0000000000..15892fc5bf --- /dev/null +++ b/ruby_1_8_5/lib/xsd/codegen/methoddef.rb @@ -0,0 +1,63 @@ +# XSD4R - Generating method definition code +# Copyright (C) 2004 NAKAMURA, Hiroshi . + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'xsd/codegen/gensupport' +require 'xsd/codegen/commentdef' + + +module XSD +module CodeGen + + +class MethodDef + include GenSupport + include CommentDef + + attr_accessor :definition + + def initialize(name, *params) + unless safemethodname?(name) + raise ArgumentError.new("name '#{name}' seems to be unsafe") + end + @name = name + @params = params + @comment = nil + @definition = yield if block_given? + end + + def dump + buf = "" + buf << dump_comment if @comment + buf << dump_method_def + buf << dump_definition if @definition and !@definition.empty? + buf << dump_method_def_end + buf + end + +private + + def dump_method_def + if @params.empty? + format("def #{@name}") + else + format("def #{@name}(#{@params.join(", ")})") + end + end + + def dump_method_def_end + format("end") + end + + def dump_definition + format(@definition, 2) + end +end + + +end +end diff --git a/ruby_1_8_5/lib/xsd/codegen/moduledef.rb b/ruby_1_8_5/lib/xsd/codegen/moduledef.rb new file mode 100644 index 0000000000..744af2ff97 --- /dev/null +++ b/ruby_1_8_5/lib/xsd/codegen/moduledef.rb @@ -0,0 +1,191 @@ +# XSD4R - Generating module definition code +# Copyright (C) 2004 NAKAMURA, Hiroshi . + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'xsd/codegen/gensupport' +require 'xsd/codegen/methoddef' +require 'xsd/codegen/commentdef' + + +module XSD +module CodeGen + + +class ModuleDef + include GenSupport + include CommentDef + + def initialize(name) + @name = name + @comment = nil + @const = [] + @code = [] + @requirepath = [] + @methoddef = [] + end + + def def_require(path) + @requirepath << path + end + + def def_const(const, value) + unless safeconstname?(const) + raise ArgumentError.new("#{const} seems to be unsafe") + end + @const << [const, value] + end + + def def_code(code) + @code << code + end + + def def_method(name, *params) + add_method(MethodDef.new(name, *params) { yield if block_given? }, :public) + end + alias def_publicmethod def_method + + def def_protectedmethod(name, *params) + add_method(MethodDef.new(name, *params) { yield if block_given? }, + :protected) + end + + def def_privatemethod(name, *params) + add_method(MethodDef.new(name, *params) { yield if block_given? }, :private) + end + + def add_method(m, visibility = :public) + @methoddef << [visibility, m] + end + + def dump + buf = "" + unless @requirepath.empty? + buf << dump_requirepath + end + buf << dump_emptyline unless buf.empty? + package = @name.split(/::/)[0..-2] + buf << dump_package_def(package) unless package.empty? + buf << dump_comment if @comment + buf << dump_module_def + spacer = false + unless @const.empty? + buf << dump_emptyline if spacer + spacer = true + buf << dump_const + end + unless @code.empty? + buf << dump_emptyline if spacer + spacer = true + buf << dump_code + end + unless @methoddef.empty? + buf << dump_emptyline if spacer + spacer = true + buf << dump_methods + end + buf << dump_module_def_end + buf << dump_package_def_end(package) unless package.empty? + buf.gsub(/^\s+$/, '') + end + +private + + def dump_requirepath + format( + @requirepath.collect { |path| + %Q(require '#{path}') + }.join("\n") + ) + end + + def dump_const + dump_static( + @const.sort.collect { |var, value| + %Q(#{var} = #{dump_value(value)}) + }.join("\n") + ) + end + + def dump_code + dump_static(@code.join("\n")) + end + + def dump_static(str) + format(str, 2) + end + + def dump_methods + methods = {} + @methoddef.each do |visibility, method| + (methods[visibility] ||= []) << method + end + str = "" + [:public, :protected, :private].each do |visibility| + if methods[visibility] + str << "\n" unless str.empty? + str << visibility.to_s << "\n\n" unless visibility == :public + str << methods[visibility].collect { |m| format(m.dump, 2) }.join("\n") + end + end + str + end + + def dump_value(value) + if value.respond_to?(:to_src) + value.to_src + else + value + end + end + + def dump_package_def(package) + format(package.collect { |ele| "module #{ele}" }.join("; ")) + "\n\n" + end + + def dump_package_def_end(package) + "\n\n" + format(package.collect { |ele| "end" }.join("; ")) + end + + def dump_module_def + name = @name.to_s.split(/::/) + format("module #{name.last}") + end + + def dump_module_def_end + format("end") + end +end + + +end +end + + +if __FILE__ == $0 + require 'xsd/codegen/moduledef' + include XSD::CodeGen + m = ModuleDef.new("Foo::Bar::HobbitName") + m.def_require("foo/bar") + m.def_require("baz") + m.comment = <<-EOD + foo + bar + baz + EOD + m.def_method("foo") do + <<-EOD + foo.bar = 1 + baz.each do |ele| + ele + 1 + end + EOD + end + m.def_method("baz", "qux") + #m.def_protectedmethod("aaa") + m.def_privatemethod("bbb") + puts m.dump +end diff --git a/ruby_1_8_5/lib/xsd/datatypes.rb b/ruby_1_8_5/lib/xsd/datatypes.rb new file mode 100644 index 0000000000..bbe6c8578f --- /dev/null +++ b/ruby_1_8_5/lib/xsd/datatypes.rb @@ -0,0 +1,1269 @@ +# XSD4R - XML Schema Datatype implementation. +# Copyright (C) 2000, 2001, 2002, 2003 NAKAMURA, Hiroshi . + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'xsd/qname' +require 'xsd/charset' +require 'uri' + + +### +## XMLSchamaDatatypes general definitions. +# +module XSD + + +Namespace = 'http://www.w3.org/2001/XMLSchema' +InstanceNamespace = 'http://www.w3.org/2001/XMLSchema-instance' + +AttrType = 'type' +NilValue = 'true' + +AnyTypeLiteral = 'anyType' +AnySimpleTypeLiteral = 'anySimpleType' +NilLiteral = 'nil' +StringLiteral = 'string' +BooleanLiteral = 'boolean' +DecimalLiteral = 'decimal' +FloatLiteral = 'float' +DoubleLiteral = 'double' +DurationLiteral = 'duration' +DateTimeLiteral = 'dateTime' +TimeLiteral = 'time' +DateLiteral = 'date' +GYearMonthLiteral = 'gYearMonth' +GYearLiteral = 'gYear' +GMonthDayLiteral = 'gMonthDay' +GDayLiteral = 'gDay' +GMonthLiteral = 'gMonth' +HexBinaryLiteral = 'hexBinary' +Base64BinaryLiteral = 'base64Binary' +AnyURILiteral = 'anyURI' +QNameLiteral = 'QName' + +NormalizedStringLiteral = 'normalizedString' +#3.3.2 token +#3.3.3 language +#3.3.4 NMTOKEN +#3.3.5 NMTOKENS +#3.3.6 Name +#3.3.7 NCName +#3.3.8 ID +#3.3.9 IDREF +#3.3.10 IDREFS +#3.3.11 ENTITY +#3.3.12 ENTITIES +IntegerLiteral = 'integer' +NonPositiveIntegerLiteral = 'nonPositiveInteger' +NegativeIntegerLiteral = 'negativeInteger' +LongLiteral = 'long' +IntLiteral = 'int' +ShortLiteral = 'short' +ByteLiteral = 'byte' +NonNegativeIntegerLiteral = 'nonNegativeInteger' +UnsignedLongLiteral = 'unsignedLong' +UnsignedIntLiteral = 'unsignedInt' +UnsignedShortLiteral = 'unsignedShort' +UnsignedByteLiteral = 'unsignedByte' +PositiveIntegerLiteral = 'positiveInteger' + +AttrTypeName = QName.new(InstanceNamespace, AttrType) +AttrNilName = QName.new(InstanceNamespace, NilLiteral) + +AnyTypeName = QName.new(Namespace, AnyTypeLiteral) +AnySimpleTypeName = QName.new(Namespace, AnySimpleTypeLiteral) + +class Error < StandardError; end +class ValueSpaceError < Error; end + + +### +## The base class of all datatypes with Namespace. +# +class NSDBase + @@types = [] + + attr_accessor :type + + def self.inherited(klass) + @@types << klass + end + + def self.types + @@types + end + + def initialize + end + + def init(type) + @type = type + end +end + + +### +## The base class of XSD datatypes. +# +class XSDAnySimpleType < NSDBase + include XSD + Type = QName.new(Namespace, AnySimpleTypeLiteral) + + # @data represents canonical space (ex. Integer: 123). + attr_reader :data + # @is_nil represents this data is nil or not. + attr_accessor :is_nil + + def initialize(value = nil) + init(Type, value) + end + + # true or raise + def check_lexical_format(value) + screen_data(value) + true + end + + # set accepts a string which follows lexical space (ex. String: "+123"), or + # an object which follows canonical space (ex. Integer: 123). + def set(value) + if value.nil? + @is_nil = true + @data = nil + _set(nil) + else + @is_nil = false + _set(screen_data(value)) + end + end + + # to_s creates a string which follows lexical space (ex. String: "123"). + def to_s() + if @is_nil + "" + else + _to_s + end + end + +private + + def init(type, value) + super(type) + set(value) + end + + # raises ValueSpaceError if check failed + def screen_data(value) + value + end + + def _set(value) + @data = value + end + + def _to_s + @data.to_s + end +end + +class XSDNil < XSDAnySimpleType + Type = QName.new(Namespace, NilLiteral) + Value = 'true' + + def initialize(value = nil) + init(Type, value) + end +end + + +### +## Primitive datatypes. +# +class XSDString < XSDAnySimpleType + Type = QName.new(Namespace, StringLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def screen_data(value) + unless XSD::Charset.is_ces(value, XSD::Charset.encoding) + raise ValueSpaceError.new("#{ type }: cannot accept '#{ value }'.") + end + value + end +end + +class XSDBoolean < XSDAnySimpleType + Type = QName.new(Namespace, BooleanLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def screen_data(value) + if value.is_a?(String) + str = value.strip + if str == 'true' || str == '1' + true + elsif str == 'false' || str == '0' + false + else + raise ValueSpaceError.new("#{ type }: cannot accept '#{ str }'.") + end + else + value ? true : false + end + end +end + +class XSDDecimal < XSDAnySimpleType + Type = QName.new(Namespace, DecimalLiteral) + + def initialize(value = nil) + init(Type, value) + end + + def nonzero? + (@number != '0') + end + +private + + def screen_data(d) + if d.is_a?(String) + # Integer("00012") => 10 in Ruby. + d.sub!(/^([+\-]?)0*(?=\d)/, "\\1") + end + screen_data_str(d) + end + + def screen_data_str(str) + /^([+\-]?)(\d*)(?:\.(\d*)?)?$/ =~ str.to_s.strip + unless Regexp.last_match + raise ValueSpaceError.new("#{ type }: cannot accept '#{ str }'.") + end + sign = $1 || '+' + int_part = $2 + frac_part = $3 + int_part = '0' if int_part.empty? + frac_part = frac_part ? frac_part.sub(/0+$/, '') : '' + point = - frac_part.size + number = int_part + frac_part + # normalize + if sign == '+' + sign = '' + elsif sign == '-' + if number == '0' + sign = '' + end + end + [sign, point, number] + end + + def _set(data) + if data.nil? + @sign = @point = @number = @data = nil + return + end + @sign, @point, @number = data + @data = _to_s + @data.freeze + end + + # 0.0 -> 0; right? + def _to_s + str = @number.dup + if @point.nonzero? + str[@number.size + @point, 0] = '.' + end + @sign + str + end +end + +module FloatConstants + NaN = 0.0/0.0 + POSITIVE_INF = +1.0/0.0 + NEGATIVE_INF = -1.0/0.0 + POSITIVE_ZERO = +1.0/POSITIVE_INF + NEGATIVE_ZERO = -1.0/POSITIVE_INF + MIN_POSITIVE_SINGLE = 2.0 ** -149 +end + +class XSDFloat < XSDAnySimpleType + include FloatConstants + Type = QName.new(Namespace, FloatLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def screen_data(value) + # "NaN".to_f => 0 in some environment. libc? + if value.is_a?(Float) + return narrow32bit(value) + end + str = value.to_s.strip + if str == 'NaN' + NaN + elsif str == 'INF' + POSITIVE_INF + elsif str == '-INF' + NEGATIVE_INF + else + if /^[+\-\.\deE]+$/ !~ str + raise ValueSpaceError.new("#{ type }: cannot accept '#{ str }'.") + end + # Float("-1.4E") might fail on some system. + str << '0' if /e$/i =~ str + begin + return narrow32bit(Float(str)) + rescue ArgumentError + raise ValueSpaceError.new("#{ type }: cannot accept '#{ str }'.") + end + end + end + + def _to_s + if @data.nan? + 'NaN' + elsif @data.infinite? == 1 + 'INF' + elsif @data.infinite? == -1 + '-INF' + else + sign = XSDFloat.positive?(@data) ? '+' : '-' + sign + sprintf("%.10g", @data.abs).sub(/[eE]([+-])?0+/) { 'e' + $1 } + end + end + + # Convert to single-precision 32-bit floating point value. + def narrow32bit(f) + if f.nan? || f.infinite? + f + elsif f.abs < MIN_POSITIVE_SINGLE + XSDFloat.positive?(f) ? POSITIVE_ZERO : NEGATIVE_ZERO + else + f + end + end + + def self.positive?(value) + (1 / value) > 0.0 + end +end + +# Ruby's Float is double-precision 64-bit floating point value. +class XSDDouble < XSDAnySimpleType + include FloatConstants + Type = QName.new(Namespace, DoubleLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def screen_data(value) + # "NaN".to_f => 0 in some environment. libc? + if value.is_a?(Float) + return value + end + str = value.to_s.strip + if str == 'NaN' + NaN + elsif str == 'INF' + POSITIVE_INF + elsif str == '-INF' + NEGATIVE_INF + else + begin + return Float(str) + rescue ArgumentError + # '1.4e' cannot be parsed on some architecture. + if /e\z/i =~ str + begin + return Float(str + '0') + rescue ArgumentError + raise ValueSpaceError.new("#{ type }: cannot accept '#{ str }'.") + end + else + raise ValueSpaceError.new("#{ type }: cannot accept '#{ str }'.") + end + end + end + end + + def _to_s + if @data.nan? + 'NaN' + elsif @data.infinite? == 1 + 'INF' + elsif @data.infinite? == -1 + '-INF' + else + sign = (1 / @data > 0.0) ? '+' : '-' + sign + sprintf("%.16g", @data.abs).sub(/[eE]([+-])?0+/) { 'e' + $1 } + end + end +end + +class XSDDuration < XSDAnySimpleType + Type = QName.new(Namespace, DurationLiteral) + + attr_accessor :sign + attr_accessor :year + attr_accessor :month + attr_accessor :day + attr_accessor :hour + attr_accessor :min + attr_accessor :sec + + def initialize(value = nil) + init(Type, value) + end + +private + + def screen_data(value) + /^([+\-]?)P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?)?$/ =~ value.to_s.strip + unless Regexp.last_match + raise ValueSpaceError.new("#{ type }: cannot accept '#{ value }'.") + end + if ($5 and ((!$2 and !$3 and !$4) or (!$6 and !$7 and !$8))) + # Should we allow 'PT5S' here? + raise ValueSpaceError.new("#{ type }: cannot accept '#{ value }'.") + end + sign = $1 + year = $2.to_i + month = $3.to_i + day = $4.to_i + hour = $6.to_i + min = $7.to_i + sec = $8 ? XSDDecimal.new($8) : 0 + [sign, year, month, day, hour, min, sec] + end + + def _set(data) + if data.nil? + @sign = @year = @month = @day = @hour = @min = @sec = @data = nil + return + end + @sign, @year, @month, @day, @hour, @min, @sec = data + @data = _to_s + @data.freeze + end + + def _to_s + str = '' + str << @sign if @sign + str << 'P' + l = '' + l << "#{ @year }Y" if @year.nonzero? + l << "#{ @month }M" if @month.nonzero? + l << "#{ @day }D" if @day.nonzero? + r = '' + r << "#{ @hour }H" if @hour.nonzero? + r << "#{ @min }M" if @min.nonzero? + r << "#{ @sec }S" if @sec.nonzero? + str << l + if l.empty? + str << "0D" + end + unless r.empty? + str << "T" << r + end + str + end +end + + +require 'rational' +require 'date' + +module XSDDateTimeImpl + SecInDay = 86400 # 24 * 60 * 60 + + def to_obj(klass) + if klass == Time + to_time + elsif klass == Date + to_date + elsif klass == DateTime + to_datetime + else + nil + end + end + + def to_time + begin + if @data.offset * SecInDay == Time.now.utc_offset + d = @data + usec = (d.sec_fraction * SecInDay * 1000000).round + Time.local(d.year, d.month, d.mday, d.hour, d.min, d.sec, usec) + else + d = @data.newof + usec = (d.sec_fraction * SecInDay * 1000000).round + Time.gm(d.year, d.month, d.mday, d.hour, d.min, d.sec, usec) + end + rescue ArgumentError + nil + end + end + + def to_date + Date.new0(@data.class.jd_to_ajd(@data.jd, 0, 0), 0, @data.start) + end + + def to_datetime + data + end + + def tz2of(str) + /^(?:Z|(?:([+\-])(\d\d):(\d\d))?)$/ =~ str + sign = $1 + hour = $2.to_i + min = $3.to_i + + of = case sign + when '+' + of = +(hour.to_r * 60 + min) / 1440 # 24 * 60 + when '-' + of = -(hour.to_r * 60 + min) / 1440 # 24 * 60 + else + 0 + end + of + end + + def of2tz(offset) + diffmin = offset * 24 * 60 + if diffmin.zero? + 'Z' + else + ((diffmin < 0) ? '-' : '+') << format('%02d:%02d', + (diffmin.abs / 60.0).to_i, (diffmin.abs % 60.0).to_i) + end + end + + def screen_data(t) + # convert t to a DateTime as an internal representation. + if t.respond_to?(:to_datetime) # 1.9 or later + t.to_datetime + elsif t.is_a?(DateTime) + t + elsif t.is_a?(Date) + t = screen_data_str(t) + t <<= 12 if t.year < 0 + t + elsif t.is_a?(Time) + jd = DateTime.civil_to_jd(t.year, t.mon, t.mday, DateTime::ITALY) + fr = DateTime.time_to_day_fraction(t.hour, t.min, [t.sec, 59].min) + + t.usec.to_r / 1000000 / SecInDay + of = t.utc_offset.to_r / SecInDay + DateTime.new0(DateTime.jd_to_ajd(jd, fr, of), of, DateTime::ITALY) + else + screen_data_str(t) + end + end + + def add_tz(s) + s + of2tz(@data.offset) + end +end + +class XSDDateTime < XSDAnySimpleType + include XSDDateTimeImpl + Type = QName.new(Namespace, DateTimeLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def screen_data_str(t) + /^([+\-]?\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d(?:\.(\d*))?)(Z|(?:[+\-]\d\d:\d\d)?)?$/ =~ t.to_s.strip + unless Regexp.last_match + raise ValueSpaceError.new("#{ type }: cannot accept '#{ t }'.") + end + if $1 == '0000' + raise ValueSpaceError.new("#{ type }: cannot accept '#{ t }'.") + end + year = $1.to_i + if year < 0 + year += 1 + end + mon = $2.to_i + mday = $3.to_i + hour = $4.to_i + min = $5.to_i + sec = $6.to_i + secfrac = $7 + zonestr = $8 + data = DateTime.civil(year, mon, mday, hour, min, sec, tz2of(zonestr)) + if secfrac + diffday = secfrac.to_i.to_r / (10 ** secfrac.size) / SecInDay + data += diffday + # FYI: new0 and jd_to_rjd are not necessary to use if you don't have + # exceptional reason. + end + [data, secfrac] + end + + def _set(data) + if data.nil? + @data = @secfrac = nil + return + end + @data, @secfrac = data + end + + def _to_s + year = (@data.year > 0) ? @data.year : @data.year - 1 + s = format('%.4d-%02d-%02dT%02d:%02d:%02d', + year, @data.mon, @data.mday, @data.hour, @data.min, @data.sec) + if @data.sec_fraction.nonzero? + if @secfrac + s << ".#{ @secfrac }" + else + s << sprintf("%.16f", + (@data.sec_fraction * SecInDay).to_f).sub(/^0/, '').sub(/0*$/, '') + end + end + add_tz(s) + end +end + +class XSDTime < XSDAnySimpleType + include XSDDateTimeImpl + Type = QName.new(Namespace, TimeLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def screen_data_str(t) + /^(\d\d):(\d\d):(\d\d(?:\.(\d*))?)(Z|(?:([+\-])(\d\d):(\d\d))?)?$/ =~ t.to_s.strip + unless Regexp.last_match + raise ValueSpaceError.new("#{ type }: cannot accept '#{ t }'.") + end + hour = $1.to_i + min = $2.to_i + sec = $3.to_i + secfrac = $4 + zonestr = $5 + data = DateTime.civil(1, 1, 1, hour, min, sec, tz2of(zonestr)) + if secfrac + diffday = secfrac.to_i.to_r / (10 ** secfrac.size) / SecInDay + data += diffday + end + [data, secfrac] + end + + def _set(data) + if data.nil? + @data = @secfrac = nil + return + end + @data, @secfrac = data + end + + def _to_s + s = format('%02d:%02d:%02d', @data.hour, @data.min, @data.sec) + if @data.sec_fraction.nonzero? + if @secfrac + s << ".#{ @secfrac }" + else + s << sprintf("%.16f", + (@data.sec_fraction * SecInDay).to_f).sub(/^0/, '').sub(/0*$/, '') + end + end + add_tz(s) + end +end + +class XSDDate < XSDAnySimpleType + include XSDDateTimeImpl + Type = QName.new(Namespace, DateLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def screen_data_str(t) + /^([+\-]?\d{4,})-(\d\d)-(\d\d)(Z|(?:([+\-])(\d\d):(\d\d))?)?$/ =~ t.to_s.strip + unless Regexp.last_match + raise ValueSpaceError.new("#{ type }: cannot accept '#{ t }'.") + end + year = $1.to_i + if year < 0 + year += 1 + end + mon = $2.to_i + mday = $3.to_i + zonestr = $4 + DateTime.civil(year, mon, mday, 0, 0, 0, tz2of(zonestr)) + end + + def _to_s + year = (@data.year > 0) ? @data.year : @data.year - 1 + s = format('%.4d-%02d-%02d', year, @data.mon, @data.mday) + add_tz(s) + end +end + +class XSDGYearMonth < XSDAnySimpleType + include XSDDateTimeImpl + Type = QName.new(Namespace, GYearMonthLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def screen_data_str(t) + /^([+\-]?\d{4,})-(\d\d)(Z|(?:([+\-])(\d\d):(\d\d))?)?$/ =~ t.to_s.strip + unless Regexp.last_match + raise ValueSpaceError.new("#{ type }: cannot accept '#{ t }'.") + end + year = $1.to_i + if year < 0 + year += 1 + end + mon = $2.to_i + zonestr = $3 + DateTime.civil(year, mon, 1, 0, 0, 0, tz2of(zonestr)) + end + + def _to_s + year = (@data.year > 0) ? @data.year : @data.year - 1 + s = format('%.4d-%02d', year, @data.mon) + add_tz(s) + end +end + +class XSDGYear < XSDAnySimpleType + include XSDDateTimeImpl + Type = QName.new(Namespace, GYearLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def screen_data_str(t) + /^([+\-]?\d{4,})(Z|(?:([+\-])(\d\d):(\d\d))?)?$/ =~ t.to_s.strip + unless Regexp.last_match + raise ValueSpaceError.new("#{ type }: cannot accept '#{ t }'.") + end + year = $1.to_i + if year < 0 + year += 1 + end + zonestr = $2 + DateTime.civil(year, 1, 1, 0, 0, 0, tz2of(zonestr)) + end + + def _to_s + year = (@data.year > 0) ? @data.year : @data.year - 1 + s = format('%.4d', year) + add_tz(s) + end +end + +class XSDGMonthDay < XSDAnySimpleType + include XSDDateTimeImpl + Type = QName.new(Namespace, GMonthDayLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def screen_data_str(t) + /^(\d\d)-(\d\d)(Z|(?:[+\-]\d\d:\d\d)?)?$/ =~ t.to_s.strip + unless Regexp.last_match + raise ValueSpaceError.new("#{ type }: cannot accept '#{ t }'.") + end + mon = $1.to_i + mday = $2.to_i + zonestr = $3 + DateTime.civil(1, mon, mday, 0, 0, 0, tz2of(zonestr)) + end + + def _to_s + s = format('%02d-%02d', @data.mon, @data.mday) + add_tz(s) + end +end + +class XSDGDay < XSDAnySimpleType + include XSDDateTimeImpl + Type = QName.new(Namespace, GDayLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def screen_data_str(t) + /^(\d\d)(Z|(?:[+\-]\d\d:\d\d)?)?$/ =~ t.to_s.strip + unless Regexp.last_match + raise ValueSpaceError.new("#{ type }: cannot accept '#{ t }'.") + end + mday = $1.to_i + zonestr = $2 + DateTime.civil(1, 1, mday, 0, 0, 0, tz2of(zonestr)) + end + + def _to_s + s = format('%02d', @data.mday) + add_tz(s) + end +end + +class XSDGMonth < XSDAnySimpleType + include XSDDateTimeImpl + Type = QName.new(Namespace, GMonthLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def screen_data_str(t) + /^(\d\d)(Z|(?:[+\-]\d\d:\d\d)?)?$/ =~ t.to_s.strip + unless Regexp.last_match + raise ValueSpaceError.new("#{ type }: cannot accept '#{ t }'.") + end + mon = $1.to_i + zonestr = $2 + DateTime.civil(1, mon, 1, 0, 0, 0, tz2of(zonestr)) + end + + def _to_s + s = format('%02d', @data.mon) + add_tz(s) + end +end + +class XSDHexBinary < XSDAnySimpleType + Type = QName.new(Namespace, HexBinaryLiteral) + + # String in Ruby could be a binary. + def initialize(value = nil) + init(Type, value) + end + + def set_encoded(value) + if /^[0-9a-fA-F]*$/ !~ value + raise ValueSpaceError.new("#{ type }: cannot accept '#{ value }'.") + end + @data = String.new(value).strip + @is_nil = false + end + + def string + [@data].pack("H*") + end + +private + + def screen_data(value) + value.unpack("H*")[0].tr('a-f', 'A-F') + end +end + +class XSDBase64Binary < XSDAnySimpleType + Type = QName.new(Namespace, Base64BinaryLiteral) + + # String in Ruby could be a binary. + def initialize(value = nil) + init(Type, value) + end + + def set_encoded(value) + if /^[A-Za-z0-9+\/=]*$/ !~ value + raise ValueSpaceError.new("#{ type }: cannot accept '#{ value }'.") + end + @data = String.new(value).strip + @is_nil = false + end + + def string + @data.unpack("m")[0] + end + +private + + def screen_data(value) + [value].pack("m").strip + end +end + +class XSDAnyURI < XSDAnySimpleType + Type = QName.new(Namespace, AnyURILiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def screen_data(value) + begin + URI.parse(value.to_s.strip) + rescue URI::InvalidURIError + raise ValueSpaceError.new("#{ type }: cannot accept '#{ value }'.") + end + end +end + +class XSDQName < XSDAnySimpleType + Type = QName.new(Namespace, QNameLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def screen_data(value) + /^(?:([^:]+):)?([^:]+)$/ =~ value.to_s.strip + unless Regexp.last_match + raise ValueSpaceError.new("#{ type }: cannot accept '#{ value }'.") + end + prefix = $1 + localpart = $2 + [prefix, localpart] + end + + def _set(data) + if data.nil? + @prefix = @localpart = @data = nil + return + end + @prefix, @localpart = data + @data = _to_s + @data.freeze + end + + def _to_s + if @prefix + "#{ @prefix }:#{ @localpart }" + else + "#{ @localpart }" + end + end +end + + +### +## Derived types +# +class XSDNormalizedString < XSDString + Type = QName.new(Namespace, NormalizedStringLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def screen_data(value) + if /[\t\r\n]/ =~ value + raise ValueSpaceError.new("#{ type }: cannot accept '#{ value }'.") + end + super + end +end + +class XSDInteger < XSDDecimal + Type = QName.new(Namespace, IntegerLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def screen_data_str(str) + begin + data = Integer(str) + rescue ArgumentError + raise ValueSpaceError.new("#{ type }: cannot accept '#{ str }'.") + end + unless validate(data) + raise ValueSpaceError.new("#{ type }: cannot accept '#{ str }'.") + end + data + end + + def _set(value) + @data = value + end + + def _to_s() + @data.to_s + end + + def validate(v) + max = maxinclusive + min = mininclusive + (max.nil? or v <= max) and (min.nil? or v >= min) + end + + def maxinclusive + nil + end + + def mininclusive + nil + end + + PositiveMinInclusive = 1 + def positive(v) + PositiveMinInclusive <= v + end +end + +class XSDNonPositiveInteger < XSDInteger + Type = QName.new(Namespace, NonPositiveIntegerLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def maxinclusive + 0 + end + + def mininclusive + nil + end +end + +class XSDNegativeInteger < XSDNonPositiveInteger + Type = QName.new(Namespace, NegativeIntegerLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def maxinclusive + -1 + end + + def mininclusive + nil + end +end + +class XSDLong < XSDInteger + Type = QName.new(Namespace, LongLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def maxinclusive + +9223372036854775807 + end + + def mininclusive + -9223372036854775808 + end +end + +class XSDInt < XSDLong + Type = QName.new(Namespace, IntLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def maxinclusive + +2147483647 + end + + def mininclusive + -2147483648 + end +end + +class XSDShort < XSDInt + Type = QName.new(Namespace, ShortLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def maxinclusive + +32767 + end + + def mininclusive + -32768 + end +end + +class XSDByte < XSDShort + Type = QName.new(Namespace, ByteLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def maxinclusive + +127 + end + + def mininclusive + -128 + end +end + +class XSDNonNegativeInteger < XSDInteger + Type = QName.new(Namespace, NonNegativeIntegerLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def maxinclusive + nil + end + + def mininclusive + 0 + end +end + +class XSDUnsignedLong < XSDNonNegativeInteger + Type = QName.new(Namespace, UnsignedLongLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def maxinclusive + +18446744073709551615 + end + + def mininclusive + 0 + end +end + +class XSDUnsignedInt < XSDUnsignedLong + Type = QName.new(Namespace, UnsignedIntLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def maxinclusive + +4294967295 + end + + def mininclusive + 0 + end +end + +class XSDUnsignedShort < XSDUnsignedInt + Type = QName.new(Namespace, UnsignedShortLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def maxinclusive + +65535 + end + + def mininclusive + 0 + end +end + +class XSDUnsignedByte < XSDUnsignedShort + Type = QName.new(Namespace, UnsignedByteLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def maxinclusive + +255 + end + + def mininclusive + 0 + end +end + +class XSDPositiveInteger < XSDNonNegativeInteger + Type = QName.new(Namespace, PositiveIntegerLiteral) + + def initialize(value = nil) + init(Type, value) + end + +private + + def maxinclusive + nil + end + + def mininclusive + 1 + end +end + + +end diff --git a/ruby_1_8_5/lib/xsd/datatypes1999.rb b/ruby_1_8_5/lib/xsd/datatypes1999.rb new file mode 100644 index 0000000000..c7d6479e54 --- /dev/null +++ b/ruby_1_8_5/lib/xsd/datatypes1999.rb @@ -0,0 +1,20 @@ +# XSD4R - XML Schema Datatype 1999 support +# Copyright (C) 2001, 2003 NAKAMURA, Hiroshi . + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'xsd/datatypes' + + +module XSD + Namespace.replace('http://www.w3.org/1999/XMLSchema') + InstanceNamespace.replace('http://www.w3.org/1999/XMLSchema-instance') + AnyTypeLiteral.replace('ur-type') + AnySimpleTypeLiteral.replace('ur-type') + NilLiteral.replace('null') + NilValue.replace('1') + DateTimeLiteral.replace('timeInstant') +end diff --git a/ruby_1_8_5/lib/xsd/iconvcharset.rb b/ruby_1_8_5/lib/xsd/iconvcharset.rb new file mode 100644 index 0000000000..7e629d569b --- /dev/null +++ b/ruby_1_8_5/lib/xsd/iconvcharset.rb @@ -0,0 +1,33 @@ +# XSD4R - Charset handling with iconv. +# Copyright (C) 2003 NAKAMURA, Hiroshi . + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'iconv' + + +module XSD + + +class IconvCharset + def self.safe_iconv(to, from, str) + iconv = Iconv.new(to, from) + out = "" + begin + out << iconv.iconv(str) + rescue Iconv::IllegalSequence => e + out << e.success + ch, str = e.failed.split(//, 2) + out << '?' + warn("Failed to convert #{ch}") + retry + end + return out + end +end + + +end diff --git a/ruby_1_8_5/lib/xsd/mapping.rb b/ruby_1_8_5/lib/xsd/mapping.rb new file mode 100644 index 0000000000..06d30d4cbf --- /dev/null +++ b/ruby_1_8_5/lib/xsd/mapping.rb @@ -0,0 +1,42 @@ +# XSD4R - XML Mapping for Ruby +# Copyright (C) 2005 NAKAMURA, Hiroshi . + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require "soap/parser" +require 'soap/encodingstyle/literalHandler' +require "soap/generator" +require "soap/mapping" +require "soap/mapping/wsdlliteralregistry" + + +module XSD + + +module Mapping + MappingRegistry = SOAP::Mapping::WSDLLiteralRegistry.new + MappingOpt = {:default_encodingstyle => SOAP::LiteralNamespace} + + def self.obj2xml(obj, elename = nil, io = nil) + if !elename.nil? and !elename.is_a?(XSD::QName) + elename = XSD::QName.new(nil, elename) + end + elename ||= XSD::QName.new(nil, SOAP::Mapping.name2elename(obj.class.to_s)) + soap = SOAP::Mapping.obj2soap(obj, MappingRegistry) + soap.elename = elename + generator = SOAP::SOAPGenerator.new(MappingOpt) + generator.generate(soap, io) + end + + def self.xml2obj(stream) + parser = SOAP::Parser.new(MappingOpt) + soap = parser.parse(stream) + SOAP::Mapping.soap2obj(soap, MappingRegistry) + end +end + + +end diff --git a/ruby_1_8_5/lib/xsd/namedelements.rb b/ruby_1_8_5/lib/xsd/namedelements.rb new file mode 100644 index 0000000000..a13396bb71 --- /dev/null +++ b/ruby_1_8_5/lib/xsd/namedelements.rb @@ -0,0 +1,95 @@ +# XSD4R - WSDL named element collection. +# Copyright (C) 2002, 2003, 2005 NAKAMURA, Hiroshi . + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +module XSD + + +class NamedElements + include Enumerable + + def initialize + @elements = [] + @cache = {} + end + + def dup + o = NamedElements.new + o.elements = @elements.dup + o + end + + def freeze + super + @elements.freeze + self + end + + def empty? + size == 0 + end + + def size + @elements.size + end + + def [](idx) + if idx.is_a?(Numeric) + @elements[idx] + else + @cache[idx] ||= @elements.find { |item| item.name == idx } + end + end + + def find_name(name) + @elements.find { |item| item.name.name == name } + end + + def keys + collect { |element| element.name } + end + + def each + @elements.each do |element| + yield(element) + end + end + + def <<(rhs) + @elements << rhs + self + end + + def delete(rhs) + @elements.delete(rhs) + end + + def +(rhs) + o = NamedElements.new + o.elements = @elements + rhs.elements + o + end + + def concat(rhs) + @elements.concat(rhs.elements) + self + end + + Empty = NamedElements.new.freeze + +protected + + def elements=(rhs) + @elements = rhs + end + + def elements + @elements + end +end + +end diff --git a/ruby_1_8_5/lib/xsd/ns.rb b/ruby_1_8_5/lib/xsd/ns.rb new file mode 100644 index 0000000000..53eeae7130 --- /dev/null +++ b/ruby_1_8_5/lib/xsd/ns.rb @@ -0,0 +1,140 @@ +# XSD4R - XML Schema Namespace library +# Copyright (C) 2000-2003, 2005 NAKAMURA, Hiroshi . + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'xsd/datatypes' + + +module XSD + + +class NS + class Assigner + def initialize + @count = 0 + end + + def assign(ns) + @count += 1 + "n#{@count}" + end + end + + attr_reader :default_namespace + + class FormatError < Error; end + +public + + def initialize(tag2ns = {}) + @tag2ns = tag2ns + @assigner = nil + @ns2tag = {} + @tag2ns.each do |tag, ns| + @ns2tag[ns] = tag + end + @default_namespace = nil + end + + def assign(ns, tag = nil) + if (tag == '') + @default_namespace = ns + tag + else + @assigner ||= Assigner.new + tag ||= @assigner.assign(ns) + @ns2tag[ns] = tag + @tag2ns[tag] = ns + tag + end + end + + def assigned?(ns) + @default_namespace == ns or @ns2tag.key?(ns) + end + + def assigned_tag?(tag) + @tag2ns.key?(tag) + end + + def clone_ns + cloned = NS.new(@tag2ns.dup) + cloned.assigner = @assigner + cloned.assign(@default_namespace, '') if @default_namespace + cloned + end + + def name(name) + if (name.namespace == @default_namespace) + name.name + elsif @ns2tag.key?(name.namespace) + "#{@ns2tag[name.namespace]}:#{name.name}" + else + raise FormatError.new("namespace: #{name.namespace} not defined yet") + end + end + + def compare(ns, name, rhs) + if (ns == @default_namespace) + return true if (name == rhs) + end + @tag2ns.each do |assigned_tag, assigned_ns| + if assigned_ns == ns && "#{assigned_tag}:#{name}" == rhs + return true + end + end + false + end + + # $1 and $2 are necessary. + ParseRegexp = Regexp.new('^([^:]+)(?::(.+))?$') + + def parse(str, local = false) + if ParseRegexp =~ str + if (name = $2) and (ns = @tag2ns[$1]) + return XSD::QName.new(ns, name) + end + end + XSD::QName.new(local ? nil : @default_namespace, str) + end + + # For local attribute key parsing + # + # => + # {}bar, {urn:a}baz + def parse_local(elem) + ParseRegexp =~ elem + if $2 + ns = @tag2ns[$1] + name = $2 + if !ns + raise FormatError.new("unknown namespace qualifier: #{$1}") + end + elsif $1 + ns = nil + name = $1 + else + raise FormatError.new("illegal element format: #{elem}") + end + XSD::QName.new(ns, name) + end + + def each_ns + @ns2tag.each do |ns, tag| + yield(ns, tag) + end + end + +protected + + def assigner=(assigner) + @assigner = assigner + end +end + + +end diff --git a/ruby_1_8_5/lib/xsd/qname.rb b/ruby_1_8_5/lib/xsd/qname.rb new file mode 100644 index 0000000000..bb9763a69a --- /dev/null +++ b/ruby_1_8_5/lib/xsd/qname.rb @@ -0,0 +1,78 @@ +# XSD4R - XML QName definition. +# Copyright (C) 2002, 2003, 2004 NAKAMURA, Hiroshi . + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +module XSD + + +class QName + attr_accessor :namespace + attr_accessor :name + attr_accessor :source + + def initialize(namespace = nil, name = nil) + @namespace = namespace + @name = name + @source = nil + end + + def dup_name(name) + XSD::QName.new(@namespace, name) + end + + def dump + ns = @namespace.nil? ? 'nil' : @namespace.dump + name = @name.nil? ? 'nil' : @name.dump + "XSD::QName.new(#{ns}, #{name})" + end + + def match(rhs) + if rhs.namespace and (rhs.namespace != @namespace) + return false + end + if rhs.name and (rhs.name != @name) + return false + end + true + end + + def ==(rhs) + !rhs.nil? and @namespace == rhs.namespace and @name == rhs.name + end + + def ===(rhs) + (self == rhs) + end + + def eql?(rhs) + (self == rhs) + end + + def hash + @namespace.hash ^ @name.hash + end + + def to_s + "{#{ namespace }}#{ name }" + end + + def inspect + sprintf("#<%s:0x%x %s>", self.class.name, __id__, + "{#{ namespace }}#{ name }") + end + + NormalizedNameRegexp = /^\{([^}]*)\}(.*)$/ + def parse(str) + NormalizedNameRegexp =~ str + self.new($1, $2) + end + + EMPTY = QName.new.freeze +end + + +end diff --git a/ruby_1_8_5/lib/xsd/xmlparser.rb b/ruby_1_8_5/lib/xsd/xmlparser.rb new file mode 100644 index 0000000000..e79e36c58c --- /dev/null +++ b/ruby_1_8_5/lib/xsd/xmlparser.rb @@ -0,0 +1,61 @@ +# XSD4R - XML Instance parser library. +# Copyright (C) 2002, 2003 NAKAMURA, Hiroshi . + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'xsd/xmlparser/parser' + + +module XSD + + +module XMLParser + def create_parser(host, opt) + XSD::XMLParser::Parser.create_parser(host, opt) + end + module_function :create_parser + + # $1 is necessary. + NSParseRegexp = Regexp.new('^xmlns:?(.*)$') + + def filter_ns(ns, attrs) + return attrs if attrs.nil? or attrs.empty? + newattrs = {} + attrs.each do |key, value| + if (NSParseRegexp =~ key) + # '' means 'default namespace'. + tag = $1 || '' + ns.assign(value, tag) + else + newattrs[key] = value + end + end + newattrs + end + module_function :filter_ns +end + + +end + + +# Try to load XML processor. +loaded = false +[ + 'xsd/xmlparser/xmlparser', + 'xsd/xmlparser/xmlscanner', + 'xsd/xmlparser/rexmlparser', +].each do |lib| + begin + require lib + loaded = true + break + rescue LoadError + end +end +unless loaded + raise RuntimeError.new("XML processor module not found.") +end diff --git a/ruby_1_8_5/lib/xsd/xmlparser/parser.rb b/ruby_1_8_5/lib/xsd/xmlparser/parser.rb new file mode 100644 index 0000000000..ad01d55aa0 --- /dev/null +++ b/ruby_1_8_5/lib/xsd/xmlparser/parser.rb @@ -0,0 +1,96 @@ +# XSD4R - XML Instance parser library. +# Copyright (C) 2002, 2003 NAKAMURA, Hiroshi . + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'xsd/qname' +require 'xsd/ns' +require 'xsd/charset' + + +module XSD +module XMLParser + + +class Parser + class ParseError < Error; end + class FormatDecodeError < ParseError; end + class UnknownElementError < FormatDecodeError; end + class UnknownAttributeError < FormatDecodeError; end + class UnexpectedElementError < FormatDecodeError; end + class ElementConstraintError < FormatDecodeError; end + + @@parser_factory = nil + + def self.factory + @@parser_factory + end + + def self.create_parser(host, opt = {}) + @@parser_factory.new(host, opt) + end + + def self.add_factory(factory) + if $DEBUG + puts "Set #{ factory } as XML processor." + end + @@parser_factory = factory + end + +public + + attr_accessor :charset + + def initialize(host, opt = {}) + @host = host + @charset = opt[:charset] || nil + end + + def parse(string_or_readable) + @textbuf = '' + prologue + do_parse(string_or_readable) + epilogue + end + +private + + def do_parse(string_or_readable) + raise NotImplementError.new( + 'Method do_parse must be defined in derived class.') + end + + def start_element(name, attrs) + @host.start_element(name, attrs) + end + + def characters(text) + @host.characters(text) + end + + def end_element(name) + @host.end_element(name) + end + + def prologue + end + + def epilogue + end + + def xmldecl_encoding=(charset) + if @charset.nil? + @charset = charset + else + # Definition in a stream (like HTTP) has a priority. + p "encoding definition: #{ charset } is ignored." if $DEBUG + end + end +end + + +end +end diff --git a/ruby_1_8_5/lib/xsd/xmlparser/rexmlparser.rb b/ruby_1_8_5/lib/xsd/xmlparser/rexmlparser.rb new file mode 100644 index 0000000000..61da9aafc7 --- /dev/null +++ b/ruby_1_8_5/lib/xsd/xmlparser/rexmlparser.rb @@ -0,0 +1,54 @@ +# XSD4R - REXMLParser XML parser library. +# Copyright (C) 2002, 2003 NAKAMURA, Hiroshi . + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'xsd/xmlparser' +require 'rexml/streamlistener' +require 'rexml/document' + + +module XSD +module XMLParser + + +class REXMLParser < XSD::XMLParser::Parser + include REXML::StreamListener + + def do_parse(string_or_readable) + source = nil + source = REXML::SourceFactory.create_from(string_or_readable) + source.encoding = charset if charset + # Listener passes a String in utf-8. + @charset = 'utf-8' + REXML::Document.parse_stream(source, self) + end + + def epilogue + end + + def tag_start(name, attrs) + start_element(name, attrs) + end + + def tag_end(name) + end_element(name) + end + + def text(text) + characters(text) + end + + def xmldecl(version, encoding, standalone) + # Version should be checked. + end + + add_factory(self) +end + + +end +end diff --git a/ruby_1_8_5/lib/xsd/xmlparser/xmlparser.rb b/ruby_1_8_5/lib/xsd/xmlparser/xmlparser.rb new file mode 100644 index 0000000000..6db914cd37 --- /dev/null +++ b/ruby_1_8_5/lib/xsd/xmlparser/xmlparser.rb @@ -0,0 +1,50 @@ +# XSD4R - XMLParser XML parser library. +# Copyright (C) 2001, 2003 NAKAMURA, Hiroshi . + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'xsd/xmlparser' +require 'xml/parser' + + +module XSD +module XMLParser + + +class XMLParser < XSD::XMLParser::Parser + class Listener < XML::Parser + begin + require 'xml/encoding-ja' + include XML::Encoding_ja + rescue LoadError + # uconv may not be installed. + end + end + + def do_parse(string_or_readable) + # XMLParser passes a String in utf-8. + @charset = 'utf-8' + @parser = Listener.new + @parser.parse(string_or_readable) do |type, name, data| + case type + when XML::Parser::START_ELEM + start_element(name, data) + when XML::Parser::END_ELEM + end_element(name) + when XML::Parser::CDATA + characters(data) + else + raise FormatDecodeError.new("Unexpected XML: #{ type }/#{ name }/#{ data }.") + end + end + end + + add_factory(self) +end + + +end +end diff --git a/ruby_1_8_5/lib/xsd/xmlparser/xmlscanner.rb b/ruby_1_8_5/lib/xsd/xmlparser/xmlscanner.rb new file mode 100644 index 0000000000..c80dc23910 --- /dev/null +++ b/ruby_1_8_5/lib/xsd/xmlparser/xmlscanner.rb @@ -0,0 +1,147 @@ +# XSD4R - XMLScan XML parser library. +# Copyright (C) 2002, 2003, 2005 NAKAMURA, Hiroshi . + +# This program is copyrighted free software by NAKAMURA, Hiroshi. You can +# redistribute it and/or modify it under the same terms of Ruby's license; +# either the dual license version in 2003, or any later version. + + +require 'xsd/xmlparser' +require 'xmlscan/scanner' + + +module XSD +module XMLParser + + +class XMLScanner < XSD::XMLParser::Parser + include XMLScan::Visitor + + def do_parse(string_or_readable) + @attrs = {} + @curattr = nil + @scanner = XMLScan::XMLScanner.new(self) + @scanner.kcode = XSD::Charset.charset_str(charset) if charset + @scanner.parse(string_or_readable) + end + + def scanner_kcode=(charset) + @scanner.kcode = XSD::Charset.charset_str(charset) if charset + self.xmldecl_encoding = charset + end + + ENTITY_REF_MAP = { + 'lt' => '<', + 'gt' => '>', + 'amp' => '&', + 'quot' => '"', + 'apos' => '\'' + } + + def parse_error(msg) + raise ParseError.new(msg) + end + + def wellformed_error(msg) + raise NotWellFormedError.new(msg) + end + + def valid_error(msg) + raise NotValidError.new(msg) + end + + def warning(msg) + p msg if $DEBUG + end + + # def on_xmldecl; end + + def on_xmldecl_version(str) + # 1.0 expected. + end + + def on_xmldecl_encoding(str) + self.scanner_kcode = str + end + + # def on_xmldecl_standalone(str); end + + # def on_xmldecl_other(name, value); end + + # def on_xmldecl_end; end + + # def on_doctype(root, pubid, sysid); end + + # def on_prolog_space(str); end + + # def on_comment(str); end + + # def on_pi(target, pi); end + + def on_chardata(str) + characters(str) + end + + # def on_cdata(str); end + + def on_etag(name) + end_element(name) + end + + def on_entityref(ref) + characters(ENTITY_REF_MAP[ref]) + end + + def on_charref(code) + characters([code].pack('U')) + end + + def on_charref_hex(code) + on_charref(code) + end + + # def on_start_document; end + + # def on_end_document; end + + def on_stag(name) + @attrs = {} + end + + def on_attribute(name) + @attrs[name] = @curattr = '' + end + + def on_attr_value(str) + @curattr << str + end + + def on_attr_entityref(ref) + @curattr << ENTITY_REF_MAP[ref] + end + + def on_attr_charref(code) + @curattr << [code].pack('U') + end + + def on_attr_charref_hex(code) + on_attr_charref(code) + end + + # def on_attribute_end(name); end + + def on_stag_end_empty(name) + on_stag_end(name) + on_etag(name) + end + + def on_stag_end(name) + start_element(name, @attrs) + end + + add_factory(self) +end + + +end +end -- cgit v1.2.3