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

* lib/xmlrpc, lib/rexml, test/ruby/test_array.rb,

test/ruby/test_unicode_escape.rb, test/scanf/test_scanf.rb,
  test/rss/rss-assertions.rb: fix indentation to remove warning.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19657 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
mame 2008-10-01 13:46:53 +00:00
parent 952385b712
commit 46321a9a31
40 changed files with 2198 additions and 2192 deletions

View file

@ -1,3 +1,9 @@
Wed Oct 1 22:43:59 2008 Yusuke Endoh <mame@tsg.ne.jp>
* lib/xmlrpc, lib/rexml, test/ruby/test_array.rb,
test/ruby/test_unicode_escape.rb, test/scanf/test_scanf.rb,
test/rss/rss-assertions.rb: fix indentation to remove warning.
Wed Oct 1 21:36:35 2008 Nobuyoshi Nakada <nobu@ruby-lang.org> Wed Oct 1 21:36:35 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
* gc.c (rb_gc_call_finalizer_at_exit): finalize deferred IO and Data. * gc.c (rb_gc_call_finalizer_at_exit): finalize deferred IO and Data.

View file

@ -3,60 +3,60 @@ require 'rexml/child'
require 'rexml/source' require 'rexml/source'
module REXML module REXML
# This class needs: # This class needs:
# * Documentation # * Documentation
# * Work! Not all types of attlists are intelligently parsed, so we just # * Work! Not all types of attlists are intelligently parsed, so we just
# spew back out what we get in. This works, but it would be better if # spew back out what we get in. This works, but it would be better if
# we formatted the output ourselves. # we formatted the output ourselves.
# #
# AttlistDecls provide *just* enough support to allow namespace # AttlistDecls provide *just* enough support to allow namespace
# declarations. If you need some sort of generalized support, or have an # declarations. If you need some sort of generalized support, or have an
# interesting idea about how to map the hideous, terrible design of DTD # interesting idea about how to map the hideous, terrible design of DTD
# AttlistDecls onto an intuitive Ruby interface, let me know. I'm desperate # AttlistDecls onto an intuitive Ruby interface, let me know. I'm desperate
# for anything to make DTDs more palateable. # for anything to make DTDs more palateable.
class AttlistDecl < Child class AttlistDecl < Child
include Enumerable include Enumerable
# What is this? Got me. # What is this? Got me.
attr_reader :element_name attr_reader :element_name
# Create an AttlistDecl, pulling the information from a Source. Notice # Create an AttlistDecl, pulling the information from a Source. Notice
# that this isn't very convenient; to create an AttlistDecl, you basically # that this isn't very convenient; to create an AttlistDecl, you basically
# have to format it yourself, and then have the initializer parse it. # have to format it yourself, and then have the initializer parse it.
# Sorry, but for the forseeable future, DTD support in REXML is pretty # Sorry, but for the forseeable future, DTD support in REXML is pretty
# weak on convenience. Have I mentioned how much I hate DTDs? # weak on convenience. Have I mentioned how much I hate DTDs?
def initialize(source) def initialize(source)
super() super()
if (source.kind_of? Array) if (source.kind_of? Array)
@element_name, @pairs, @contents = *source @element_name, @pairs, @contents = *source
end end
end end
# Access the attlist attribute/value pairs. # Access the attlist attribute/value pairs.
# value = attlist_decl[ attribute_name ] # value = attlist_decl[ attribute_name ]
def [](key) def [](key)
@pairs[key] @pairs[key]
end end
# Whether an attlist declaration includes the given attribute definition # Whether an attlist declaration includes the given attribute definition
# if attlist_decl.include? "xmlns:foobar" # if attlist_decl.include? "xmlns:foobar"
def include?(key) def include?(key)
@pairs.keys.include? key @pairs.keys.include? key
end end
# Iterate over the key/value pairs: # Iterate over the key/value pairs:
# attlist_decl.each { |attribute_name, attribute_value| ... } # attlist_decl.each { |attribute_name, attribute_value| ... }
def each(&block) def each(&block)
@pairs.each(&block) @pairs.each(&block)
end end
# Write out exactly what we got in. # Write out exactly what we got in.
def write out, indent=-1 def write out, indent=-1
out << @contents out << @contents
end end
def node_type def node_type
:attlistdecl :attlistdecl
end end
end end
end end

View file

@ -2,24 +2,24 @@ require "rexml/namespace"
require 'rexml/text' require 'rexml/text'
module REXML module REXML
# Defines an Element Attribute; IE, a attribute=value pair, as in: # Defines an Element Attribute; IE, a attribute=value pair, as in:
# <element attribute="value"/>. Attributes can be in their own # <element attribute="value"/>. Attributes can be in their own
# namespaces. General users of REXML will not interact with the # namespaces. General users of REXML will not interact with the
# Attribute class much. # Attribute class much.
class Attribute class Attribute
include Node include Node
include Namespace include Namespace
# The element to which this attribute belongs # The element to which this attribute belongs
attr_reader :element attr_reader :element
# The normalized value of this attribute. That is, the attribute with # The normalized value of this attribute. That is, the attribute with
# entities intact. # entities intact.
attr_writer :normalized attr_writer :normalized
PATTERN = /\s*(#{NAME_STR})\s*=\s*(["'])(.*?)\2/um PATTERN = /\s*(#{NAME_STR})\s*=\s*(["'])(.*?)\2/um
NEEDS_A_SECOND_CHECK = /(<|&((#{Entity::NAME});|(#0*((?:\d+)|(?:x[a-fA-F0-9]+)));)?)/um NEEDS_A_SECOND_CHECK = /(<|&((#{Entity::NAME});|(#0*((?:\d+)|(?:x[a-fA-F0-9]+)));)?)/um
# Constructor. # Constructor.
# FIXME: The parser doesn't catch illegal characters in attributes # FIXME: The parser doesn't catch illegal characters in attributes
# #
# first:: # first::
@ -36,137 +36,137 @@ module REXML
# Ignored unless +first+ is a String; otherwise, may be the Element # Ignored unless +first+ is a String; otherwise, may be the Element
# parent of this attribute, or nil. # parent of this attribute, or nil.
# #
# #
# Attribute.new( attribute_to_clone ) # Attribute.new( attribute_to_clone )
# Attribute.new( attribute_to_clone, parent_element ) # Attribute.new( attribute_to_clone, parent_element )
# Attribute.new( "attr", "attr_value" ) # Attribute.new( "attr", "attr_value" )
# Attribute.new( "attr", "attr_value", parent_element ) # Attribute.new( "attr", "attr_value", parent_element )
def initialize( first, second=nil, parent=nil ) def initialize( first, second=nil, parent=nil )
@normalized = @unnormalized = @element = nil @normalized = @unnormalized = @element = nil
if first.kind_of? Attribute if first.kind_of? Attribute
self.name = first.expanded_name self.name = first.expanded_name
@unnormalized = first.value @unnormalized = first.value
if second.kind_of? Element if second.kind_of? Element
@element = second @element = second
else else
@element = first.element @element = first.element
end end
elsif first.kind_of? String elsif first.kind_of? String
@element = parent @element = parent
self.name = first self.name = first
@normalized = second.to_s @normalized = second.to_s
else else
raise "illegal argument #{first.class.name} to Attribute constructor" raise "illegal argument #{first.class.name} to Attribute constructor"
end end
end
# Returns the namespace of the attribute.
#
# e = Element.new( "elns:myelement" )
# e.add_attribute( "nsa:a", "aval" )
# e.add_attribute( "b", "bval" )
# e.attributes.get_attribute( "a" ).prefix # -> "nsa"
# e.attributes.get_attribute( "b" ).prefix # -> "elns"
# a = Attribute.new( "x", "y" )
# a.prefix # -> ""
def prefix
pf = super
if pf == ""
pf = @element.prefix if @element
end
pf
end
# Returns the namespace URL, if defined, or nil otherwise
#
# e = Element.new("el")
# e.add_attributes({"xmlns:ns", "http://url"})
# e.namespace( "ns" ) # -> "http://url"
def namespace arg=nil
arg = prefix if arg.nil?
@element.namespace arg
end
# Returns true if other is an Attribute and has the same name and value,
# false otherwise.
def ==( other )
other.kind_of?(Attribute) and other.name==name and other.value==value
end
# Creates (and returns) a hash from both the name and value
def hash
name.hash + value.hash
end
# Returns this attribute out as XML source, expanding the name
#
# a = Attribute.new( "x", "y" )
# a.to_string # -> "x='y'"
# b = Attribute.new( "ns:x", "y" )
# b.to_string # -> "ns:x='y'"
def to_string
if @element and @element.context and @element.context[:attribute_quote] == :quote
%Q^#@expanded_name="#{to_s().gsub(/"/, '&quote;')}"^
else
"#@expanded_name='#{to_s().gsub(/'/, '&apos;')}'"
end
end
def doctype
if @element
doc = @element.document
doctype = doc.doctype if doc
end
end end
# Returns the attribute value, with entities replaced # Returns the namespace of the attribute.
def to_s #
return @normalized if @normalized # e = Element.new( "elns:myelement" )
# e.add_attribute( "nsa:a", "aval" )
# e.add_attribute( "b", "bval" )
# e.attributes.get_attribute( "a" ).prefix # -> "nsa"
# e.attributes.get_attribute( "b" ).prefix # -> "elns"
# a = Attribute.new( "x", "y" )
# a.prefix # -> ""
def prefix
pf = super
if pf == ""
pf = @element.prefix if @element
end
pf
end
@normalized = Text::normalize( @unnormalized, doctype ) # Returns the namespace URL, if defined, or nil otherwise
@unnormalized = nil #
# e = Element.new("el")
# e.add_attributes({"xmlns:ns", "http://url"})
# e.namespace( "ns" ) # -> "http://url"
def namespace arg=nil
arg = prefix if arg.nil?
@element.namespace arg
end
# Returns true if other is an Attribute and has the same name and value,
# false otherwise.
def ==( other )
other.kind_of?(Attribute) and other.name==name and other.value==value
end
# Creates (and returns) a hash from both the name and value
def hash
name.hash + value.hash
end
# Returns this attribute out as XML source, expanding the name
#
# a = Attribute.new( "x", "y" )
# a.to_string # -> "x='y'"
# b = Attribute.new( "ns:x", "y" )
# b.to_string # -> "ns:x='y'"
def to_string
if @element and @element.context and @element.context[:attribute_quote] == :quote
%Q^#@expanded_name="#{to_s().gsub(/"/, '&quote;')}"^
else
"#@expanded_name='#{to_s().gsub(/'/, '&apos;')}'"
end
end
def doctype
if @element
doc = @element.document
doctype = doc.doctype if doc
end
end
# Returns the attribute value, with entities replaced
def to_s
return @normalized if @normalized
@normalized = Text::normalize( @unnormalized, doctype )
@unnormalized = nil
@normalized @normalized
end end
# Returns the UNNORMALIZED value of this attribute. That is, entities # Returns the UNNORMALIZED value of this attribute. That is, entities
# have been expanded to their values # have been expanded to their values
def value def value
return @unnormalized if @unnormalized return @unnormalized if @unnormalized
@unnormalized = Text::unnormalize( @normalized, doctype ) @unnormalized = Text::unnormalize( @normalized, doctype )
@normalized = nil @normalized = nil
@unnormalized @unnormalized
end end
# Returns a copy of this attribute # Returns a copy of this attribute
def clone def clone
Attribute.new self Attribute.new self
end end
# Sets the element of which this object is an attribute. Normally, this # Sets the element of which this object is an attribute. Normally, this
# is not directly called. # is not directly called.
# #
# Returns this attribute # Returns this attribute
def element=( element ) def element=( element )
@element = element @element = element
if @normalized if @normalized
Text.check( @normalized, NEEDS_A_SECOND_CHECK, doctype ) Text.check( @normalized, NEEDS_A_SECOND_CHECK, doctype )
end end
self self
end end
# Removes this Attribute from the tree, and returns true if successfull # Removes this Attribute from the tree, and returns true if successfull
# #
# This method is usually not called directly. # This method is usually not called directly.
def remove def remove
@element.attributes.delete self.name unless @element.nil? @element.attributes.delete self.name unless @element.nil?
end end
# Writes this attribute (EG, puts 'key="value"' to the output) # Writes this attribute (EG, puts 'key="value"' to the output)
def write( output, indent=-1 ) def write( output, indent=-1 )
output << to_string output << to_string
end end
def node_type def node_type
:attribute :attribute
@ -183,6 +183,6 @@ module REXML
path += "/@#{self.expanded_name}" path += "/@#{self.expanded_name}"
return path return path
end end
end end
end end
#vim:ts=2 sw=2 noexpandtab: #vim:ts=2 sw=2 noexpandtab:

View file

@ -1,39 +1,39 @@
require "rexml/text" require "rexml/text"
module REXML module REXML
class CData < Text class CData < Text
START = '<![CDATA[' START = '<![CDATA['
STOP = ']]>' STOP = ']]>'
ILLEGAL = /(\]\]>)/ ILLEGAL = /(\]\]>)/
# Constructor. CData is data between <![CDATA[ ... ]]> # Constructor. CData is data between <![CDATA[ ... ]]>
# #
# _Examples_ # _Examples_
# CData.new( source ) # CData.new( source )
# CData.new( "Here is some CDATA" ) # CData.new( "Here is some CDATA" )
# CData.new( "Some unprocessed data", respect_whitespace_TF, parent_element ) # CData.new( "Some unprocessed data", respect_whitespace_TF, parent_element )
def initialize( first, whitespace=true, parent=nil ) def initialize( first, whitespace=true, parent=nil )
super( first, whitespace, parent, false, true, ILLEGAL ) super( first, whitespace, parent, false, true, ILLEGAL )
end end
# Make a copy of this object # Make a copy of this object
# #
# _Examples_ # _Examples_
# c = CData.new( "Some text" ) # c = CData.new( "Some text" )
# d = c.clone # d = c.clone
# d.to_s # -> "Some text" # d.to_s # -> "Some text"
def clone def clone
CData.new self CData.new self
end end
# Returns the content of this CData object # Returns the content of this CData object
# #
# _Examples_ # _Examples_
# c = CData.new( "Some text" ) # c = CData.new( "Some text" )
# c.to_s # -> "Some text" # c.to_s # -> "Some text"
def to_s def to_s
@string @string
end end
def value def value
@string @string
@ -42,26 +42,26 @@ module REXML
# == DEPRECATED # == DEPRECATED
# See the rexml/formatters package # See the rexml/formatters package
# #
# Generates XML output of this object # Generates XML output of this object
# #
# output:: # output::
# Where to write the string. Defaults to $stdout # Where to write the string. Defaults to $stdout
# indent:: # indent::
# The amount to indent this node by # The amount to indent this node by
# transitive:: # transitive::
# Ignored # Ignored
# ie_hack:: # ie_hack::
# Ignored # Ignored
# #
# _Examples_ # _Examples_
# c = CData.new( " Some text " ) # c = CData.new( " Some text " )
# c.write( $stdout ) #-> <![CDATA[ Some text ]]> # c.write( $stdout ) #-> <![CDATA[ Some text ]]>
def write( output=$stdout, indent=-1, transitive=false, ie_hack=false ) def write( output=$stdout, indent=-1, transitive=false, ie_hack=false )
Kernel.warn( "#{self.class.name}.write is deprecated" ) Kernel.warn( "#{self.class.name}.write is deprecated" )
indent( output, indent ) indent( output, indent )
output << START output << START
output << @string output << @string
output << STOP output << STOP
end end
end end
end end

View file

@ -1,96 +1,96 @@
require "rexml/node" require "rexml/node"
module REXML module REXML
## ##
# A Child object is something contained by a parent, and this class # A Child object is something contained by a parent, and this class
# contains methods to support that. Most user code will not use this # contains methods to support that. Most user code will not use this
# class directly. # class directly.
class Child class Child
include Node include Node
attr_reader :parent # The Parent of this object attr_reader :parent # The Parent of this object
# Constructor. Any inheritors of this class should call super to make # Constructor. Any inheritors of this class should call super to make
# sure this method is called. # sure this method is called.
# parent:: # parent::
# if supplied, the parent of this child will be set to the # if supplied, the parent of this child will be set to the
# supplied value, and self will be added to the parent # supplied value, and self will be added to the parent
def initialize( parent = nil ) def initialize( parent = nil )
@parent = nil @parent = nil
# Declare @parent, but don't define it. The next line sets the # Declare @parent, but don't define it. The next line sets the
# parent. # parent.
parent.add( self ) if parent parent.add( self ) if parent
end end
# Replaces this object with another object. Basically, calls # Replaces this object with another object. Basically, calls
# Parent.replace_child # Parent.replace_child
# #
# Returns:: self # Returns:: self
def replace_with( child ) def replace_with( child )
@parent.replace_child( self, child ) @parent.replace_child( self, child )
self self
end end
# Removes this child from the parent. # Removes this child from the parent.
# #
# Returns:: self # Returns:: self
def remove def remove
unless @parent.nil? unless @parent.nil?
@parent.delete self @parent.delete self
end end
self self
end end
# Sets the parent of this child to the supplied argument. # Sets the parent of this child to the supplied argument.
# #
# other:: # other::
# Must be a Parent object. If this object is the same object as the # Must be a Parent object. If this object is the same object as the
# existing parent of this child, no action is taken. Otherwise, this # existing parent of this child, no action is taken. Otherwise, this
# child is removed from the current parent (if one exists), and is added # child is removed from the current parent (if one exists), and is added
# to the new parent. # to the new parent.
# Returns:: The parent added # Returns:: The parent added
def parent=( other ) def parent=( other )
return @parent if @parent == other return @parent if @parent == other
@parent.delete self if defined? @parent and @parent @parent.delete self if defined? @parent and @parent
@parent = other @parent = other
end end
alias :next_sibling :next_sibling_node alias :next_sibling :next_sibling_node
alias :previous_sibling :previous_sibling_node alias :previous_sibling :previous_sibling_node
# Sets the next sibling of this child. This can be used to insert a child # Sets the next sibling of this child. This can be used to insert a child
# after some other child. # after some other child.
# a = Element.new("a") # a = Element.new("a")
# b = a.add_element("b") # b = a.add_element("b")
# c = Element.new("c") # c = Element.new("c")
# b.next_sibling = c # b.next_sibling = c
# # => <a><b/><c/></a> # # => <a><b/><c/></a>
def next_sibling=( other ) def next_sibling=( other )
parent.insert_after self, other parent.insert_after self, other
end end
# Sets the previous sibling of this child. This can be used to insert a # Sets the previous sibling of this child. This can be used to insert a
# child before some other child. # child before some other child.
# a = Element.new("a") # a = Element.new("a")
# b = a.add_element("b") # b = a.add_element("b")
# c = Element.new("c") # c = Element.new("c")
# b.previous_sibling = c # b.previous_sibling = c
# # => <a><b/><c/></a> # # => <a><b/><c/></a>
def previous_sibling=(other) def previous_sibling=(other)
parent.insert_before self, other parent.insert_before self, other
end end
# Returns:: the document this child belongs to, or nil if this child # Returns:: the document this child belongs to, or nil if this child
# belongs to no document # belongs to no document
def document def document
return parent.document unless parent.nil? return parent.document unless parent.nil?
nil nil
end end
# This doesn't yet handle encodings # This doesn't yet handle encodings
def bytes def bytes
encoding = document.encoding encoding = document.encoding
to_s to_s
end end
end end
end end

View file

@ -1,80 +1,80 @@
require "rexml/child" require "rexml/child"
module REXML module REXML
## ##
# Represents an XML comment; that is, text between \<!-- ... --> # Represents an XML comment; that is, text between \<!-- ... -->
class Comment < Child class Comment < Child
include Comparable include Comparable
START = "<!--" START = "<!--"
STOP = "-->" STOP = "-->"
# The content text # The content text
attr_accessor :string attr_accessor :string
## ##
# Constructor. The first argument can be one of three types: # Constructor. The first argument can be one of three types:
# @param first If String, the contents of this comment are set to the # @param first If String, the contents of this comment are set to the
# argument. If Comment, the argument is duplicated. If # argument. If Comment, the argument is duplicated. If
# Source, the argument is scanned for a comment. # Source, the argument is scanned for a comment.
# @param second If the first argument is a Source, this argument # @param second If the first argument is a Source, this argument
# should be nil, not supplied, or a Parent to be set as the parent # should be nil, not supplied, or a Parent to be set as the parent
# of this object # of this object
def initialize( first, second = nil ) def initialize( first, second = nil )
#puts "IN COMMENT CONSTRUCTOR; SECOND IS #{second.type}" #puts "IN COMMENT CONSTRUCTOR; SECOND IS #{second.type}"
super(second) super(second)
if first.kind_of? String if first.kind_of? String
@string = first @string = first
elsif first.kind_of? Comment elsif first.kind_of? Comment
@string = first.string @string = first.string
end end
end end
def clone def clone
Comment.new self Comment.new self
end end
# == DEPRECATED # == DEPRECATED
# See REXML::Formatters # See REXML::Formatters
# #
# output:: # output::
# Where to write the string # Where to write the string
# indent:: # indent::
# An integer. If -1, no indenting will be used; otherwise, the # An integer. If -1, no indenting will be used; otherwise, the
# indentation will be this number of spaces, and children will be # indentation will be this number of spaces, and children will be
# indented an additional amount. # indented an additional amount.
# transitive:: # transitive::
# Ignored by this class. The contents of comments are never modified. # Ignored by this class. The contents of comments are never modified.
# ie_hack:: # ie_hack::
# Needed for conformity to the child API, but not used by this class. # Needed for conformity to the child API, but not used by this class.
def write( output, indent=-1, transitive=false, ie_hack=false ) def write( output, indent=-1, transitive=false, ie_hack=false )
Kernel.warn("Comment.write is deprecated. See REXML::Formatters") Kernel.warn("Comment.write is deprecated. See REXML::Formatters")
indent( output, indent ) indent( output, indent )
output << START output << START
output << @string output << @string
output << STOP output << STOP
end end
alias :to_s :string alias :to_s :string
## ##
# Compares this Comment to another; the contents of the comment are used # Compares this Comment to another; the contents of the comment are used
# in the comparison. # in the comparison.
def <=>(other) def <=>(other)
other.to_s <=> @string other.to_s <=> @string
end end
## ##
# Compares this Comment to another; the contents of the comment are used # Compares this Comment to another; the contents of the comment are used
# in the comparison. # in the comparison.
def ==( other ) def ==( other )
other.kind_of? Comment and other.kind_of? Comment and
(other <=> self) == 0 (other <=> self) == 0
end end
def node_type def node_type
:comment :comment
end end
end end
end end
#vim:ts=2 sw=2 noexpandtab: #vim:ts=2 sw=2 noexpandtab:

View file

@ -16,59 +16,59 @@ module REXML
# Document has a single child that can be accessed by root(). # Document has a single child that can be accessed by root().
# Note that if you want to have an XML declaration written for a document # Note that if you want to have an XML declaration written for a document
# you create, you must add one; REXML documents do not write a default # you create, you must add one; REXML documents do not write a default
# declaration for you. See |DECLARATION| and |write|. # declaration for you. See |DECLARATION| and |write|.
class Document < Element class Document < Element
# A convenient default XML declaration. If you want an XML declaration, # A convenient default XML declaration. If you want an XML declaration,
# the easiest way to add one is mydoc << Document::DECLARATION # the easiest way to add one is mydoc << Document::DECLARATION
# +DEPRECATED+ # +DEPRECATED+
# Use: mydoc << XMLDecl.default # Use: mydoc << XMLDecl.default
DECLARATION = XMLDecl.default DECLARATION = XMLDecl.default
# Constructor # Constructor
# @param source if supplied, must be a Document, String, or IO. # @param source if supplied, must be a Document, String, or IO.
# Documents have their context and Element attributes cloned. # Documents have their context and Element attributes cloned.
# Strings are expected to be valid XML documents. IOs are expected # Strings are expected to be valid XML documents. IOs are expected
# to be sources of valid XML documents. # to be sources of valid XML documents.
# @param context if supplied, contains the context of the document; # @param context if supplied, contains the context of the document;
# this should be a Hash. # this should be a Hash.
def initialize( source = nil, context = {} ) def initialize( source = nil, context = {} )
@entity_expansion_count = 0 @entity_expansion_count = 0
super() super()
@context = context @context = context
return if source.nil? return if source.nil?
if source.kind_of? Document if source.kind_of? Document
@context = source.context @context = source.context
super source super source
else else
build( source ) build( source )
end end
end end
def node_type def node_type
:document :document
end end
# Should be obvious # Should be obvious
def clone def clone
Document.new self Document.new self
end end
# According to the XML spec, a root node has no expanded name # According to the XML spec, a root node has no expanded name
def expanded_name def expanded_name
'' ''
#d = doc_type #d = doc_type
#d ? d.name : "UNDEFINED" #d ? d.name : "UNDEFINED"
end end
alias :name :expanded_name alias :name :expanded_name
# We override this, because XMLDecls and DocTypes must go at the start # We override this, because XMLDecls and DocTypes must go at the start
# of the document # of the document
def add( child ) def add( child )
if child.kind_of? XMLDecl if child.kind_of? XMLDecl
@children.unshift child @children.unshift child
child.parent = self child.parent = self
elsif child.kind_of? DocType elsif child.kind_of? DocType
# Find first Element or DocType node and insert the decl right # Find first Element or DocType node and insert the decl right
# before it. If there is no such node, just insert the child at the # before it. If there is no such node, just insert the child at the
# end. If there is a child and it is an DocType, then replace it. # end. If there is a child and it is an DocType, then replace it.
@ -86,60 +86,60 @@ module REXML
else # Insert at end of list else # Insert at end of list
@children[insert_before_index] = child @children[insert_before_index] = child
end end
child.parent = self child.parent = self
else else
rv = super rv = super
raise "attempted adding second root element to document" if @elements.size > 1 raise "attempted adding second root element to document" if @elements.size > 1
rv rv
end end
end end
alias :<< :add alias :<< :add
def add_element(arg=nil, arg2=nil) def add_element(arg=nil, arg2=nil)
rv = super rv = super
raise "attempted adding second root element to document" if @elements.size > 1 raise "attempted adding second root element to document" if @elements.size > 1
rv rv
end end
# @return the root Element of the document, or nil if this document # @return the root Element of the document, or nil if this document
# has no children. # has no children.
def root def root
elements[1] elements[1]
#self #self
#@children.find { |item| item.kind_of? Element } #@children.find { |item| item.kind_of? Element }
end end
# @return the DocType child of the document, if one exists, # @return the DocType child of the document, if one exists,
# and nil otherwise. # and nil otherwise.
def doctype def doctype
@children.find { |item| item.kind_of? DocType } @children.find { |item| item.kind_of? DocType }
end end
# @return the XMLDecl of this document; if no XMLDecl has been # @return the XMLDecl of this document; if no XMLDecl has been
# set, the default declaration is returned. # set, the default declaration is returned.
def xml_decl def xml_decl
rv = @children[0] rv = @children[0]
return rv if rv.kind_of? XMLDecl return rv if rv.kind_of? XMLDecl
rv = @children.unshift(XMLDecl.default)[0] rv = @children.unshift(XMLDecl.default)[0]
end end
# @return the XMLDecl version of this document as a String. # @return the XMLDecl version of this document as a String.
# If no XMLDecl has been set, returns the default version. # If no XMLDecl has been set, returns the default version.
def version def version
xml_decl().version xml_decl().version
end end
# @return the XMLDecl encoding of this document as a String. # @return the XMLDecl encoding of this document as a String.
# If no XMLDecl has been set, returns the default encoding. # If no XMLDecl has been set, returns the default encoding.
def encoding def encoding
xml_decl().encoding xml_decl().encoding
end end
# @return the XMLDecl standalone value of this document as a String. # @return the XMLDecl standalone value of this document as a String.
# If no XMLDecl has been set, returns the default setting. # If no XMLDecl has been set, returns the default setting.
def stand_alone? def stand_alone?
xml_decl().stand_alone? xml_decl().stand_alone?
end end
# Write the XML tree out, optionally with indent. This writes out the # Write the XML tree out, optionally with indent. This writes out the
# entire XML document, including XML declarations, doctype declarations, # entire XML document, including XML declarations, doctype declarations,
@ -194,12 +194,12 @@ module REXML
REXML::Formatters::Default.new( ie_hack ) REXML::Formatters::Default.new( ie_hack )
end end
formatter.write( self, output ) formatter.write( self, output )
end end
def Document::parse_stream( source, listener ) def Document::parse_stream( source, listener )
Parsers::StreamParser.new( source, listener ).parse Parsers::StreamParser.new( source, listener ).parse
end end
@@entity_expansion_limit = 10_000 @@entity_expansion_limit = 10_000
@ -222,9 +222,9 @@ module REXML
end end
end end
private private
def build( source ) def build( source )
Parsers::TreeParser.new( source, self ).parse Parsers::TreeParser.new( source, self ).parse
end end
end end
end end

View file

@ -1,10 +1,10 @@
require "rexml/child" require "rexml/child"
module REXML module REXML
module DTD module DTD
class AttlistDecl < Child class AttlistDecl < Child
START = "<!ATTLIST" START = "<!ATTLIST"
START_RE = /^\s*#{START}/um START_RE = /^\s*#{START}/um
PATTERN_RE = /\s*(#{START}.*?>)/um PATTERN_RE = /\s*(#{START}.*?>)/um
end end
end end
end end

View file

@ -6,46 +6,46 @@ require "rexml/dtd/attlistdecl"
require "rexml/parent" require "rexml/parent"
module REXML module REXML
module DTD module DTD
class Parser class Parser
def Parser.parse( input ) def Parser.parse( input )
case input case input
when String when String
parse_helper input parse_helper input
when File when File
parse_helper input.read parse_helper input.read
end end
end end
# Takes a String and parses it out # Takes a String and parses it out
def Parser.parse_helper( input ) def Parser.parse_helper( input )
contents = Parent.new contents = Parent.new
while input.size > 0 while input.size > 0
case input case input
when ElementDecl.PATTERN_RE when ElementDecl.PATTERN_RE
match = $& match = $&
source = $' source = $'
contents << ElementDecl.new( match ) contents << ElementDecl.new( match )
when AttlistDecl.PATTERN_RE when AttlistDecl.PATTERN_RE
matchdata = $~ matchdata = $~
source = $' source = $'
contents << AttlistDecl.new( matchdata ) contents << AttlistDecl.new( matchdata )
when EntityDecl.PATTERN_RE when EntityDecl.PATTERN_RE
matchdata = $~ matchdata = $~
source = $' source = $'
contents << EntityDecl.new( matchdata ) contents << EntityDecl.new( matchdata )
when Comment.PATTERN_RE when Comment.PATTERN_RE
matchdata = $~ matchdata = $~
source = $' source = $'
contents << Comment.new( matchdata ) contents << Comment.new( matchdata )
when NotationDecl.PATTERN_RE when NotationDecl.PATTERN_RE
matchdata = $~ matchdata = $~
source = $' source = $'
contents << NotationDecl.new( matchdata ) contents << NotationDecl.new( matchdata )
end end
end end
contents contents
end end
end end
end end
end end

View file

@ -1,17 +1,17 @@
require "rexml/child" require "rexml/child"
module REXML module REXML
module DTD module DTD
class ElementDecl < Child class ElementDecl < Child
START = "<!ELEMENT" START = "<!ELEMENT"
START_RE = /^\s*#{START}/um START_RE = /^\s*#{START}/um
PATTERN_RE = /^\s*(#{START}.*?)>/um PATTERN_RE = /^\s*(#{START}.*?)>/um
PATTERN_RE = /^\s*#{START}\s+((?:[:\w_][-\.\w_]*:)?[-!\*\.\w_]*)(.*?)>/ PATTERN_RE = /^\s*#{START}\s+((?:[:\w_][-\.\w_]*:)?[-!\*\.\w_]*)(.*?)>/
#\s*((((["']).*?\5)|[^\/'">]*)*?)(\/)?>/um, true) #\s*((((["']).*?\5)|[^\/'">]*)*?)(\/)?>/um, true)
def initialize match def initialize match
@name = match[1] @name = match[1]
@rest = match[2] @rest = match[2]
end end
end end
end end
end end

View file

@ -1,56 +1,56 @@
require "rexml/child" require "rexml/child"
module REXML module REXML
module DTD module DTD
class EntityDecl < Child class EntityDecl < Child
START = "<!ENTITY" START = "<!ENTITY"
START_RE = /^\s*#{START}/um START_RE = /^\s*#{START}/um
PUBLIC = /^\s*#{START}\s+(?:%\s+)?(\w+)\s+PUBLIC\s+((["']).*?\3)\s+((["']).*?\5)\s*>/um PUBLIC = /^\s*#{START}\s+(?:%\s+)?(\w+)\s+PUBLIC\s+((["']).*?\3)\s+((["']).*?\5)\s*>/um
SYSTEM = /^\s*#{START}\s+(?:%\s+)?(\w+)\s+SYSTEM\s+((["']).*?\3)(?:\s+NDATA\s+\w+)?\s*>/um SYSTEM = /^\s*#{START}\s+(?:%\s+)?(\w+)\s+SYSTEM\s+((["']).*?\3)(?:\s+NDATA\s+\w+)?\s*>/um
PLAIN = /^\s*#{START}\s+(\w+)\s+((["']).*?\3)\s*>/um PLAIN = /^\s*#{START}\s+(\w+)\s+((["']).*?\3)\s*>/um
PERCENT = /^\s*#{START}\s+%\s+(\w+)\s+((["']).*?\3)\s*>/um PERCENT = /^\s*#{START}\s+%\s+(\w+)\s+((["']).*?\3)\s*>/um
# <!ENTITY name SYSTEM "..."> # <!ENTITY name SYSTEM "...">
# <!ENTITY name "..."> # <!ENTITY name "...">
def initialize src def initialize src
super() super()
md = nil md = nil
if src.match( PUBLIC ) if src.match( PUBLIC )
md = src.match( PUBLIC, true ) md = src.match( PUBLIC, true )
@middle = "PUBLIC" @middle = "PUBLIC"
@content = "#{md[2]} #{md[4]}" @content = "#{md[2]} #{md[4]}"
elsif src.match( SYSTEM ) elsif src.match( SYSTEM )
md = src.match( SYSTEM, true ) md = src.match( SYSTEM, true )
@middle = "SYSTEM" @middle = "SYSTEM"
@content = md[2] @content = md[2]
elsif src.match( PLAIN ) elsif src.match( PLAIN )
md = src.match( PLAIN, true ) md = src.match( PLAIN, true )
@middle = "" @middle = ""
@content = md[2] @content = md[2]
elsif src.match( PERCENT ) elsif src.match( PERCENT )
md = src.match( PERCENT, true ) md = src.match( PERCENT, true )
@middle = "" @middle = ""
@content = md[2] @content = md[2]
end end
raise ParseException.new("failed Entity match", src) if md.nil? raise ParseException.new("failed Entity match", src) if md.nil?
@name = md[1] @name = md[1]
end end
def to_s def to_s
rv = "<!ENTITY #@name " rv = "<!ENTITY #@name "
rv << "#@middle " if @middle.size > 0 rv << "#@middle " if @middle.size > 0
rv << @content rv << @content
rv rv
end end
def write( output, indent ) def write( output, indent )
indent( output, indent ) indent( output, indent )
output << to_s output << to_s
end end
def EntityDecl.parse_source source, listener def EntityDecl.parse_source source, listener
md = source.match( PATTERN_RE, true ) md = source.match( PATTERN_RE, true )
thing = md[0].squeeze(" \t\n\r") thing = md[0].squeeze(" \t\n\r")
listener.send inspect.downcase, thing listener.send inspect.downcase, thing
end end
end end
end end
end end

View file

@ -1,39 +1,39 @@
require "rexml/child" require "rexml/child"
module REXML module REXML
module DTD module DTD
class NotationDecl < Child class NotationDecl < Child
START = "<!NOTATION" START = "<!NOTATION"
START_RE = /^\s*#{START}/um START_RE = /^\s*#{START}/um
PUBLIC = /^\s*#{START}\s+(\w[\w-]*)\s+(PUBLIC)\s+((["']).*?\4)\s*>/um PUBLIC = /^\s*#{START}\s+(\w[\w-]*)\s+(PUBLIC)\s+((["']).*?\4)\s*>/um
SYSTEM = /^\s*#{START}\s+(\w[\w-]*)\s+(SYSTEM)\s+((["']).*?\4)\s*>/um SYSTEM = /^\s*#{START}\s+(\w[\w-]*)\s+(SYSTEM)\s+((["']).*?\4)\s*>/um
def initialize src def initialize src
super() super()
if src.match( PUBLIC ) if src.match( PUBLIC )
md = src.match( PUBLIC, true ) md = src.match( PUBLIC, true )
elsif src.match( SYSTEM ) elsif src.match( SYSTEM )
md = src.match( SYSTEM, true ) md = src.match( SYSTEM, true )
else else
raise ParseException.new( "error parsing notation: no matching pattern", src ) raise ParseException.new( "error parsing notation: no matching pattern", src )
end end
@name = md[1] @name = md[1]
@middle = md[2] @middle = md[2]
@rest = md[3] @rest = md[3]
end end
def to_s def to_s
"<!NOTATION #@name #@middle #@rest>" "<!NOTATION #@name #@middle #@rest>"
end end
def write( output, indent ) def write( output, indent )
indent( output, indent ) indent( output, indent )
output << to_s output << to_s
end end
def NotationDecl.parse_source source, listener def NotationDecl.parse_source source, listener
md = source.match( PATTERN_RE, true ) md = source.match( PATTERN_RE, true )
thing = md[0].squeeze(" \t\n\r") thing = md[0].squeeze(" \t\n\r")
listener.send inspect.downcase, thing listener.send inspect.downcase, thing
end end
end end
end end
end end

View file

@ -3,12 +3,12 @@
# #
module REXML module REXML
module Encoding module Encoding
register( "CP-1252" ) do |o| register( "CP-1252" ) do |o|
class << o class << o
alias encode encode_cp1252 alias encode encode_cp1252
alias decode decode_cp1252 alias decode decode_cp1252
end end
end end
# Convert from UTF-8 # Convert from UTF-8
def encode_cp1252(content) def encode_cp1252(content)

View file

@ -3,10 +3,10 @@
# #
module REXML module REXML
module Encoding module Encoding
register("ISO-8859-15") do |o| register("ISO-8859-15") do |o|
alias encode to_iso_8859_15 alias encode to_iso_8859_15
alias decode from_iso_8859_15 alias decode from_iso_8859_15
end end
# Convert from UTF-8 # Convert from UTF-8
def to_iso_8859_15(content) def to_iso_8859_15(content)

View file

@ -3,164 +3,164 @@ require 'rexml/source'
require 'rexml/xmltokens' require 'rexml/xmltokens'
module REXML module REXML
# God, I hate DTDs. I really do. Why this idiot standard still # God, I hate DTDs. I really do. Why this idiot standard still
# plagues us is beyond me. # plagues us is beyond me.
class Entity < Child class Entity < Child
include XMLTokens include XMLTokens
PUBIDCHAR = "\x20\x0D\x0Aa-zA-Z0-9\\-()+,./:=?;!*@$_%#" PUBIDCHAR = "\x20\x0D\x0Aa-zA-Z0-9\\-()+,./:=?;!*@$_%#"
SYSTEMLITERAL = %Q{((?:"[^"]*")|(?:'[^']*'))} SYSTEMLITERAL = %Q{((?:"[^"]*")|(?:'[^']*'))}
PUBIDLITERAL = %Q{("[#{PUBIDCHAR}']*"|'[#{PUBIDCHAR}]*')} PUBIDLITERAL = %Q{("[#{PUBIDCHAR}']*"|'[#{PUBIDCHAR}]*')}
EXTERNALID = "(?:(?:(SYSTEM)\\s+#{SYSTEMLITERAL})|(?:(PUBLIC)\\s+#{PUBIDLITERAL}\\s+#{SYSTEMLITERAL}))" EXTERNALID = "(?:(?:(SYSTEM)\\s+#{SYSTEMLITERAL})|(?:(PUBLIC)\\s+#{PUBIDLITERAL}\\s+#{SYSTEMLITERAL}))"
NDATADECL = "\\s+NDATA\\s+#{NAME}" NDATADECL = "\\s+NDATA\\s+#{NAME}"
PEREFERENCE = "%#{NAME};" PEREFERENCE = "%#{NAME};"
ENTITYVALUE = %Q{((?:"(?:[^%&"]|#{PEREFERENCE}|#{REFERENCE})*")|(?:'([^%&']|#{PEREFERENCE}|#{REFERENCE})*'))} ENTITYVALUE = %Q{((?:"(?:[^%&"]|#{PEREFERENCE}|#{REFERENCE})*")|(?:'([^%&']|#{PEREFERENCE}|#{REFERENCE})*'))}
PEDEF = "(?:#{ENTITYVALUE}|#{EXTERNALID})" PEDEF = "(?:#{ENTITYVALUE}|#{EXTERNALID})"
ENTITYDEF = "(?:#{ENTITYVALUE}|(?:#{EXTERNALID}(#{NDATADECL})?))" ENTITYDEF = "(?:#{ENTITYVALUE}|(?:#{EXTERNALID}(#{NDATADECL})?))"
PEDECL = "<!ENTITY\\s+(%)\\s+#{NAME}\\s+#{PEDEF}\\s*>" PEDECL = "<!ENTITY\\s+(%)\\s+#{NAME}\\s+#{PEDEF}\\s*>"
GEDECL = "<!ENTITY\\s+#{NAME}\\s+#{ENTITYDEF}\\s*>" GEDECL = "<!ENTITY\\s+#{NAME}\\s+#{ENTITYDEF}\\s*>"
ENTITYDECL = /\s*(?:#{GEDECL})|(?:#{PEDECL})/um ENTITYDECL = /\s*(?:#{GEDECL})|(?:#{PEDECL})/um
attr_reader :name, :external, :ref, :ndata, :pubid attr_reader :name, :external, :ref, :ndata, :pubid
# Create a new entity. Simple entities can be constructed by passing a # Create a new entity. Simple entities can be constructed by passing a
# name, value to the constructor; this creates a generic, plain entity # name, value to the constructor; this creates a generic, plain entity
# reference. For anything more complicated, you have to pass a Source to # reference. For anything more complicated, you have to pass a Source to
# the constructor with the entity definiton, or use the accessor methods. # the constructor with the entity definiton, or use the accessor methods.
# +WARNING+: There is no validation of entity state except when the entity # +WARNING+: There is no validation of entity state except when the entity
# is read from a stream. If you start poking around with the accessors, # is read from a stream. If you start poking around with the accessors,
# you can easily create a non-conformant Entity. The best thing to do is # you can easily create a non-conformant Entity. The best thing to do is
# dump the stupid DTDs and use XMLSchema instead. # dump the stupid DTDs and use XMLSchema instead.
# #
# e = Entity.new( 'amp', '&' ) # e = Entity.new( 'amp', '&' )
def initialize stream, value=nil, parent=nil, reference=false def initialize stream, value=nil, parent=nil, reference=false
super(parent) super(parent)
@ndata = @pubid = @value = @external = nil @ndata = @pubid = @value = @external = nil
if stream.kind_of? Array if stream.kind_of? Array
@name = stream[1] @name = stream[1]
if stream[-1] == '%' if stream[-1] == '%'
@reference = true @reference = true
stream.pop stream.pop
else else
@reference = false @reference = false
end end
if stream[2] =~ /SYSTEM|PUBLIC/ if stream[2] =~ /SYSTEM|PUBLIC/
@external = stream[2] @external = stream[2]
if @external == 'SYSTEM' if @external == 'SYSTEM'
@ref = stream[3] @ref = stream[3]
@ndata = stream[4] if stream.size == 5 @ndata = stream[4] if stream.size == 5
else else
@pubid = stream[3] @pubid = stream[3]
@ref = stream[4] @ref = stream[4]
end end
else else
@value = stream[2] @value = stream[2]
end end
else else
@reference = reference @reference = reference
@external = nil @external = nil
@name = stream @name = stream
@value = value @value = value
end end
end end
# Evaluates whether the given string matchs an entity definition, # Evaluates whether the given string matchs an entity definition,
# returning true if so, and false otherwise. # returning true if so, and false otherwise.
def Entity::matches? string def Entity::matches? string
(ENTITYDECL =~ string) == 0 (ENTITYDECL =~ string) == 0
end end
# Evaluates to the unnormalized value of this entity; that is, replacing # Evaluates to the unnormalized value of this entity; that is, replacing
# all entities -- both %ent; and &ent; entities. This differs from # all entities -- both %ent; and &ent; entities. This differs from
# +value()+ in that +value+ only replaces %ent; entities. # +value()+ in that +value+ only replaces %ent; entities.
def unnormalized def unnormalized
document.record_entity_expansion document.record_entity_expansion
v = value() v = value()
return nil if v.nil? return nil if v.nil?
@unnormalized = Text::unnormalize(v, parent) @unnormalized = Text::unnormalize(v, parent)
@unnormalized @unnormalized
end end
#once :unnormalized #once :unnormalized
# Returns the value of this entity unprocessed -- raw. This is the # Returns the value of this entity unprocessed -- raw. This is the
# normalized value; that is, with all %ent; and &ent; entities intact # normalized value; that is, with all %ent; and &ent; entities intact
def normalized def normalized
@value @value
end end
# Write out a fully formed, correct entity definition (assuming the Entity # Write out a fully formed, correct entity definition (assuming the Entity
# object itself is valid.) # object itself is valid.)
# #
# out:: # out::
# An object implementing <TT>&lt;&lt;<TT> to which the entity will be # An object implementing <TT>&lt;&lt;<TT> to which the entity will be
# output # output
# indent:: # indent::
# *DEPRECATED* and ignored # *DEPRECATED* and ignored
def write out, indent=-1 def write out, indent=-1
out << '<!ENTITY ' out << '<!ENTITY '
out << '% ' if @reference out << '% ' if @reference
out << @name out << @name
out << ' ' out << ' '
if @external if @external
out << @external << ' ' out << @external << ' '
if @pubid if @pubid
q = @pubid.include?('"')?"'":'"' q = @pubid.include?('"')?"'":'"'
out << q << @pubid << q << ' ' out << q << @pubid << q << ' '
end end
q = @ref.include?('"')?"'":'"' q = @ref.include?('"')?"'":'"'
out << q << @ref << q out << q << @ref << q
out << ' NDATA ' << @ndata if @ndata out << ' NDATA ' << @ndata if @ndata
else else
q = @value.include?('"')?"'":'"' q = @value.include?('"')?"'":'"'
out << q << @value << q out << q << @value << q
end end
out << '>' out << '>'
end end
# Returns this entity as a string. See write(). # Returns this entity as a string. See write().
def to_s def to_s
rv = '' rv = ''
write rv write rv
rv rv
end end
PEREFERENCE_RE = /#{PEREFERENCE}/um PEREFERENCE_RE = /#{PEREFERENCE}/um
# Returns the value of this entity. At the moment, only internal entities # Returns the value of this entity. At the moment, only internal entities
# are processed. If the value contains internal references (IE, # are processed. If the value contains internal references (IE,
# %blah;), those are replaced with their values. IE, if the doctype # %blah;), those are replaced with their values. IE, if the doctype
# contains: # contains:
# <!ENTITY % foo "bar"> # <!ENTITY % foo "bar">
# <!ENTITY yada "nanoo %foo; nanoo> # <!ENTITY yada "nanoo %foo; nanoo>
# then: # then:
# doctype.entity('yada').value #-> "nanoo bar nanoo" # doctype.entity('yada').value #-> "nanoo bar nanoo"
def value def value
if @value if @value
matches = @value.scan(PEREFERENCE_RE) matches = @value.scan(PEREFERENCE_RE)
rv = @value.clone rv = @value.clone
if @parent if @parent
matches.each do |entity_reference| matches.each do |entity_reference|
entity_value = @parent.entity( entity_reference[0] ) entity_value = @parent.entity( entity_reference[0] )
rv.gsub!( /%#{entity_reference.join};/um, entity_value ) rv.gsub!( /%#{entity_reference.join};/um, entity_value )
end end
end end
return rv return rv
end end
nil nil
end end
end end
# This is a set of entity constants -- the ones defined in the XML # This is a set of entity constants -- the ones defined in the XML
# specification. These are +gt+, +lt+, +amp+, +quot+ and +apos+. # specification. These are +gt+, +lt+, +amp+, +quot+ and +apos+.
module EntityConst module EntityConst
# +>+ # +>+
GT = Entity.new( 'gt', '>' ) GT = Entity.new( 'gt', '>' )
# +<+ # +<+
LT = Entity.new( 'lt', '<' ) LT = Entity.new( 'lt', '<' )
# +&+ # +&+
AMP = Entity.new( 'amp', '&' ) AMP = Entity.new( 'amp', '&' )
# +"+ # +"+
QUOT = Entity.new( 'quot', '"' ) QUOT = Entity.new( 'quot', '"' )
# +'+ # +'+
APOS = Entity.new( 'apos', "'" ) APOS = Entity.new( 'apos', "'" )
end end
end end

View file

@ -2,62 +2,62 @@ require "rexml/child"
require "rexml/source" require "rexml/source"
module REXML module REXML
# Represents an XML Instruction; IE, <? ... ?> # Represents an XML Instruction; IE, <? ... ?>
# TODO: Add parent arg (3rd arg) to constructor # TODO: Add parent arg (3rd arg) to constructor
class Instruction < Child class Instruction < Child
START = '<\?' START = '<\?'
STOP = '\?>' STOP = '\?>'
# target is the "name" of the Instruction; IE, the "tag" in <?tag ...?> # target is the "name" of the Instruction; IE, the "tag" in <?tag ...?>
# content is everything else. # content is everything else.
attr_accessor :target, :content attr_accessor :target, :content
# Constructs a new Instruction # Constructs a new Instruction
# @param target can be one of a number of things. If String, then # @param target can be one of a number of things. If String, then
# the target of this instruction is set to this. If an Instruction, # the target of this instruction is set to this. If an Instruction,
# then the Instruction is shallowly cloned (target and content are # then the Instruction is shallowly cloned (target and content are
# copied). If a Source, then the source is scanned and parsed for # copied). If a Source, then the source is scanned and parsed for
# an Instruction declaration. # an Instruction declaration.
# @param content Must be either a String, or a Parent. Can only # @param content Must be either a String, or a Parent. Can only
# be a Parent if the target argument is a Source. Otherwise, this # be a Parent if the target argument is a Source. Otherwise, this
# String is set as the content of this instruction. # String is set as the content of this instruction.
def initialize(target, content=nil) def initialize(target, content=nil)
if target.kind_of? String if target.kind_of? String
super() super()
@target = target @target = target
@content = content @content = content
elsif target.kind_of? Instruction elsif target.kind_of? Instruction
super(content) super(content)
@target = target.target @target = target.target
@content = target.content @content = target.content
end end
@content.strip! if @content @content.strip! if @content
end end
def clone def clone
Instruction.new self Instruction.new self
end end
# == DEPRECATED # == DEPRECATED
# See the rexml/formatters package # See the rexml/formatters package
# #
def write writer, indent=-1, transitive=false, ie_hack=false def write writer, indent=-1, transitive=false, ie_hack=false
Kernel.warn( "#{self.class.name}.write is deprecated" ) Kernel.warn( "#{self.class.name}.write is deprecated" )
indent(writer, indent) indent(writer, indent)
writer << START.sub(/\\/u, '') writer << START.sub(/\\/u, '')
writer << @target writer << @target
writer << ' ' writer << ' '
writer << @content writer << @content
writer << STOP.sub(/\\/u, '') writer << STOP.sub(/\\/u, '')
end end
# @return true if other is an Instruction, and the content and target # @return true if other is an Instruction, and the content and target
# of the other matches the target and content of this object. # of the other matches the target and content of this object.
def ==( other ) def ==( other )
other.kind_of? Instruction and other.kind_of? Instruction and
other.target == @target and other.target == @target and
other.content == @content other.content == @content
end end
def node_type def node_type
:processing_instruction :processing_instruction
@ -66,5 +66,5 @@ module REXML
def inspect def inspect
"<?p-i #{target} ...?>" "<?p-i #{target} ...?>"
end end
end end
end end

View file

@ -2,195 +2,195 @@ require 'rexml/xmltokens'
require 'rexml/light/node' require 'rexml/light/node'
# [ :element, parent, name, attributes, children* ] # [ :element, parent, name, attributes, children* ]
# a = Node.new # a = Node.new
# a << "B" # => <a>B</a> # a << "B" # => <a>B</a>
# a.b # => <a>B<b/></a> # a.b # => <a>B<b/></a>
# a.b[1] # => <a>B<b/><b/><a> # a.b[1] # => <a>B<b/><b/><a>
# a.b[1]["x"] = "y" # => <a>B<b/><b x="y"/></a> # a.b[1]["x"] = "y" # => <a>B<b/><b x="y"/></a>
# a.b[0].c # => <a>B<b><c/></b><b x="y"/></a> # a.b[0].c # => <a>B<b><c/></b><b x="y"/></a>
# a.b.c << "D" # => <a>B<b><c>D</c></b><b x="y"/></a> # a.b.c << "D" # => <a>B<b><c>D</c></b><b x="y"/></a>
module REXML module REXML
module Light module Light
# Represents a tagged XML element. Elements are characterized by # Represents a tagged XML element. Elements are characterized by
# having children, attributes, and names, and can themselves be # having children, attributes, and names, and can themselves be
# children. # children.
class Node class Node
NAMESPLIT = /^(?:(#{XMLTokens::NCNAME_STR}):)?(#{XMLTokens::NCNAME_STR})/u NAMESPLIT = /^(?:(#{XMLTokens::NCNAME_STR}):)?(#{XMLTokens::NCNAME_STR})/u
PARENTS = [ :element, :document, :doctype ] PARENTS = [ :element, :document, :doctype ]
# Create a new element. # Create a new element.
def initialize node=nil def initialize node=nil
@node = node @node = node
if node.kind_of? String if node.kind_of? String
node = [ :text, node ] node = [ :text, node ]
elsif node.nil? elsif node.nil?
node = [ :document, nil, nil ] node = [ :document, nil, nil ]
elsif node[0] == :start_element elsif node[0] == :start_element
node[0] = :element node[0] = :element
elsif node[0] == :start_doctype elsif node[0] == :start_doctype
node[0] = :doctype node[0] = :doctype
elsif node[0] == :start_document elsif node[0] == :start_document
node[0] = :document node[0] = :document
end end
end end
def size def size
if PARENTS.include? @node[0] if PARENTS.include? @node[0]
@node[-1].size @node[-1].size
else else
0 0
end end
end end
def each( &block ) def each( &block )
size.times { |x| yield( at(x+4) ) } size.times { |x| yield( at(x+4) ) }
end end
def name def name
at(2) at(2)
end end
def name=( name_str, ns=nil ) def name=( name_str, ns=nil )
pfx = '' pfx = ''
pfx = "#{prefix(ns)}:" if ns pfx = "#{prefix(ns)}:" if ns
_old_put(2, "#{pfx}#{name_str}") _old_put(2, "#{pfx}#{name_str}")
end end
def parent=( node ) def parent=( node )
_old_put(1,node) _old_put(1,node)
end end
def local_name def local_name
namesplit namesplit
@name @name
end end
def local_name=( name_str ) def local_name=( name_str )
_old_put( 1, "#@prefix:#{name_str}" ) _old_put( 1, "#@prefix:#{name_str}" )
end end
def prefix( namespace=nil ) def prefix( namespace=nil )
prefix_of( self, namespace ) prefix_of( self, namespace )
end end
def namespace( prefix=prefix() ) def namespace( prefix=prefix() )
namespace_of( self, prefix ) namespace_of( self, prefix )
end end
def namespace=( namespace ) def namespace=( namespace )
@prefix = prefix( namespace ) @prefix = prefix( namespace )
pfx = '' pfx = ''
pfx = "#@prefix:" if @prefix.size > 0 pfx = "#@prefix:" if @prefix.size > 0
_old_put(1, "#{pfx}#@name") _old_put(1, "#{pfx}#@name")
end end
def []( reference, ns=nil ) def []( reference, ns=nil )
if reference.kind_of? String if reference.kind_of? String
pfx = '' pfx = ''
pfx = "#{prefix(ns)}:" if ns pfx = "#{prefix(ns)}:" if ns
at(3)["#{pfx}#{reference}"] at(3)["#{pfx}#{reference}"]
elsif reference.kind_of? Range elsif reference.kind_of? Range
_old_get( Range.new(4+reference.begin, reference.end, reference.exclude_end?) ) _old_get( Range.new(4+reference.begin, reference.end, reference.exclude_end?) )
else else
_old_get( 4+reference ) _old_get( 4+reference )
end end
end end
def =~( path ) def =~( path )
XPath.match( self, path ) XPath.match( self, path )
end end
# Doesn't handle namespaces yet # Doesn't handle namespaces yet
def []=( reference, ns, value=nil ) def []=( reference, ns, value=nil )
if reference.kind_of? String if reference.kind_of? String
value = ns unless value value = ns unless value
at( 3 )[reference] = value at( 3 )[reference] = value
elsif reference.kind_of? Range elsif reference.kind_of? Range
_old_put( Range.new(3+reference.begin, reference.end, reference.exclude_end?), ns ) _old_put( Range.new(3+reference.begin, reference.end, reference.exclude_end?), ns )
else else
if value if value
_old_put( 4+reference, ns, value ) _old_put( 4+reference, ns, value )
else else
_old_put( 4+reference, ns ) _old_put( 4+reference, ns )
end end
end end
end end
# Append a child to this element, optionally under a provided namespace. # Append a child to this element, optionally under a provided namespace.
# The namespace argument is ignored if the element argument is an Element # The namespace argument is ignored if the element argument is an Element
# object. Otherwise, the element argument is a string, the namespace (if # object. Otherwise, the element argument is a string, the namespace (if
# provided) is the namespace the element is created in. # provided) is the namespace the element is created in.
def << element def << element
if node_type() == :text if node_type() == :text
at(-1) << element at(-1) << element
else else
newnode = Node.new( element ) newnode = Node.new( element )
newnode.parent = self newnode.parent = self
self.push( newnode ) self.push( newnode )
end end
at(-1) at(-1)
end end
def node_type def node_type
_old_get(0) _old_get(0)
end end
def text=( foo ) def text=( foo )
replace = at(4).kind_of?(String)? 1 : 0 replace = at(4).kind_of?(String)? 1 : 0
self._old_put(4,replace, normalizefoo) self._old_put(4,replace, normalizefoo)
end end
def root def root
context = self context = self
context = context.at(1) while context.at(1) context = context.at(1) while context.at(1)
end end
def has_name?( name, namespace = '' ) def has_name?( name, namespace = '' )
at(3) == name and namespace() == namespace at(3) == name and namespace() == namespace
end end
def children def children
self self
end end
def parent def parent
at(1) at(1)
end end
def to_s def to_s
end end
private private
def namesplit def namesplit
return if @name.defined? return if @name.defined?
at(2) =~ NAMESPLIT at(2) =~ NAMESPLIT
@prefix = '' || $1 @prefix = '' || $1
@name = $2 @name = $2
end end
def namespace_of( node, prefix=nil ) def namespace_of( node, prefix=nil )
if not prefix if not prefix
name = at(2) name = at(2)
name =~ NAMESPLIT name =~ NAMESPLIT
prefix = $1 prefix = $1
end end
to_find = 'xmlns' to_find = 'xmlns'
to_find = "xmlns:#{prefix}" if not prefix.nil? to_find = "xmlns:#{prefix}" if not prefix.nil?
ns = at(3)[ to_find ] ns = at(3)[ to_find ]
ns ? ns : namespace_of( @node[0], prefix ) ns ? ns : namespace_of( @node[0], prefix )
end end
def prefix_of( node, namespace=nil ) def prefix_of( node, namespace=nil )
if not namespace if not namespace
name = node.name name = node.name
name =~ NAMESPLIT name =~ NAMESPLIT
$1 $1
else else
ns = at(3).find { |k,v| v == namespace } ns = at(3).find { |k,v| v == namespace }
ns ? ns : prefix_of( node.parent, namespace ) ns ? ns : prefix_of( node.parent, namespace )
end end
end end
end end
end end
end end

View file

@ -1,47 +1,47 @@
require 'rexml/xmltokens' require 'rexml/xmltokens'
module REXML module REXML
# Adds named attributes to an object. # Adds named attributes to an object.
module Namespace module Namespace
# The name of the object, valid if set # The name of the object, valid if set
attr_reader :name, :expanded_name attr_reader :name, :expanded_name
# The expanded name of the object, valid if name is set # The expanded name of the object, valid if name is set
attr_accessor :prefix attr_accessor :prefix
include XMLTokens include XMLTokens
NAMESPLIT = /^(?:(#{NCNAME_STR}):)?(#{NCNAME_STR})/u NAMESPLIT = /^(?:(#{NCNAME_STR}):)?(#{NCNAME_STR})/u
# Sets the name and the expanded name # Sets the name and the expanded name
def name=( name ) def name=( name )
@expanded_name = name @expanded_name = name
name =~ NAMESPLIT name =~ NAMESPLIT
if $1 if $1
@prefix = $1 @prefix = $1
else else
@prefix = "" @prefix = ""
@namespace = "" @namespace = ""
end end
@name = $2 @name = $2
end end
# Compares names optionally WITH namespaces # Compares names optionally WITH namespaces
def has_name?( other, ns=nil ) def has_name?( other, ns=nil )
if ns if ns
return (namespace() == ns and name() == other) return (namespace() == ns and name() == other)
elsif other.include? ":" elsif other.include? ":"
return fully_expanded_name == other return fully_expanded_name == other
else else
return name == other return name == other
end end
end end
alias :local_name :name alias :local_name :name
# Fully expand the name, even if the prefix wasn't specified in the # Fully expand the name, even if the prefix wasn't specified in the
# source file. # source file.
def fully_expanded_name def fully_expanded_name
ns = prefix ns = prefix
return "#{ns}:#@name" if ns.size > 0 return "#{ns}:#@name" if ns.size > 0
return @name return @name
end end
end end
end end

View file

@ -3,27 +3,27 @@ require "rexml/formatters/pretty"
require "rexml/formatters/default" require "rexml/formatters/default"
module REXML module REXML
# Represents a node in the tree. Nodes are never encountered except as # Represents a node in the tree. Nodes are never encountered except as
# superclasses of other objects. Nodes have siblings. # superclasses of other objects. Nodes have siblings.
module Node module Node
# @return the next sibling (nil if unset) # @return the next sibling (nil if unset)
def next_sibling_node def next_sibling_node
return nil if @parent.nil? return nil if @parent.nil?
@parent[ @parent.index(self) + 1 ] @parent[ @parent.index(self) + 1 ]
end end
# @return the previous sibling (nil if unset) # @return the previous sibling (nil if unset)
def previous_sibling_node def previous_sibling_node
return nil if @parent.nil? return nil if @parent.nil?
ind = @parent.index(self) ind = @parent.index(self)
return nil if ind == 0 return nil if ind == 0
@parent[ ind - 1 ] @parent[ ind - 1 ]
end end
# indent:: # indent::
# *DEPRECATED* This parameter is now ignored. See the formatters in the # *DEPRECATED* This parameter is now ignored. See the formatters in the
# REXML::Formatters package for changing the output style. # REXML::Formatters package for changing the output style.
def to_s indent=nil def to_s indent=nil
unless indent.nil? unless indent.nil?
Kernel.warn( "#{self.class.name}.to_s(indent) parameter is deprecated" ) Kernel.warn( "#{self.class.name}.to_s(indent) parameter is deprecated" )
f = REXML::Formatters::Pretty.new( indent ) f = REXML::Formatters::Pretty.new( indent )
@ -33,33 +33,33 @@ module REXML
f.write( self, rv = "" ) f.write( self, rv = "" )
end end
return rv return rv
end end
def indent to, ind def indent to, ind
if @parent and @parent.context and not @parent.context[:indentstyle].nil? then if @parent and @parent.context and not @parent.context[:indentstyle].nil? then
indentstyle = @parent.context[:indentstyle] indentstyle = @parent.context[:indentstyle]
else else
indentstyle = ' ' indentstyle = ' '
end end
to << indentstyle*ind unless ind<1 to << indentstyle*ind unless ind<1
end end
def parent? def parent?
false; false;
end end
# Visit all subnodes of +self+ recursively # Visit all subnodes of +self+ recursively
def each_recursive(&block) # :yields: node def each_recursive(&block) # :yields: node
self.elements.each {|node| self.elements.each {|node|
block.call(node) block.call(node)
node.each_recursive(&block) node.each_recursive(&block)
} }
end end
# Find (and return) first subnode (recursively) for which the block # Find (and return) first subnode (recursively) for which the block
# evaluates to true. Returns +nil+ if none was found. # evaluates to true. Returns +nil+ if none was found.
def find_first_recursive(&block) # :yields: node def find_first_recursive(&block) # :yields: node
each_recursive {|node| each_recursive {|node|
return node if block.call(node) return node if block.call(node)
} }
@ -71,5 +71,5 @@ module REXML
def index_in_parent def index_in_parent
parent.index(self)+1 parent.index(self)+1
end end
end end
end end

View file

@ -1,24 +1,24 @@
require 'rexml/encoding' require 'rexml/encoding'
module REXML module REXML
class Output class Output
include Encoding include Encoding
attr_reader :encoding attr_reader :encoding
def initialize real_IO, encd="iso-8859-1" def initialize real_IO, encd="iso-8859-1"
@output = real_IO @output = real_IO
self.encoding = encd self.encoding = encd
@to_utf = encd == UTF_8 ? false : true @to_utf = encd == UTF_8 ? false : true
end end
def <<( content ) def <<( content )
@output << (@to_utf ? self.encode(content) : content) @output << (@to_utf ? self.encode(content) : content)
end end
def to_s def to_s
"Output[#{encoding}]" "Output[#{encoding}]"
end end
end end
end end

View file

@ -3,12 +3,12 @@ require 'rexml/parsers/baseparser'
require 'rexml/light/node' require 'rexml/light/node'
module REXML module REXML
module Parsers module Parsers
class LightParser class LightParser
def initialize stream def initialize stream
@stream = stream @stream = stream
@parser = REXML::Parsers::BaseParser.new( stream ) @parser = REXML::Parsers::BaseParser.new( stream )
end end
def add_listener( listener ) def add_listener( listener )
@parser.add_listener( listener ) @parser.add_listener( listener )
@ -19,42 +19,42 @@ module REXML
@parser.stream = @stream @parser.stream = @stream
end end
def parse def parse
root = context = [ :document ] root = context = [ :document ]
while true while true
event = @parser.pull event = @parser.pull
case event[0] case event[0]
when :end_document when :end_document
break break
when :end_doctype when :end_doctype
context = context[1] context = context[1]
when :start_element, :start_doctype when :start_element, :start_doctype
new_node = event new_node = event
context << new_node context << new_node
new_node[1,0] = [context] new_node[1,0] = [context]
context = new_node context = new_node
when :end_element, :end_doctype when :end_element, :end_doctype
context = context[1] context = context[1]
else else
new_node = event new_node = event
context << new_node context << new_node
new_node[1,0] = [context] new_node[1,0] = [context]
end end
end end
root root
end end
end end
# An element is an array. The array contains: # An element is an array. The array contains:
# 0 The parent element # 0 The parent element
# 1 The tag name # 1 The tag name
# 2 A hash of attributes # 2 A hash of attributes
# 3..-1 The child elements # 3..-1 The child elements
# An element is an array of size > 3 # An element is an array of size > 3
# Text is a String # Text is a String
# PIs are [ :processing_instruction, target, data ] # PIs are [ :processing_instruction, target, data ]
# Comments are [ :comment, data ] # Comments are [ :comment, data ]
# DocTypes are DocType structs # DocTypes are DocType structs
# The root is an array with XMLDecls, Text, DocType, Array, Text # The root is an array with XMLDecls, Text, DocType, Array, Text
end end
end end

View file

@ -4,158 +4,158 @@ require 'rexml/namespace'
require 'rexml/text' require 'rexml/text'
module REXML module REXML
module Parsers module Parsers
# SAX2Parser # SAX2Parser
class SAX2Parser class SAX2Parser
def initialize source def initialize source
@parser = BaseParser.new(source) @parser = BaseParser.new(source)
@listeners = [] @listeners = []
@procs = [] @procs = []
@namespace_stack = [] @namespace_stack = []
@has_listeners = false @has_listeners = false
@tag_stack = [] @tag_stack = []
@entities = {} @entities = {}
end end
def source def source
@parser.source @parser.source
end end
def add_listener( listener ) def add_listener( listener )
@parser.add_listener( listener ) @parser.add_listener( listener )
end end
# Listen arguments: # Listen arguments:
# #
# Symbol, Array, Block # Symbol, Array, Block
# Listen to Symbol events on Array elements # Listen to Symbol events on Array elements
# Symbol, Block # Symbol, Block
# Listen to Symbol events # Listen to Symbol events
# Array, Listener # Array, Listener
# Listen to all events on Array elements # Listen to all events on Array elements
# Array, Block # Array, Block
# Listen to :start_element events on Array elements # Listen to :start_element events on Array elements
# Listener # Listener
# Listen to All events # Listen to All events
# #
# Symbol can be one of: :start_element, :end_element, # Symbol can be one of: :start_element, :end_element,
# :start_prefix_mapping, :end_prefix_mapping, :characters, # :start_prefix_mapping, :end_prefix_mapping, :characters,
# :processing_instruction, :doctype, :attlistdecl, :elementdecl, # :processing_instruction, :doctype, :attlistdecl, :elementdecl,
# :entitydecl, :notationdecl, :cdata, :xmldecl, :comment # :entitydecl, :notationdecl, :cdata, :xmldecl, :comment
# #
# There is an additional symbol that can be listened for: :progress. # There is an additional symbol that can be listened for: :progress.
# This will be called for every event generated, passing in the current # This will be called for every event generated, passing in the current
# stream position. # stream position.
# #
# Array contains regular expressions or strings which will be matched # Array contains regular expressions or strings which will be matched
# against fully qualified element names. # against fully qualified element names.
# #
# Listener must implement the methods in SAX2Listener # Listener must implement the methods in SAX2Listener
# #
# Block will be passed the same arguments as a SAX2Listener method would # Block will be passed the same arguments as a SAX2Listener method would
# be, where the method name is the same as the matched Symbol. # be, where the method name is the same as the matched Symbol.
# See the SAX2Listener for more information. # See the SAX2Listener for more information.
def listen( *args, &blok ) def listen( *args, &blok )
if args[0].kind_of? Symbol if args[0].kind_of? Symbol
if args.size == 2 if args.size == 2
args[1].each { |match| @procs << [args[0], match, blok] } args[1].each { |match| @procs << [args[0], match, blok] }
else else
add( [args[0], nil, blok] ) add( [args[0], nil, blok] )
end end
elsif args[0].kind_of? Array elsif args[0].kind_of? Array
if args.size == 2 if args.size == 2
args[0].each { |match| add( [nil, match, args[1]] ) } args[0].each { |match| add( [nil, match, args[1]] ) }
else else
args[0].each { |match| add( [ :start_element, match, blok ] ) } args[0].each { |match| add( [ :start_element, match, blok ] ) }
end end
else else
add([nil, nil, args[0]]) add([nil, nil, args[0]])
end end
end end
def deafen( listener=nil, &blok ) def deafen( listener=nil, &blok )
if listener if listener
@listeners.delete_if {|item| item[-1] == listener } @listeners.delete_if {|item| item[-1] == listener }
@has_listeners = false if @listeners.size == 0 @has_listeners = false if @listeners.size == 0
else else
@procs.delete_if {|item| item[-1] == blok } @procs.delete_if {|item| item[-1] == blok }
end end
end end
def parse def parse
@procs.each { |sym,match,block| block.call if sym == :start_document } @procs.each { |sym,match,block| block.call if sym == :start_document }
@listeners.each { |sym,match,block| @listeners.each { |sym,match,block|
block.start_document if sym == :start_document or sym.nil? block.start_document if sym == :start_document or sym.nil?
} }
root = context = [] root = context = []
while true while true
event = @parser.pull event = @parser.pull
case event[0] case event[0]
when :end_document when :end_document
handle( :end_document ) handle( :end_document )
break break
when :start_doctype when :start_doctype
handle( :doctype, *event[1..-1]) handle( :doctype, *event[1..-1])
when :end_doctype when :end_doctype
context = context[1] context = context[1]
when :start_element when :start_element
@tag_stack.push(event[1]) @tag_stack.push(event[1])
# find the observers for namespaces # find the observers for namespaces
procs = get_procs( :start_prefix_mapping, event[1] ) procs = get_procs( :start_prefix_mapping, event[1] )
listeners = get_listeners( :start_prefix_mapping, event[1] ) listeners = get_listeners( :start_prefix_mapping, event[1] )
if procs or listeners if procs or listeners
# break out the namespace declarations # break out the namespace declarations
# The attributes live in event[2] # The attributes live in event[2]
event[2].each {|n, v| event[2][n] = @parser.normalize(v)} event[2].each {|n, v| event[2][n] = @parser.normalize(v)}
nsdecl = event[2].find_all { |n, value| n =~ /^xmlns(:|$)/ } nsdecl = event[2].find_all { |n, value| n =~ /^xmlns(:|$)/ }
nsdecl.collect! { |n, value| [ n[6..-1], value ] } nsdecl.collect! { |n, value| [ n[6..-1], value ] }
@namespace_stack.push({}) @namespace_stack.push({})
nsdecl.each do |n,v| nsdecl.each do |n,v|
@namespace_stack[-1][n] = v @namespace_stack[-1][n] = v
# notify observers of namespaces # notify observers of namespaces
procs.each { |ob| ob.call( n, v ) } if procs procs.each { |ob| ob.call( n, v ) } if procs
listeners.each { |ob| ob.start_prefix_mapping(n, v) } if listeners listeners.each { |ob| ob.start_prefix_mapping(n, v) } if listeners
end end
end end
event[1] =~ Namespace::NAMESPLIT event[1] =~ Namespace::NAMESPLIT
prefix = $1 prefix = $1
local = $2 local = $2
uri = get_namespace(prefix) uri = get_namespace(prefix)
# find the observers for start_element # find the observers for start_element
procs = get_procs( :start_element, event[1] ) procs = get_procs( :start_element, event[1] )
listeners = get_listeners( :start_element, event[1] ) listeners = get_listeners( :start_element, event[1] )
# notify observers # notify observers
procs.each { |ob| ob.call( uri, local, event[1], event[2] ) } if procs procs.each { |ob| ob.call( uri, local, event[1], event[2] ) } if procs
listeners.each { |ob| listeners.each { |ob|
ob.start_element( uri, local, event[1], event[2] ) ob.start_element( uri, local, event[1], event[2] )
} if listeners } if listeners
when :end_element when :end_element
@tag_stack.pop @tag_stack.pop
event[1] =~ Namespace::NAMESPLIT event[1] =~ Namespace::NAMESPLIT
prefix = $1 prefix = $1
local = $2 local = $2
uri = get_namespace(prefix) uri = get_namespace(prefix)
# find the observers for start_element # find the observers for start_element
procs = get_procs( :end_element, event[1] ) procs = get_procs( :end_element, event[1] )
listeners = get_listeners( :end_element, event[1] ) listeners = get_listeners( :end_element, event[1] )
# notify observers # notify observers
procs.each { |ob| ob.call( uri, local, event[1] ) } if procs procs.each { |ob| ob.call( uri, local, event[1] ) } if procs
listeners.each { |ob| listeners.each { |ob|
ob.end_element( uri, local, event[1] ) ob.end_element( uri, local, event[1] )
} if listeners } if listeners
namespace_mapping = @namespace_stack.pop namespace_mapping = @namespace_stack.pop
# find the observers for namespaces # find the observers for namespaces
procs = get_procs( :end_prefix_mapping, event[1] ) procs = get_procs( :end_prefix_mapping, event[1] )
listeners = get_listeners( :end_prefix_mapping, event[1] ) listeners = get_listeners( :end_prefix_mapping, event[1] )
if procs or listeners if procs or listeners
namespace_mapping.each do |ns_prefix, ns_uri| namespace_mapping.each do |ns_prefix, ns_uri|
# notify observers of namespaces # notify observers of namespaces
procs.each { |ob| ob.call( ns_prefix ) } if procs procs.each { |ob| ob.call( ns_prefix ) } if procs
listeners.each { |ob| ob.end_prefix_mapping(ns_prefix) } if listeners listeners.each { |ob| ob.end_prefix_mapping(ns_prefix) } if listeners
end end
end end
when :text when :text
#normalized = @parser.normalize( event[1] ) #normalized = @parser.normalize( event[1] )
#handle( :characters, normalized ) #handle( :characters, normalized )
copy = event[1].clone copy = event[1].clone
@ -177,71 +177,71 @@ module REXML
handle( :characters, copy ) handle( :characters, copy )
when :entitydecl when :entitydecl
@entities[ event[1] ] = event[2] if event.size == 3 @entities[ event[1] ] = event[2] if event.size == 3
handle( *event ) handle( *event )
when :processing_instruction, :comment, :attlistdecl, when :processing_instruction, :comment, :attlistdecl,
:elementdecl, :cdata, :notationdecl, :xmldecl :elementdecl, :cdata, :notationdecl, :xmldecl
handle( *event ) handle( *event )
end end
handle( :progress, @parser.position ) handle( :progress, @parser.position )
end end
end end
private private
def handle( symbol, *arguments ) def handle( symbol, *arguments )
tag = @tag_stack[-1] tag = @tag_stack[-1]
procs = get_procs( symbol, tag ) procs = get_procs( symbol, tag )
listeners = get_listeners( symbol, tag ) listeners = get_listeners( symbol, tag )
# notify observers # notify observers
procs.each { |ob| ob.call( *arguments ) } if procs procs.each { |ob| ob.call( *arguments ) } if procs
listeners.each { |l| listeners.each { |l|
l.send( symbol.to_s, *arguments ) l.send( symbol.to_s, *arguments )
} if listeners } if listeners
end end
# The following methods are duplicates, but it is faster than using # The following methods are duplicates, but it is faster than using
# a helper # a helper
def get_procs( symbol, name ) def get_procs( symbol, name )
return nil if @procs.size == 0 return nil if @procs.size == 0
@procs.find_all do |sym, match, block| @procs.find_all do |sym, match, block|
#puts sym.inspect+"=="+symbol.inspect+ "\t"+match.inspect+"=="+name.inspect+ "\t"+( (sym.nil? or symbol == sym) and ((name.nil? and match.nil?) or match.nil? or ( (name == match) or (match.kind_of? Regexp and name =~ match)))).to_s #puts sym.inspect+"=="+symbol.inspect+ "\t"+match.inspect+"=="+name.inspect+ "\t"+( (sym.nil? or symbol == sym) and ((name.nil? and match.nil?) or match.nil? or ( (name == match) or (match.kind_of? Regexp and name =~ match)))).to_s
( (
(sym.nil? or symbol == sym) and (sym.nil? or symbol == sym) and
((name.nil? and match.nil?) or match.nil? or ( ((name.nil? and match.nil?) or match.nil? or (
(name == match) or (name == match) or
(match.kind_of? Regexp and name =~ match) (match.kind_of? Regexp and name =~ match)
) )
) )
) )
end.collect{|x| x[-1]} end.collect{|x| x[-1]}
end end
def get_listeners( symbol, name ) def get_listeners( symbol, name )
return nil if @listeners.size == 0 return nil if @listeners.size == 0
@listeners.find_all do |sym, match, block| @listeners.find_all do |sym, match, block|
( (
(sym.nil? or symbol == sym) and (sym.nil? or symbol == sym) and
((name.nil? and match.nil?) or match.nil? or ( ((name.nil? and match.nil?) or match.nil? or (
(name == match) or (name == match) or
(match.kind_of? Regexp and name =~ match) (match.kind_of? Regexp and name =~ match)
) )
) )
) )
end.collect{|x| x[-1]} end.collect{|x| x[-1]}
end end
def add( pair ) def add( pair )
if pair[-1].respond_to? :call if pair[-1].respond_to? :call
@procs << pair unless @procs.include? pair @procs << pair unless @procs.include? pair
else else
@listeners << pair unless @listeners.include? pair @listeners << pair unless @listeners.include? pair
@has_listeners = true @has_listeners = true
end end
end end
def get_namespace( prefix ) def get_namespace( prefix )
uris = (@namespace_stack.find_all { |ns| not ns[prefix].nil? }) || uris = (@namespace_stack.find_all { |ns| not ns[prefix].nil? }) ||
(@namespace_stack.find { |ns| not ns[nil].nil? }) (@namespace_stack.find { |ns| not ns[nil].nil? })
uris[-1][prefix] unless uris.nil? or 0 == uris.size uris[-1][prefix] unless uris.nil? or 0 == uris.size
end end
end end
end end
end end

View file

@ -2,12 +2,12 @@ require 'rexml/parsers/streamparser'
require 'rexml/parsers/baseparser' require 'rexml/parsers/baseparser'
module REXML module REXML
module Parsers module Parsers
class UltraLightParser class UltraLightParser
def initialize stream def initialize stream
@stream = stream @stream = stream
@parser = REXML::Parsers::BaseParser.new( stream ) @parser = REXML::Parsers::BaseParser.new( stream )
end end
def add_listener( listener ) def add_listener( listener )
@parser.add_listener( listener ) @parser.add_listener( listener )
@ -18,39 +18,39 @@ module REXML
@parser.stream = @stream @parser.stream = @stream
end end
def parse def parse
root = context = [] root = context = []
while true while true
event = @parser.pull event = @parser.pull
case event[0] case event[0]
when :end_document when :end_document
break break
when :end_doctype when :end_doctype
context = context[1] context = context[1]
when :start_element, :doctype when :start_element, :doctype
context << event context << event
event[1,0] = [context] event[1,0] = [context]
context = event context = event
when :end_element when :end_element
context = context[1] context = context[1]
else else
context << event context << event
end end
end end
root root
end end
end end
# An element is an array. The array contains: # An element is an array. The array contains:
# 0 The parent element # 0 The parent element
# 1 The tag name # 1 The tag name
# 2 A hash of attributes # 2 A hash of attributes
# 3..-1 The child elements # 3..-1 The child elements
# An element is an array of size > 3 # An element is an array of size > 3
# Text is a String # Text is a String
# PIs are [ :processing_instruction, target, data ] # PIs are [ :processing_instruction, target, data ]
# Comments are [ :comment, data ] # Comments are [ :comment, data ]
# DocTypes are DocType structs # DocTypes are DocType structs
# The root is an array with XMLDecls, Text, DocType, Array, Text # The root is an array with XMLDecls, Text, DocType, Array, Text
end end
end end

View file

@ -39,10 +39,10 @@ module REXML
case op case op
when :node when :node
when :attribute when :attribute
string << "/" if string.size > 0 string << "/" if string.size > 0
string << "@" string << "@"
when :child when :child
string << "/" if string.size > 0 string << "/" if string.size > 0
when :descendant_or_self when :descendant_or_self
string << "/" string << "/"
when :self when :self
@ -51,8 +51,8 @@ module REXML
string << ".." string << ".."
when :any when :any
string << "*" string << "*"
when :text when :text
string << "text()" string << "text()"
when :following, :following_sibling, when :following, :following_sibling,
:ancestor, :ancestor_or_self, :descendant, :ancestor, :ancestor_or_self, :descendant,
:namespace, :preceding, :preceding_sibling :namespace, :preceding, :preceding_sibling
@ -70,13 +70,13 @@ module REXML
string << ']' string << ']'
when :document when :document
document = true document = true
when :function when :function
string << path.shift string << path.shift
string << "( " string << "( "
string << predicate_to_string( path.shift[0] ) {|x| abbreviate( x )} string << predicate_to_string( path.shift[0] ) {|x| abbreviate( x )}
string << " )" string << " )"
when :literal when :literal
string << %Q{ "#{path.shift}" } string << %Q{ "#{path.shift}" }
else else
string << "/" unless string.size == 0 string << "/" unless string.size == 0
string << "UNKNOWN(" string << "UNKNOWN("
@ -84,7 +84,7 @@ module REXML
string << ")" string << ")"
end end
end end
string = "/"+string if document string = "/"+string if document
return string return string
end end
@ -653,39 +653,39 @@ module REXML
def parse_args( string ) def parse_args( string )
arguments = [] arguments = []
ind = 0 ind = 0
inquot = false inquot = false
inapos = false inapos = false
depth = 1 depth = 1
begin begin
case string[ind] case string[ind]
when ?" when ?"
inquot = !inquot unless inapos inquot = !inquot unless inapos
when ?' when ?'
inapos = !inapos unless inquot inapos = !inapos unless inquot
else else
unless inquot or inapos unless inquot or inapos
case string[ind] case string[ind]
when ?( when ?(
depth += 1 depth += 1
if depth == 1 if depth == 1
string = string[1..-1] string = string[1..-1]
ind -= 1 ind -= 1
end end
when ?) when ?)
depth -= 1 depth -= 1
if depth == 0 if depth == 0
s = string[0,ind].strip s = string[0,ind].strip
arguments << s unless s == "" arguments << s unless s == ""
string = string[ind+1..-1] string = string[ind+1..-1]
end end
when ?, when ?,
if depth == 1 if depth == 1
s = string[0,ind].strip s = string[0,ind].strip
arguments << s unless s == "" arguments << s unless s == ""
string = string[ind+1..-1] string = string[ind+1..-1]
ind = -1 ind = -1
end end
end end
end end
end end
ind += 1 ind += 1

View file

@ -2,262 +2,262 @@ require 'rexml/functions'
require 'rexml/xmltokens' require 'rexml/xmltokens'
module REXML module REXML
class QuickPath class QuickPath
include Functions include Functions
include XMLTokens include XMLTokens
EMPTY_HASH = {} EMPTY_HASH = {}
def QuickPath::first element, path, namespaces=EMPTY_HASH def QuickPath::first element, path, namespaces=EMPTY_HASH
match(element, path, namespaces)[0] match(element, path, namespaces)[0]
end end
def QuickPath::each element, path, namespaces=EMPTY_HASH, &block def QuickPath::each element, path, namespaces=EMPTY_HASH, &block
path = "*" unless path path = "*" unless path
match(element, path, namespaces).each( &block ) match(element, path, namespaces).each( &block )
end end
def QuickPath::match element, path, namespaces=EMPTY_HASH def QuickPath::match element, path, namespaces=EMPTY_HASH
raise "nil is not a valid xpath" unless path raise "nil is not a valid xpath" unless path
results = nil results = nil
Functions::namespace_context = namespaces Functions::namespace_context = namespaces
case path case path
when /^\/([^\/]|$)/u when /^\/([^\/]|$)/u
# match on root # match on root
path = path[1..-1] path = path[1..-1]
return [element.root.parent] if path == '' return [element.root.parent] if path == ''
results = filter([element.root], path) results = filter([element.root], path)
when /^[-\w]*::/u when /^[-\w]*::/u
results = filter([element], path) results = filter([element], path)
when /^\*/u when /^\*/u
results = filter(element.to_a, path) results = filter(element.to_a, path)
when /^[\[!\w:]/u when /^[\[!\w:]/u
# match on child # match on child
matches = [] matches = []
children = element.to_a children = element.to_a
results = filter(children, path) results = filter(children, path)
else else
results = filter([element], path) results = filter([element], path)
end end
return results return results
end end
# Given an array of nodes it filters the array based on the path. The # Given an array of nodes it filters the array based on the path. The
# result is that when this method returns, the array will contain elements # result is that when this method returns, the array will contain elements
# which match the path # which match the path
def QuickPath::filter elements, path def QuickPath::filter elements, path
return elements if path.nil? or path == '' or elements.size == 0 return elements if path.nil? or path == '' or elements.size == 0
case path case path
when /^\/\//u # Descendant when /^\/\//u # Descendant
return axe( elements, "descendant-or-self", $' ) return axe( elements, "descendant-or-self", $' )
when /^\/?\b(\w[-\w]*)\b::/u # Axe when /^\/?\b(\w[-\w]*)\b::/u # Axe
axe_name = $1 axe_name = $1
rest = $' rest = $'
return axe( elements, $1, $' ) return axe( elements, $1, $' )
when /^\/(?=\b([:!\w][-\.\w]*:)?[-!\*\.\w]*\b([^:(]|$)|\*)/u # Child when /^\/(?=\b([:!\w][-\.\w]*:)?[-!\*\.\w]*\b([^:(]|$)|\*)/u # Child
rest = $' rest = $'
results = [] results = []
elements.each do |element| elements.each do |element|
results |= filter( element.to_a, rest ) results |= filter( element.to_a, rest )
end end
return results return results
when /^\/?(\w[-\w]*)\(/u # / Function when /^\/?(\w[-\w]*)\(/u # / Function
return function( elements, $1, $' ) return function( elements, $1, $' )
when Namespace::NAMESPLIT # Element name when Namespace::NAMESPLIT # Element name
name = $2 name = $2
ns = $1 ns = $1
rest = $' rest = $'
elements.delete_if do |element| elements.delete_if do |element|
!(element.kind_of? Element and !(element.kind_of? Element and
(element.expanded_name == name or (element.expanded_name == name or
(element.name == name and (element.name == name and
element.namespace == Functions.namespace_context[ns]))) element.namespace == Functions.namespace_context[ns])))
end end
return filter( elements, rest ) return filter( elements, rest )
when /^\/\[/u when /^\/\[/u
matches = [] matches = []
elements.each do |element| elements.each do |element|
matches |= predicate( element.to_a, path[1..-1] ) if element.kind_of? Element matches |= predicate( element.to_a, path[1..-1] ) if element.kind_of? Element
end end
return matches return matches
when /^\[/u # Predicate when /^\[/u # Predicate
return predicate( elements, path ) return predicate( elements, path )
when /^\/?\.\.\./u # Ancestor when /^\/?\.\.\./u # Ancestor
return axe( elements, "ancestor", $' ) return axe( elements, "ancestor", $' )
when /^\/?\.\./u # Parent when /^\/?\.\./u # Parent
return filter( elements.collect{|e|e.parent}, $' ) return filter( elements.collect{|e|e.parent}, $' )
when /^\/?\./u # Self when /^\/?\./u # Self
return filter( elements, $' ) return filter( elements, $' )
when /^\*/u # Any when /^\*/u # Any
results = [] results = []
elements.each do |element| elements.each do |element|
results |= filter( [element], $' ) if element.kind_of? Element results |= filter( [element], $' ) if element.kind_of? Element
#if element.kind_of? Element #if element.kind_of? Element
# children = element.to_a # children = element.to_a
# children.delete_if { |child| !child.kind_of?(Element) } # children.delete_if { |child| !child.kind_of?(Element) }
# results |= filter( children, $' ) # results |= filter( children, $' )
#end #end
end end
return results return results
end end
return [] return []
end end
def QuickPath::axe( elements, axe_name, rest ) def QuickPath::axe( elements, axe_name, rest )
matches = [] matches = []
matches = filter( elements.dup, rest ) if axe_name =~ /-or-self$/u matches = filter( elements.dup, rest ) if axe_name =~ /-or-self$/u
case axe_name case axe_name
when /^descendant/u when /^descendant/u
elements.each do |element| elements.each do |element|
matches |= filter( element.to_a, "descendant-or-self::#{rest}" ) if element.kind_of? Element matches |= filter( element.to_a, "descendant-or-self::#{rest}" ) if element.kind_of? Element
end end
when /^ancestor/u when /^ancestor/u
elements.each do |element| elements.each do |element|
while element.parent while element.parent
matches << element.parent matches << element.parent
element = element.parent element = element.parent
end end
end end
matches = filter( matches, rest ) matches = filter( matches, rest )
when "self" when "self"
matches = filter( elements, rest ) matches = filter( elements, rest )
when "child" when "child"
elements.each do |element| elements.each do |element|
matches |= filter( element.to_a, rest ) if element.kind_of? Element matches |= filter( element.to_a, rest ) if element.kind_of? Element
end end
when "attribute" when "attribute"
elements.each do |element| elements.each do |element|
matches << element.attributes[ rest ] if element.kind_of? Element matches << element.attributes[ rest ] if element.kind_of? Element
end end
when "parent" when "parent"
matches = filter(elements.collect{|element| element.parent}.uniq, rest) matches = filter(elements.collect{|element| element.parent}.uniq, rest)
when "following-sibling" when "following-sibling"
matches = filter(elements.collect{|element| element.next_sibling}.uniq, matches = filter(elements.collect{|element| element.next_sibling}.uniq,
rest) rest)
when "previous-sibling" when "previous-sibling"
matches = filter(elements.collect{|element| matches = filter(elements.collect{|element|
element.previous_sibling}.uniq, rest ) element.previous_sibling}.uniq, rest )
end end
return matches.uniq return matches.uniq
end end
# A predicate filters a node-set with respect to an axis to produce a # A predicate filters a node-set with respect to an axis to produce a
# new node-set. For each node in the node-set to be filtered, the # new node-set. For each node in the node-set to be filtered, the
# PredicateExpr is evaluated with that node as the context node, with # PredicateExpr is evaluated with that node as the context node, with
# the number of nodes in the node-set as the context size, and with the # the number of nodes in the node-set as the context size, and with the
# proximity position of the node in the node-set with respect to the # proximity position of the node in the node-set with respect to the
# axis as the context position; if PredicateExpr evaluates to true for # axis as the context position; if PredicateExpr evaluates to true for
# that node, the node is included in the new node-set; otherwise, it is # that node, the node is included in the new node-set; otherwise, it is
# not included. # not included.
# #
# A PredicateExpr is evaluated by evaluating the Expr and converting # A PredicateExpr is evaluated by evaluating the Expr and converting
# the result to a boolean. If the result is a number, the result will # the result to a boolean. If the result is a number, the result will
# be converted to true if the number is equal to the context position # be converted to true if the number is equal to the context position
# and will be converted to false otherwise; if the result is not a # and will be converted to false otherwise; if the result is not a
# number, then the result will be converted as if by a call to the # number, then the result will be converted as if by a call to the
# boolean function. Thus a location path para[3] is equivalent to # boolean function. Thus a location path para[3] is equivalent to
# para[position()=3]. # para[position()=3].
def QuickPath::predicate( elements, path ) def QuickPath::predicate( elements, path )
ind = 1 ind = 1
bcount = 1 bcount = 1
while bcount > 0 while bcount > 0
bcount += 1 if path[ind] == ?[ bcount += 1 if path[ind] == ?[
bcount -= 1 if path[ind] == ?] bcount -= 1 if path[ind] == ?]
ind += 1 ind += 1
end end
ind -= 1 ind -= 1
predicate = path[1..ind-1] predicate = path[1..ind-1]
rest = path[ind+1..-1] rest = path[ind+1..-1]
# have to change 'a [=<>] b [=<>] c' into 'a [=<>] b and b [=<>] c' # have to change 'a [=<>] b [=<>] c' into 'a [=<>] b and b [=<>] c'
predicate.gsub!( /([^\s(and)(or)<>=]+)\s*([<>=])\s*([^\s(and)(or)<>=]+)\s*([<>=])\s*([^\s(and)(or)<>=]+)/u, predicate.gsub!( /([^\s(and)(or)<>=]+)\s*([<>=])\s*([^\s(and)(or)<>=]+)\s*([<>=])\s*([^\s(and)(or)<>=]+)/u,
'\1 \2 \3 and \3 \4 \5' ) '\1 \2 \3 and \3 \4 \5' )
# Let's do some Ruby trickery to avoid some work: # Let's do some Ruby trickery to avoid some work:
predicate.gsub!( /&/u, "&&" ) predicate.gsub!( /&/u, "&&" )
predicate.gsub!( /=/u, "==" ) predicate.gsub!( /=/u, "==" )
predicate.gsub!( /@(\w[-\w.]*)/u, 'attribute("\1")' ) predicate.gsub!( /@(\w[-\w.]*)/u, 'attribute("\1")' )
predicate.gsub!( /\bmod\b/u, "%" ) predicate.gsub!( /\bmod\b/u, "%" )
predicate.gsub!( /\b(\w[-\w.]*\()/u ) { predicate.gsub!( /\b(\w[-\w.]*\()/u ) {
fname = $1 fname = $1
fname.gsub( /-/u, "_" ) fname.gsub( /-/u, "_" )
} }
Functions.pair = [ 0, elements.size ] Functions.pair = [ 0, elements.size ]
results = [] results = []
elements.each do |element| elements.each do |element|
Functions.pair[0] += 1 Functions.pair[0] += 1
Functions.node = element Functions.node = element
res = eval( predicate ) res = eval( predicate )
case res case res
when true when true
results << element results << element
when Fixnum when Fixnum
results << element if Functions.pair[0] == res results << element if Functions.pair[0] == res
when String when String
results << element results << element
end end
end end
return filter( results, rest ) return filter( results, rest )
end end
def QuickPath::attribute( name ) def QuickPath::attribute( name )
return Functions.node.attributes[name] if Functions.node.kind_of? Element return Functions.node.attributes[name] if Functions.node.kind_of? Element
end end
def QuickPath::name() def QuickPath::name()
return Functions.node.name if Functions.node.kind_of? Element return Functions.node.name if Functions.node.kind_of? Element
end end
def QuickPath::method_missing( id, *args ) def QuickPath::method_missing( id, *args )
begin begin
Functions.send( id.id2name, *args ) Functions.send( id.id2name, *args )
rescue Exception rescue Exception
raise "METHOD: #{id.id2name}(#{args.join ', '})\n#{$!.message}" raise "METHOD: #{id.id2name}(#{args.join ', '})\n#{$!.message}"
end end
end end
def QuickPath::function( elements, fname, rest ) def QuickPath::function( elements, fname, rest )
args = parse_args( elements, rest ) args = parse_args( elements, rest )
Functions.pair = [0, elements.size] Functions.pair = [0, elements.size]
results = [] results = []
elements.each do |element| elements.each do |element|
Functions.pair[0] += 1 Functions.pair[0] += 1
Functions.node = element Functions.node = element
res = Functions.send( fname, *args ) res = Functions.send( fname, *args )
case res case res
when true when true
results << element results << element
when Fixnum when Fixnum
results << element if Functions.pair[0] == res results << element if Functions.pair[0] == res
end end
end end
return results return results
end end
def QuickPath::parse_args( element, string ) def QuickPath::parse_args( element, string )
# /.*?(?:\)|,)/ # /.*?(?:\)|,)/
arguments = [] arguments = []
buffer = "" buffer = ""
while string and string != "" while string and string != ""
c = string[0] c = string[0]
string.sub!(/^./u, "") string.sub!(/^./u, "")
case c case c
when ?, when ?,
# if depth = 1, then we start a new argument # if depth = 1, then we start a new argument
arguments << evaluate( buffer ) arguments << evaluate( buffer )
#arguments << evaluate( string[0..count] ) #arguments << evaluate( string[0..count] )
when ?( when ?(
# start a new method call # start a new method call
function( element, buffer, string ) function( element, buffer, string )
buffer = "" buffer = ""
when ?) when ?)
# close the method call and return arguments # close the method call and return arguments
return arguments return arguments
else else
buffer << c buffer << c
end end
end end
"" ""
end end
end end
end end

View file

@ -1,97 +1,97 @@
module REXML module REXML
# A template for stream parser listeners. # A template for stream parser listeners.
# Note that the declarations (attlistdecl, elementdecl, etc) are trivially # Note that the declarations (attlistdecl, elementdecl, etc) are trivially
# processed; REXML doesn't yet handle doctype entity declarations, so you # processed; REXML doesn't yet handle doctype entity declarations, so you
# have to parse them out yourself. # have to parse them out yourself.
# === Missing methods from SAX2 # === Missing methods from SAX2
# ignorable_whitespace # ignorable_whitespace
# === Methods extending SAX2 # === Methods extending SAX2
# +WARNING+ # +WARNING+
# These methods are certainly going to change, until DTDs are fully # These methods are certainly going to change, until DTDs are fully
# supported. Be aware of this. # supported. Be aware of this.
# start_document # start_document
# end_document # end_document
# doctype # doctype
# elementdecl # elementdecl
# attlistdecl # attlistdecl
# entitydecl # entitydecl
# notationdecl # notationdecl
# cdata # cdata
# xmldecl # xmldecl
# comment # comment
module SAX2Listener module SAX2Listener
def start_document def start_document
end end
def end_document def end_document
end end
def start_prefix_mapping prefix, uri def start_prefix_mapping prefix, uri
end end
def end_prefix_mapping prefix def end_prefix_mapping prefix
end end
def start_element uri, localname, qname, attributes def start_element uri, localname, qname, attributes
end end
def end_element uri, localname, qname def end_element uri, localname, qname
end end
def characters text def characters text
end end
def processing_instruction target, data def processing_instruction target, data
end end
# Handles a doctype declaration. Any attributes of the doctype which are # Handles a doctype declaration. Any attributes of the doctype which are
# not supplied will be nil. # EG, <!DOCTYPE me PUBLIC "foo" "bar"> # not supplied will be nil. # EG, <!DOCTYPE me PUBLIC "foo" "bar">
# @p name the name of the doctype; EG, "me" # @p name the name of the doctype; EG, "me"
# @p pub_sys "PUBLIC", "SYSTEM", or nil. EG, "PUBLIC" # @p pub_sys "PUBLIC", "SYSTEM", or nil. EG, "PUBLIC"
# @p long_name the supplied long name, or nil. EG, "foo" # @p long_name the supplied long name, or nil. EG, "foo"
# @p uri the uri of the doctype, or nil. EG, "bar" # @p uri the uri of the doctype, or nil. EG, "bar"
def doctype name, pub_sys, long_name, uri def doctype name, pub_sys, long_name, uri
end end
# If a doctype includes an ATTLIST declaration, it will cause this # If a doctype includes an ATTLIST declaration, it will cause this
# method to be called. The content is the declaration itself, unparsed. # method to be called. The content is the declaration itself, unparsed.
# EG, <!ATTLIST el attr CDATA #REQUIRED> will come to this method as "el # EG, <!ATTLIST el attr CDATA #REQUIRED> will come to this method as "el
# attr CDATA #REQUIRED". This is the same for all of the .*decl # attr CDATA #REQUIRED". This is the same for all of the .*decl
# methods. # methods.
def attlistdecl(element, pairs, contents) def attlistdecl(element, pairs, contents)
end end
# <!ELEMENT ...> # <!ELEMENT ...>
def elementdecl content def elementdecl content
end end
# <!ENTITY ...> # <!ENTITY ...>
# The argument passed to this method is an array of the entity # The argument passed to this method is an array of the entity
# declaration. It can be in a number of formats, but in general it # declaration. It can be in a number of formats, but in general it
# returns (example, result): # returns (example, result):
# <!ENTITY % YN '"Yes"'> # <!ENTITY % YN '"Yes"'>
# ["%", "YN", "'\"Yes\"'", "\""] # ["%", "YN", "'\"Yes\"'", "\""]
# <!ENTITY % YN 'Yes'> # <!ENTITY % YN 'Yes'>
# ["%", "YN", "'Yes'", "s"] # ["%", "YN", "'Yes'", "s"]
# <!ENTITY WhatHeSaid "He said %YN;"> # <!ENTITY WhatHeSaid "He said %YN;">
# ["WhatHeSaid", "\"He said %YN;\"", "YN"] # ["WhatHeSaid", "\"He said %YN;\"", "YN"]
# <!ENTITY open-hatch SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml"> # <!ENTITY open-hatch SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">
# ["open-hatch", "SYSTEM", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""] # ["open-hatch", "SYSTEM", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""]
# <!ENTITY open-hatch PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN" "http://www.textuality.com/boilerplate/OpenHatch.xml"> # <!ENTITY open-hatch PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN" "http://www.textuality.com/boilerplate/OpenHatch.xml">
# ["open-hatch", "PUBLIC", "\"-//Textuality//TEXT Standard open-hatch boilerplate//EN\"", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""] # ["open-hatch", "PUBLIC", "\"-//Textuality//TEXT Standard open-hatch boilerplate//EN\"", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""]
# <!ENTITY hatch-pic SYSTEM "../grafix/OpenHatch.gif" NDATA gif> # <!ENTITY hatch-pic SYSTEM "../grafix/OpenHatch.gif" NDATA gif>
# ["hatch-pic", "SYSTEM", "\"../grafix/OpenHatch.gif\"", "\n\t\t\t\t\t\t\tNDATA gif", "gif"] # ["hatch-pic", "SYSTEM", "\"../grafix/OpenHatch.gif\"", "\n\t\t\t\t\t\t\tNDATA gif", "gif"]
def entitydecl name, decl def entitydecl name, decl
end end
# <!NOTATION ...> # <!NOTATION ...>
def notationdecl content def notationdecl content
end end
# Called when <![CDATA[ ... ]]> is encountered in a document. # Called when <![CDATA[ ... ]]> is encountered in a document.
# @p content "..." # @p content "..."
def cdata content def cdata content
end end
# Called when an XML PI is encountered in the document. # Called when an XML PI is encountered in the document.
# EG: <?xml version="1.0" encoding="utf"?> # EG: <?xml version="1.0" encoding="utf"?>
# @p version the version attribute value. EG, "1.0" # @p version the version attribute value. EG, "1.0"
# @p encoding the encoding attribute value, or nil. EG, "utf" # @p encoding the encoding attribute value, or nil. EG, "utf"
# @p standalone the standalone attribute value, or nil. EG, nil # @p standalone the standalone attribute value, or nil. EG, nil
# @p spaced the declaration is followed by a line break # @p spaced the declaration is followed by a line break
def xmldecl version, encoding, standalone def xmldecl version, encoding, standalone
end end
# Called when a comment is encountered. # Called when a comment is encountered.
# @p comment The content of the comment # @p comment The content of the comment
def comment comment def comment comment
end end
def progress position def progress position
end end
end end
end end

View file

@ -1,92 +1,92 @@
module REXML module REXML
# A template for stream parser listeners. # A template for stream parser listeners.
# Note that the declarations (attlistdecl, elementdecl, etc) are trivially # Note that the declarations (attlistdecl, elementdecl, etc) are trivially
# processed; REXML doesn't yet handle doctype entity declarations, so you # processed; REXML doesn't yet handle doctype entity declarations, so you
# have to parse them out yourself. # have to parse them out yourself.
module StreamListener module StreamListener
# Called when a tag is encountered. # Called when a tag is encountered.
# @p name the tag name # @p name the tag name
# @p attrs an array of arrays of attribute/value pairs, suitable for # @p attrs an array of arrays of attribute/value pairs, suitable for
# use with assoc or rassoc. IE, <tag attr1="value1" attr2="value2"> # use with assoc or rassoc. IE, <tag attr1="value1" attr2="value2">
# will result in # will result in
# tag_start( "tag", # [["attr1","value1"],["attr2","value2"]]) # tag_start( "tag", # [["attr1","value1"],["attr2","value2"]])
def tag_start name, attrs def tag_start name, attrs
end end
# Called when the end tag is reached. In the case of <tag/>, tag_end # Called when the end tag is reached. In the case of <tag/>, tag_end
# will be called immidiately after tag_start # will be called immidiately after tag_start
# @p the name of the tag # @p the name of the tag
def tag_end name def tag_end name
end end
# Called when text is encountered in the document # Called when text is encountered in the document
# @p text the text content. # @p text the text content.
def text text def text text
end end
# Called when an instruction is encountered. EG: <?xsl sheet='foo'?> # Called when an instruction is encountered. EG: <?xsl sheet='foo'?>
# @p name the instruction name; in the example, "xsl" # @p name the instruction name; in the example, "xsl"
# @p instruction the rest of the instruction. In the example, # @p instruction the rest of the instruction. In the example,
# "sheet='foo'" # "sheet='foo'"
def instruction name, instruction def instruction name, instruction
end end
# Called when a comment is encountered. # Called when a comment is encountered.
# @p comment The content of the comment # @p comment The content of the comment
def comment comment def comment comment
end end
# Handles a doctype declaration. Any attributes of the doctype which are # Handles a doctype declaration. Any attributes of the doctype which are
# not supplied will be nil. # EG, <!DOCTYPE me PUBLIC "foo" "bar"> # not supplied will be nil. # EG, <!DOCTYPE me PUBLIC "foo" "bar">
# @p name the name of the doctype; EG, "me" # @p name the name of the doctype; EG, "me"
# @p pub_sys "PUBLIC", "SYSTEM", or nil. EG, "PUBLIC" # @p pub_sys "PUBLIC", "SYSTEM", or nil. EG, "PUBLIC"
# @p long_name the supplied long name, or nil. EG, "foo" # @p long_name the supplied long name, or nil. EG, "foo"
# @p uri the uri of the doctype, or nil. EG, "bar" # @p uri the uri of the doctype, or nil. EG, "bar"
def doctype name, pub_sys, long_name, uri def doctype name, pub_sys, long_name, uri
end end
# Called when the doctype is done # Called when the doctype is done
def doctype_end def doctype_end
end end
# If a doctype includes an ATTLIST declaration, it will cause this # If a doctype includes an ATTLIST declaration, it will cause this
# method to be called. The content is the declaration itself, unparsed. # method to be called. The content is the declaration itself, unparsed.
# EG, <!ATTLIST el attr CDATA #REQUIRED> will come to this method as "el # EG, <!ATTLIST el attr CDATA #REQUIRED> will come to this method as "el
# attr CDATA #REQUIRED". This is the same for all of the .*decl # attr CDATA #REQUIRED". This is the same for all of the .*decl
# methods. # methods.
def attlistdecl element_name, attributes, raw_content def attlistdecl element_name, attributes, raw_content
end end
# <!ELEMENT ...> # <!ELEMENT ...>
def elementdecl content def elementdecl content
end end
# <!ENTITY ...> # <!ENTITY ...>
# The argument passed to this method is an array of the entity # The argument passed to this method is an array of the entity
# declaration. It can be in a number of formats, but in general it # declaration. It can be in a number of formats, but in general it
# returns (example, result): # returns (example, result):
# <!ENTITY % YN '"Yes"'> # <!ENTITY % YN '"Yes"'>
# ["%", "YN", "'\"Yes\"'", "\""] # ["%", "YN", "'\"Yes\"'", "\""]
# <!ENTITY % YN 'Yes'> # <!ENTITY % YN 'Yes'>
# ["%", "YN", "'Yes'", "s"] # ["%", "YN", "'Yes'", "s"]
# <!ENTITY WhatHeSaid "He said %YN;"> # <!ENTITY WhatHeSaid "He said %YN;">
# ["WhatHeSaid", "\"He said %YN;\"", "YN"] # ["WhatHeSaid", "\"He said %YN;\"", "YN"]
# <!ENTITY open-hatch SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml"> # <!ENTITY open-hatch SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">
# ["open-hatch", "SYSTEM", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""] # ["open-hatch", "SYSTEM", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""]
# <!ENTITY open-hatch PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN" "http://www.textuality.com/boilerplate/OpenHatch.xml"> # <!ENTITY open-hatch PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN" "http://www.textuality.com/boilerplate/OpenHatch.xml">
# ["open-hatch", "PUBLIC", "\"-//Textuality//TEXT Standard open-hatch boilerplate//EN\"", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""] # ["open-hatch", "PUBLIC", "\"-//Textuality//TEXT Standard open-hatch boilerplate//EN\"", "\"http://www.textuality.com/boilerplate/OpenHatch.xml\""]
# <!ENTITY hatch-pic SYSTEM "../grafix/OpenHatch.gif" NDATA gif> # <!ENTITY hatch-pic SYSTEM "../grafix/OpenHatch.gif" NDATA gif>
# ["hatch-pic", "SYSTEM", "\"../grafix/OpenHatch.gif\"", "\n\t\t\t\t\t\t\tNDATA gif", "gif"] # ["hatch-pic", "SYSTEM", "\"../grafix/OpenHatch.gif\"", "\n\t\t\t\t\t\t\tNDATA gif", "gif"]
def entitydecl content def entitydecl content
end end
# <!NOTATION ...> # <!NOTATION ...>
def notationdecl content def notationdecl content
end end
# Called when %foo; is encountered in a doctype declaration. # Called when %foo; is encountered in a doctype declaration.
# @p content "foo" # @p content "foo"
def entity content def entity content
end end
# Called when <![CDATA[ ... ]]> is encountered in a document. # Called when <![CDATA[ ... ]]> is encountered in a document.
# @p content "..." # @p content "..."
def cdata content def cdata content
end end
# Called when an XML PI is encountered in the document. # Called when an XML PI is encountered in the document.
# EG: <?xml version="1.0" encoding="utf"?> # EG: <?xml version="1.0" encoding="utf"?>
# @p version the version attribute value. EG, "1.0" # @p version the version attribute value. EG, "1.0"
# @p encoding the encoding attribute value, or nil. EG, "utf" # @p encoding the encoding attribute value, or nil. EG, "utf"
# @p standalone the standalone attribute value, or nil. EG, nil # @p standalone the standalone attribute value, or nil. EG, nil
def xmldecl version, encoding, standalone def xmldecl version, encoding, standalone
end end
end end
end end

View file

@ -2,40 +2,40 @@ require 'rexml/encoding'
require 'rexml/source' require 'rexml/source'
module REXML module REXML
# NEEDS DOCUMENTATION # NEEDS DOCUMENTATION
class XMLDecl < Child class XMLDecl < Child
include Encoding include Encoding
DEFAULT_VERSION = "1.0"; DEFAULT_VERSION = "1.0";
DEFAULT_ENCODING = "UTF-8"; DEFAULT_ENCODING = "UTF-8";
DEFAULT_STANDALONE = "no"; DEFAULT_STANDALONE = "no";
START = '<\?xml'; START = '<\?xml';
STOP = '\?>'; STOP = '\?>';
attr_accessor :version, :standalone attr_accessor :version, :standalone
attr_reader :writeencoding, :writethis attr_reader :writeencoding, :writethis
def initialize(version=DEFAULT_VERSION, encoding=nil, standalone=nil) def initialize(version=DEFAULT_VERSION, encoding=nil, standalone=nil)
@writethis = true @writethis = true
@writeencoding = !encoding.nil? @writeencoding = !encoding.nil?
if version.kind_of? XMLDecl if version.kind_of? XMLDecl
super() super()
@version = version.version @version = version.version
self.encoding = version.encoding self.encoding = version.encoding
@writeencoding = version.writeencoding @writeencoding = version.writeencoding
@standalone = version.standalone @standalone = version.standalone
else else
super() super()
@version = version @version = version
self.encoding = encoding self.encoding = encoding
@standalone = standalone @standalone = standalone
end end
@version = DEFAULT_VERSION if @version.nil? @version = DEFAULT_VERSION if @version.nil?
end end
def clone def clone
XMLDecl.new(self) XMLDecl.new(self)
end end
# indent:: # indent::
# Ignored. There must be no whitespace before an XML declaration # Ignored. There must be no whitespace before an XML declaration
@ -43,35 +43,35 @@ module REXML
# Ignored # Ignored
# ie_hack:: # ie_hack::
# Ignored # Ignored
def write(writer, indent=-1, transitive=false, ie_hack=false) def write(writer, indent=-1, transitive=false, ie_hack=false)
return nil unless @writethis or writer.kind_of? Output return nil unless @writethis or writer.kind_of? Output
writer << START.sub(/\\/u, '') writer << START.sub(/\\/u, '')
if writer.kind_of? Output if writer.kind_of? Output
writer << " #{content writer.encoding}" writer << " #{content writer.encoding}"
else else
writer << " #{content encoding}" writer << " #{content encoding}"
end end
writer << STOP.sub(/\\/u, '') writer << STOP.sub(/\\/u, '')
end end
def ==( other ) def ==( other )
other.kind_of?(XMLDecl) and other.kind_of?(XMLDecl) and
other.version == @version and other.version == @version and
other.encoding == self.encoding and other.encoding == self.encoding and
other.standalone == @standalone other.standalone == @standalone
end end
def xmldecl version, encoding, standalone def xmldecl version, encoding, standalone
@version = version @version = version
self.encoding = encoding self.encoding = encoding
@standalone = standalone @standalone = standalone
end end
def node_type def node_type
:xmldecl :xmldecl
end end
alias :stand_alone? :standalone alias :stand_alone? :standalone
alias :old_enc= :encoding= alias :old_enc= :encoding=
def encoding=( enc ) def encoding=( enc )
@ -108,12 +108,12 @@ module REXML
START.sub(/\\/u, '') + " ... " + STOP.sub(/\\/u, '') START.sub(/\\/u, '') + " ... " + STOP.sub(/\\/u, '')
end end
private private
def content(enc) def content(enc)
rv = "version='#@version'" rv = "version='#@version'"
rv << " encoding='#{enc}'" if @writeencoding || enc !~ /utf-8/i rv << " encoding='#{enc}'" if @writeencoding || enc !~ /utf-8/i
rv << " standalone='#@standalone'" if @standalone rv << " standalone='#@standalone'" if @standalone
rv rv
end end
end end
end end

View file

@ -1,18 +1,18 @@
module REXML module REXML
# Defines a number of tokens used for parsing XML. Not for general # Defines a number of tokens used for parsing XML. Not for general
# consumption. # consumption.
module XMLTokens module XMLTokens
NCNAME_STR= '[\w:][\-\w\d.]*' NCNAME_STR= '[\w:][\-\w\d.]*'
NAME_STR= "(?:#{NCNAME_STR}:)?#{NCNAME_STR}" NAME_STR= "(?:#{NCNAME_STR}:)?#{NCNAME_STR}"
NAMECHAR = '[\-\w\d\.:]' NAMECHAR = '[\-\w\d\.:]'
NAME = "([\\w:]#{NAMECHAR}*)" NAME = "([\\w:]#{NAMECHAR}*)"
NMTOKEN = "(?:#{NAMECHAR})+" NMTOKEN = "(?:#{NAMECHAR})+"
NMTOKENS = "#{NMTOKEN}(\\s+#{NMTOKEN})*" NMTOKENS = "#{NMTOKEN}(\\s+#{NMTOKEN})*"
REFERENCE = "(?:&#{NAME};|&#\\d+;|&#x[0-9a-fA-F]+;)" REFERENCE = "(?:&#{NAME};|&#\\d+;|&#x[0-9a-fA-F]+;)"
#REFERENCE = "(?:#{ENTITYREF}|#{CHARREF})" #REFERENCE = "(?:#{ENTITYREF}|#{CHARREF})"
#ENTITYREF = "&#{NAME};" #ENTITYREF = "&#{NAME};"
#CHARREF = "&#\\d+;|&#x[0-9a-fA-F]+;" #CHARREF = "&#\\d+;|&#x[0-9a-fA-F]+;"
end end
end end

View file

@ -2,65 +2,65 @@ require 'rexml/functions'
require 'rexml/xpath_parser' require 'rexml/xpath_parser'
module REXML module REXML
# Wrapper class. Use this class to access the XPath functions. # Wrapper class. Use this class to access the XPath functions.
class XPath class XPath
include Functions include Functions
EMPTY_HASH = {} EMPTY_HASH = {}
# Finds and returns the first node that matches the supplied xpath. # Finds and returns the first node that matches the supplied xpath.
# element:: # element::
# The context element # The context element
# path:: # path::
# The xpath to search for. If not supplied or nil, returns the first # The xpath to search for. If not supplied or nil, returns the first
# node matching '*'. # node matching '*'.
# namespaces:: # namespaces::
# If supplied, a Hash which defines a namespace mapping. # If supplied, a Hash which defines a namespace mapping.
# #
# XPath.first( node ) # XPath.first( node )
# XPath.first( doc, "//b"} ) # XPath.first( doc, "//b"} )
# XPath.first( node, "a/x:b", { "x"=>"http://doofus" } ) # XPath.first( node, "a/x:b", { "x"=>"http://doofus" } )
def XPath::first element, path=nil, namespaces=nil, variables={} def XPath::first element, path=nil, namespaces=nil, variables={}
raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.nil? or namespaces.kind_of?(Hash) raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.nil? or namespaces.kind_of?(Hash)
raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of?(Hash) raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of?(Hash)
parser = XPathParser.new parser = XPathParser.new
parser.namespaces = namespaces parser.namespaces = namespaces
parser.variables = variables parser.variables = variables
path = "*" unless path path = "*" unless path
element = [element] unless element.kind_of? Array element = [element] unless element.kind_of? Array
parser.parse(path, element).flatten[0] parser.parse(path, element).flatten[0]
end end
# Iterates over nodes that match the given path, calling the supplied # Iterates over nodes that match the given path, calling the supplied
# block with the match. # block with the match.
# element:: # element::
# The context element # The context element
# path:: # path::
# The xpath to search for. If not supplied or nil, defaults to '*' # The xpath to search for. If not supplied or nil, defaults to '*'
# namespaces:: # namespaces::
# If supplied, a Hash which defines a namespace mapping # If supplied, a Hash which defines a namespace mapping
# #
# XPath.each( node ) { |el| ... } # XPath.each( node ) { |el| ... }
# XPath.each( node, '/*[@attr='v']' ) { |el| ... } # XPath.each( node, '/*[@attr='v']' ) { |el| ... }
# XPath.each( node, 'ancestor::x' ) { |el| ... } # XPath.each( node, 'ancestor::x' ) { |el| ... }
def XPath::each element, path=nil, namespaces=nil, variables={}, &block def XPath::each element, path=nil, namespaces=nil, variables={}, &block
raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.nil? or namespaces.kind_of?(Hash) raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.nil? or namespaces.kind_of?(Hash)
raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of?(Hash) raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of?(Hash)
parser = XPathParser.new parser = XPathParser.new
parser.namespaces = namespaces parser.namespaces = namespaces
parser.variables = variables parser.variables = variables
path = "*" unless path path = "*" unless path
element = [element] unless element.kind_of? Array element = [element] unless element.kind_of? Array
parser.parse(path, element).each( &block ) parser.parse(path, element).each( &block )
end end
# Returns an array of nodes matching a given XPath. # Returns an array of nodes matching a given XPath.
def XPath::match element, path=nil, namespaces=nil, variables={} def XPath::match element, path=nil, namespaces=nil, variables={}
parser = XPathParser.new parser = XPathParser.new
parser.namespaces = namespaces parser.namespaces = namespaces
parser.variables = variables parser.variables = variables
path = "*" unless path path = "*" unless path
element = [element] unless element.kind_of? Array element = [element] unless element.kind_of? Array
parser.parse(path,element) parser.parse(path,element)
end end
end end
end end

View file

@ -419,10 +419,10 @@ module REXML
return @variables[ var_name ] return @variables[ var_name ]
# :and, :or, :eq, :neq, :lt, :lteq, :gt, :gteq # :and, :or, :eq, :neq, :lt, :lteq, :gt, :gteq
# TODO: Special case for :or and :and -- not evaluate the right # TODO: Special case for :or and :and -- not evaluate the right
# operand if the left alone determines result (i.e. is true for # operand if the left alone determines result (i.e. is true for
# :or and false for :and). # :or and false for :and).
when :eq, :neq, :lt, :lteq, :gt, :gteq, :and, :or when :eq, :neq, :lt, :lteq, :gt, :gteq, :or
left = expr( path_stack.shift, nodeset.dup, context ) left = expr( path_stack.shift, nodeset.dup, context )
#puts "LEFT => #{left.inspect} (#{left.class.name})" #puts "LEFT => #{left.inspect} (#{left.class.name})"
right = expr( path_stack.shift, nodeset.dup, context ) right = expr( path_stack.shift, nodeset.dup, context )
@ -675,7 +675,7 @@ module REXML
def equality_relational_compare( set1, op, set2 ) def equality_relational_compare( set1, op, set2 )
#puts "EQ_REL_COMP(#{set1.inspect} #{op.inspect} #{set2.inspect})" #puts "EQ_REL_COMP(#{set1.inspect} #{op.inspect} #{set2.inspect})"
if set1.kind_of? Array and set2.kind_of? Array if set1.kind_of? Array and set2.kind_of? Array
#puts "#{set1.size} & #{set2.size}" #puts "#{set1.size} & #{set2.size}"
if set1.size == 1 and set2.size == 1 if set1.size == 1 and set2.size == 1
set1 = set1[0] set1 = set1[0]
set2 = set2[0] set2 = set2[0]
@ -696,7 +696,7 @@ module REXML
return res return res
end end
end end
#puts "EQ_REL_COMP: #{set1.inspect} (#{set1.class.name}), #{op}, #{set2.inspect} (#{set2.class.name})" #puts "EQ_REL_COMP: #{set1.inspect} (#{set1.class.name}), #{op}, #{set2.inspect} (#{set2.class.name})"
#puts "COMPARING VALUES" #puts "COMPARING VALUES"
# If one is nodeset and other is number, compare number to each item # If one is nodeset and other is number, compare number to each item
# in nodeset s.t. number op number(string(item)) # in nodeset s.t. number op number(string(item))
@ -705,7 +705,7 @@ module REXML
# If one is nodeset and other is boolean, compare boolean to each item # If one is nodeset and other is boolean, compare boolean to each item
# in nodeset s.t. boolean op boolean(item) # in nodeset s.t. boolean op boolean(item)
if set1.kind_of? Array or set2.kind_of? Array if set1.kind_of? Array or set2.kind_of? Array
#puts "ISA ARRAY" #puts "ISA ARRAY"
if set1.kind_of? Array if set1.kind_of? Array
a = set1 a = set1
b = set2 b = set2
@ -724,7 +724,7 @@ module REXML
#puts "B = #{b.inspect}" #puts "B = #{b.inspect}"
return a.collect {|v| compare( Functions::number(v), op, b )} return a.collect {|v| compare( Functions::number(v), op, b )}
else else
#puts "Functions::string( #{b}(#{b.class.name}) ) = #{Functions::string(b)}" #puts "Functions::string( #{b}(#{b.class.name}) ) = #{Functions::string(b)}"
b = Functions::string( b ) b = Functions::string( b )
return a.collect { |v| compare( Functions::string(v), op, b ) } return a.collect { |v| compare( Functions::string(v), op, b ) }
end end

View file

@ -605,16 +605,16 @@ module XMLRPC
class Proxy class Proxy
def initialize(server, prefix, args=[], meth=:call, delim=".") def initialize(server, prefix, args=[], meth=:call, delim=".")
@server = server @server = server
@prefix = prefix ? prefix + delim : "" @prefix = prefix ? prefix + delim : ""
@args = args @args = args
@meth = meth @meth = meth
end end
def method_missing(mid, *args) def method_missing(mid, *args)
pre = @prefix + mid.to_s pre = @prefix + mid.to_s
arg = @args + args arg = @args + args
@server.send(@meth, pre, *arg) @server.send(@meth, pre, *arg)
end end
end # class Proxy end # class Proxy

View file

@ -15,11 +15,11 @@ module XMLRPC
class Abstract class Abstract
def ele(name, *children) def ele(name, *children)
element(name, nil, *children) element(name, nil, *children)
end end
def tag(name, txt) def tag(name, txt)
element(name, nil, text(txt)) element(name, nil, text(txt))
end end
end end
@ -27,19 +27,19 @@ module XMLRPC
class Simple < Abstract class Simple < Abstract
def document_to_str(doc) def document_to_str(doc)
doc doc
end end
def document(*params) def document(*params)
params.join("") params.join("")
end end
def pi(name, *params) def pi(name, *params)
"<?#{name} " + params.join(" ") + " ?>" "<?#{name} " + params.join(" ") + " ?>"
end end
def element(name, attrs, *children) def element(name, attrs, *children)
raise "attributes not yet implemented" unless attrs.nil? raise "attributes not yet implemented" unless attrs.nil?
if children.empty? if children.empty?
"<#{name}/>" "<#{name}/>"
else else
@ -61,27 +61,27 @@ module XMLRPC
class XMLParser < Abstract class XMLParser < Abstract
def initialize def initialize
require "xmltreebuilder" require "xmltreebuilder"
end end
def document_to_str(doc) def document_to_str(doc)
doc.to_s doc.to_s
end end
def document(*params) def document(*params)
XML::SimpleTree::Document.new(*params) XML::SimpleTree::Document.new(*params)
end end
def pi(name, *params) def pi(name, *params)
XML::SimpleTree::ProcessingInstruction.new(name, *params) XML::SimpleTree::ProcessingInstruction.new(name, *params)
end end
def element(name, attrs, *children) def element(name, attrs, *children)
XML::SimpleTree::Element.new(name, attrs, *children) XML::SimpleTree::Element.new(name, attrs, *children)
end end
def text(txt) def text(txt)
XML::SimpleTree::Text.new(txt) XML::SimpleTree::Text.new(txt)
end end
end # class XMLParser end # class XMLParser
@ -111,20 +111,20 @@ module XMLRPC
name = name.to_s name = name.to_s
if name !~ /[a-zA-Z0-9_.:\/]+/ if name !~ /[a-zA-Z0-9_.:\/]+/
raise ArgumentError, "Wrong XML-RPC method-name" raise ArgumentError, "Wrong XML-RPC method-name"
end end
parameter = params.collect do |param| parameter = params.collect do |param|
@writer.ele("param", conv2value(param)) @writer.ele("param", conv2value(param))
end end
tree = @writer.document( tree = @writer.document(
@writer.pi("xml", 'version="1.0"'), @writer.pi("xml", 'version="1.0"'),
@writer.ele("methodCall", @writer.ele("methodCall",
@writer.tag("methodName", name), @writer.tag("methodName", name),
@writer.ele("params", *parameter) @writer.ele("params", *parameter)
) )
) )
@writer.document_to_str(tree) + "\n" @writer.document_to_str(tree) + "\n"
end end
@ -144,23 +144,23 @@ module XMLRPC
def methodResponse(is_ret, *params) def methodResponse(is_ret, *params)
if is_ret if is_ret
resp = params.collect do |param| resp = params.collect do |param|
@writer.ele("param", conv2value(param)) @writer.ele("param", conv2value(param))
end end
resp = [@writer.ele("params", *resp)] resp = [@writer.ele("params", *resp)]
else else
if params.size != 1 or params[0] === XMLRPC::FaultException if params.size != 1 or params[0] === XMLRPC::FaultException
raise ArgumentError, "no valid fault-structure given" raise ArgumentError, "no valid fault-structure given"
end end
resp = @writer.ele("fault", conv2value(params[0].to_h)) resp = @writer.ele("fault", conv2value(params[0].to_h))
end end
tree = @writer.document( tree = @writer.document(
@writer.pi("xml", 'version="1.0"'), @writer.pi("xml", 'version="1.0"'),
@writer.ele("methodResponse", resp) @writer.ele("methodResponse", resp)
) )
@writer.document_to_str(tree) + "\n" @writer.document_to_str(tree) + "\n"
end end
@ -177,11 +177,11 @@ module XMLRPC
# #
def conv2value(param) def conv2value(param)
val = case param val = case param
when Fixnum when Fixnum
@writer.tag("i4", param.to_s) @writer.tag("i4", param.to_s)
when Bignum when Bignum
if Config::ENABLE_BIGINT if Config::ENABLE_BIGINT
@writer.tag("i4", param.to_s) @writer.tag("i4", param.to_s)
else else
@ -191,14 +191,14 @@ module XMLRPC
raise "Bignum is too big! Must be signed 32-bit integer!" raise "Bignum is too big! Must be signed 32-bit integer!"
end end
end end
when TrueClass, FalseClass when TrueClass, FalseClass
@writer.tag("boolean", param ? "1" : "0") @writer.tag("boolean", param ? "1" : "0")
when Symbol when Symbol
@writer.tag("string", param.to_s) @writer.tag("string", param.to_s)
when String when String
@writer.tag("string", param) @writer.tag("string", param)
when NilClass when NilClass
if Config::ENABLE_NIL_CREATE if Config::ENABLE_NIL_CREATE
@ -207,51 +207,51 @@ module XMLRPC
raise "Wrong type NilClass. Not allowed!" raise "Wrong type NilClass. Not allowed!"
end end
when Float when Float
@writer.tag("double", param.to_s) @writer.tag("double", param.to_s)
when Struct when Struct
h = param.members.collect do |key| h = param.members.collect do |key|
value = param[key] value = param[key]
@writer.ele("member", @writer.ele("member",
@writer.tag("name", key.to_s), @writer.tag("name", key.to_s),
conv2value(value) conv2value(value)
) )
end end
@writer.ele("struct", *h) @writer.ele("struct", *h)
when Hash when Hash
# TODO: can a Hash be empty? # TODO: can a Hash be empty?
h = param.collect do |key, value| h = param.collect do |key, value|
@writer.ele("member", @writer.ele("member",
@writer.tag("name", key.to_s), @writer.tag("name", key.to_s),
conv2value(value) conv2value(value)
) )
end end
@writer.ele("struct", *h) @writer.ele("struct", *h)
when Array when Array
# TODO: can an Array be empty? # TODO: can an Array be empty?
a = param.collect {|v| conv2value(v) } a = param.collect {|v| conv2value(v) }
@writer.ele("array", @writer.ele("array",
@writer.ele("data", *a) @writer.ele("data", *a)
) )
when Time, Date, ::DateTime when Time, Date, ::DateTime
@writer.tag("dateTime.iso8601", param.strftime("%Y%m%dT%H:%M:%S")) @writer.tag("dateTime.iso8601", param.strftime("%Y%m%dT%H:%M:%S"))
when XMLRPC::DateTime when XMLRPC::DateTime
@writer.tag("dateTime.iso8601", @writer.tag("dateTime.iso8601",
format("%.4d%02d%02dT%02d:%02d:%02d", *param.to_a)) format("%.4d%02d%02dT%02d:%02d:%02d", *param.to_a))
when XMLRPC::Base64 when XMLRPC::Base64
@writer.tag("base64", param.encoded) @writer.tag("base64", param.encoded)
else else
if Config::ENABLE_MARSHALLING and param.class.included_modules.include? XMLRPC::Marshallable if Config::ENABLE_MARSHALLING and param.class.included_modules.include? XMLRPC::Marshallable
# convert Ruby object into Hash # convert Ruby object into Hash
ret = {"___class___" => param.class.name} ret = {"___class___" => param.class.name}
@ -274,9 +274,9 @@ module XMLRPC
raise "Wrong type!" raise "Wrong type!"
end end
end end
end end
@writer.ele("value", val) @writer.ele("value", val)
end end
def wrong_type(value) def wrong_type(value)

View file

@ -156,7 +156,7 @@ private
# parse HTTP headers # parse HTTP headers
while (line=io.gets) !~ /^(\n|\r)/ while (line=io.gets) !~ /^(\n|\r)/
if line =~ /^([\w-]+):\s*(.*)$/ if line =~ /^([\w-]+):\s*(.*)$/
request.header[$1] = $2.strip request.header[$1] = $2.strip
end end
end end

View file

@ -160,11 +160,11 @@ module XMLRPC
class AbstractTreeParser class AbstractTreeParser
def parseMethodResponse(str) def parseMethodResponse(str)
methodResponse_document(createCleanedTree(str)) methodResponse_document(createCleanedTree(str))
end end
def parseMethodCall(str) def parseMethodCall(str)
methodCall_document(createCleanedTree(str)) methodCall_document(createCleanedTree(str))
end end
private private
@ -174,11 +174,11 @@ module XMLRPC
# and all comments # and all comments
# #
def removeWhitespacesAndComments(node) def removeWhitespacesAndComments(node)
remove = [] remove = []
childs = node.childNodes.to_a childs = node.childNodes.to_a
childs.each do |nd| childs.each do |nd|
case _nodeType(nd) case _nodeType(nd)
when :TEXT when :TEXT
# TODO: add nil? # TODO: add nil?
unless %w(i4 int boolean string double dateTime.iso8601 base64).include? node.nodeName unless %w(i4 int boolean string double dateTime.iso8601 base64).include? node.nodeName
@ -189,190 +189,190 @@ module XMLRPC
else else
remove << nd if nd.nodeValue.strip == "" remove << nd if nd.nodeValue.strip == ""
end end
end end
when :COMMENT when :COMMENT
remove << nd remove << nd
else else
removeWhitespacesAndComments(nd) removeWhitespacesAndComments(nd)
end end
end end
remove.each { |i| node.removeChild(i) } remove.each { |i| node.removeChild(i) }
end end
def nodeMustBe(node, name) def nodeMustBe(node, name)
cmp = case name cmp = case name
when Array when Array
name.include?(node.nodeName) name.include?(node.nodeName)
when String when String
name == node.nodeName name == node.nodeName
else else
raise "error" raise "error"
end end
if not cmp then if not cmp then
raise "wrong xml-rpc (name)" raise "wrong xml-rpc (name)"
end end
node node
end end
# #
# returns, when successfully the only child-node # returns, when successfully the only child-node
# #
def hasOnlyOneChild(node, name=nil) def hasOnlyOneChild(node, name=nil)
if node.childNodes.to_a.size != 1 if node.childNodes.to_a.size != 1
raise "wrong xml-rpc (size)" raise "wrong xml-rpc (size)"
end end
if name != nil then if name != nil then
nodeMustBe(node.firstChild, name) nodeMustBe(node.firstChild, name)
end end
end end
def assert(b) def assert(b)
if not b then if not b then
raise "assert-fail" raise "assert-fail"
end end
end end
# the node `node` has empty string or string # the node `node` has empty string or string
def text_zero_one(node) def text_zero_one(node)
nodes = node.childNodes.to_a.size nodes = node.childNodes.to_a.size
if nodes == 1 if nodes == 1
text(node.firstChild) text(node.firstChild)
elsif nodes == 0 elsif nodes == 0
"" ""
else else
raise "wrong xml-rpc (size)" raise "wrong xml-rpc (size)"
end end
end end
def integer(node) def integer(node)
#TODO: check string for float because to_i returnsa #TODO: check string for float because to_i returnsa
# 0 when wrong string # 0 when wrong string
nodeMustBe(node, %w(i4 int)) nodeMustBe(node, %w(i4 int))
hasOnlyOneChild(node) hasOnlyOneChild(node)
Convert.int(text(node.firstChild)) Convert.int(text(node.firstChild))
end end
def boolean(node) def boolean(node)
nodeMustBe(node, "boolean") nodeMustBe(node, "boolean")
hasOnlyOneChild(node) hasOnlyOneChild(node)
Convert.boolean(text(node.firstChild)) Convert.boolean(text(node.firstChild))
end end
def v_nil(node) def v_nil(node)
nodeMustBe(node, "nil") nodeMustBe(node, "nil")
assert( node.childNodes.to_a.size == 0 ) assert( node.childNodes.to_a.size == 0 )
nil nil
end end
def string(node) def string(node)
nodeMustBe(node, "string") nodeMustBe(node, "string")
text_zero_one(node) text_zero_one(node)
end end
def double(node) def double(node)
#TODO: check string for float because to_f returnsa #TODO: check string for float because to_f returnsa
# 0.0 when wrong string # 0.0 when wrong string
nodeMustBe(node, "double") nodeMustBe(node, "double")
hasOnlyOneChild(node) hasOnlyOneChild(node)
Convert.double(text(node.firstChild)) Convert.double(text(node.firstChild))
end end
def dateTime(node) def dateTime(node)
nodeMustBe(node, "dateTime.iso8601") nodeMustBe(node, "dateTime.iso8601")
hasOnlyOneChild(node) hasOnlyOneChild(node)
Convert.dateTime( text(node.firstChild) ) Convert.dateTime( text(node.firstChild) )
end end
def base64(node) def base64(node)
nodeMustBe(node, "base64") nodeMustBe(node, "base64")
#hasOnlyOneChild(node) #hasOnlyOneChild(node)
Convert.base64(text_zero_one(node)) Convert.base64(text_zero_one(node))
end end
def member(node) def member(node)
nodeMustBe(node, "member") nodeMustBe(node, "member")
assert( node.childNodes.to_a.size == 2 ) assert( node.childNodes.to_a.size == 2 )
[ name(node[0]), value(node[1]) ] [ name(node[0]), value(node[1]) ]
end end
def name(node) def name(node)
nodeMustBe(node, "name") nodeMustBe(node, "name")
#hasOnlyOneChild(node) #hasOnlyOneChild(node)
text_zero_one(node) text_zero_one(node)
end end
def array(node) def array(node)
nodeMustBe(node, "array") nodeMustBe(node, "array")
hasOnlyOneChild(node, "data") hasOnlyOneChild(node, "data")
data(node.firstChild) data(node.firstChild)
end end
def data(node) def data(node)
nodeMustBe(node, "data") nodeMustBe(node, "data")
node.childNodes.to_a.collect do |val| node.childNodes.to_a.collect do |val|
value(val) value(val)
end end
end end
def param(node) def param(node)
nodeMustBe(node, "param") nodeMustBe(node, "param")
hasOnlyOneChild(node, "value") hasOnlyOneChild(node, "value")
value(node.firstChild) value(node.firstChild)
end end
def methodResponse(node) def methodResponse(node)
nodeMustBe(node, "methodResponse") nodeMustBe(node, "methodResponse")
hasOnlyOneChild(node, %w(params fault)) hasOnlyOneChild(node, %w(params fault))
child = node.firstChild child = node.firstChild
case child.nodeName case child.nodeName
when "params" when "params"
[ true, params(child,false) ] [ true, params(child,false) ]
when "fault" when "fault"
[ false, fault(child) ] [ false, fault(child) ]
else else
raise "unexpected error" raise "unexpected error"
end end
end end
def methodName(node) def methodName(node)
nodeMustBe(node, "methodName") nodeMustBe(node, "methodName")
hasOnlyOneChild(node) hasOnlyOneChild(node)
text(node.firstChild) text(node.firstChild)
end end
def params(node, call=true) def params(node, call=true)
nodeMustBe(node, "params") nodeMustBe(node, "params")
if call if call
node.childNodes.to_a.collect do |n| node.childNodes.to_a.collect do |n|
param(n) param(n)
end end
else # response (only one param) else # response (only one param)
hasOnlyOneChild(node) hasOnlyOneChild(node)
param(node.firstChild) param(node.firstChild)
end end
end end
def fault(node) def fault(node)
nodeMustBe(node, "fault") nodeMustBe(node, "fault")
hasOnlyOneChild(node, "value") hasOnlyOneChild(node, "value")
f = value(node.firstChild) f = value(node.firstChild)
Convert.fault(f) Convert.fault(f)
end end
@ -380,76 +380,76 @@ module XMLRPC
# _nodeType is defined in the subclass # _nodeType is defined in the subclass
def text(node) def text(node)
assert( _nodeType(node) == :TEXT ) assert( _nodeType(node) == :TEXT )
assert( node.hasChildNodes == false ) assert( node.hasChildNodes == false )
assert( node.nodeValue != nil ) assert( node.nodeValue != nil )
node.nodeValue.to_s node.nodeValue.to_s
end end
def struct(node) def struct(node)
nodeMustBe(node, "struct") nodeMustBe(node, "struct")
hash = {} hash = {}
node.childNodes.to_a.each do |me| node.childNodes.to_a.each do |me|
n, v = member(me) n, v = member(me)
hash[n] = v hash[n] = v
end end
Convert.struct(hash) Convert.struct(hash)
end end
def value(node) def value(node)
nodeMustBe(node, "value") nodeMustBe(node, "value")
nodes = node.childNodes.to_a.size nodes = node.childNodes.to_a.size
if nodes == 0 if nodes == 0
return "" return ""
elsif nodes > 1 elsif nodes > 1
raise "wrong xml-rpc (size)" raise "wrong xml-rpc (size)"
end end
child = node.firstChild child = node.firstChild
case _nodeType(child) case _nodeType(child)
when :TEXT when :TEXT
text_zero_one(node) text_zero_one(node)
when :ELEMENT when :ELEMENT
case child.nodeName case child.nodeName
when "i4", "int" then integer(child) when "i4", "int" then integer(child)
when "boolean" then boolean(child) when "boolean" then boolean(child)
when "string" then string(child) when "string" then string(child)
when "double" then double(child) when "double" then double(child)
when "dateTime.iso8601" then dateTime(child) when "dateTime.iso8601" then dateTime(child)
when "base64" then base64(child) when "base64" then base64(child)
when "struct" then struct(child) when "struct" then struct(child)
when "array" then array(child) when "array" then array(child)
when "nil" when "nil"
if Config::ENABLE_NIL_PARSER if Config::ENABLE_NIL_PARSER
v_nil(child) v_nil(child)
else else
raise "wrong/unknown XML-RPC type 'nil'" raise "wrong/unknown XML-RPC type 'nil'"
end end
else else
raise "wrong/unknown XML-RPC type" raise "wrong/unknown XML-RPC type"
end end
else else
raise "wrong type of node" raise "wrong type of node"
end end
end end
def methodCall(node) def methodCall(node)
nodeMustBe(node, "methodCall") nodeMustBe(node, "methodCall")
assert( (1..2).include?( node.childNodes.to_a.size ) ) assert( (1..2).include?( node.childNodes.to_a.size ) )
name = methodName(node[0]) name = methodName(node[0])
if node.childNodes.to_a.size == 2 then if node.childNodes.to_a.size == 2 then
pa = params(node[1]) pa = params(node[1])
else # no parameters given else # no parameters given
pa = [] pa = []
end end
[name, pa] [name, pa]
end end
end # module TreeParserMixin end # module TreeParserMixin
@ -635,34 +635,34 @@ module XMLRPC
private private
def _nodeType(node) def _nodeType(node)
tp = node.nodeType tp = node.nodeType
if tp == XML::SimpleTree::Node::TEXT then :TEXT if tp == XML::SimpleTree::Node::TEXT then :TEXT
elsif tp == XML::SimpleTree::Node::COMMENT then :COMMENT elsif tp == XML::SimpleTree::Node::COMMENT then :COMMENT
elsif tp == XML::SimpleTree::Node::ELEMENT then :ELEMENT elsif tp == XML::SimpleTree::Node::ELEMENT then :ELEMENT
else :ELSE else :ELSE
end end
end end
def methodResponse_document(node) def methodResponse_document(node)
assert( node.nodeType == XML::SimpleTree::Node::DOCUMENT ) assert( node.nodeType == XML::SimpleTree::Node::DOCUMENT )
hasOnlyOneChild(node, "methodResponse") hasOnlyOneChild(node, "methodResponse")
methodResponse(node.firstChild) methodResponse(node.firstChild)
end end
def methodCall_document(node) def methodCall_document(node)
assert( node.nodeType == XML::SimpleTree::Node::DOCUMENT ) assert( node.nodeType == XML::SimpleTree::Node::DOCUMENT )
hasOnlyOneChild(node, "methodCall") hasOnlyOneChild(node, "methodCall")
methodCall(node.firstChild) methodCall(node.firstChild)
end end
def createCleanedTree(str) def createCleanedTree(str)
doc = XML::SimpleTreeBuilder.new.parse(str) doc = XML::SimpleTreeBuilder.new.parse(str)
doc.documentElement.normalize doc.documentElement.normalize
removeWhitespacesAndComments(doc) removeWhitespacesAndComments(doc)
doc doc
end end
end # class XMLParser end # class XMLParser
@ -676,21 +676,21 @@ module XMLRPC
private private
def _nodeType(node) def _nodeType(node)
node.nodeType node.nodeType
end end
def methodResponse_document(node) def methodResponse_document(node)
methodResponse(node) methodResponse(node)
end end
def methodCall_document(node) def methodCall_document(node)
methodCall(node) methodCall(node)
end end
def createCleanedTree(str) def createCleanedTree(str)
doc = ::NQXML::TreeParser.new(str).document.rootNode doc = ::NQXML::TreeParser.new(str).document.rootNode
removeWhitespacesAndComments(doc) removeWhitespacesAndComments(doc)
doc doc
end end
end # class NQXMLTreeParser end # class NQXMLTreeParser
@ -715,7 +715,7 @@ module XMLRPC
def parse(str) def parse(str)
parser = REXML::Document.parse_stream(str, self) parser = REXML::Document.parse_stream(str, self)
end end
end end
end end

View file

@ -37,7 +37,7 @@ module XMLRPC
def create def create
# if set_writer was not already called then call it now # if set_writer was not already called then call it now
if @create.nil? then if @create.nil? then
set_writer(Config::DEFAULT_WRITER.new) set_writer(Config::DEFAULT_WRITER.new)
end end
@create @create
end end
@ -45,7 +45,7 @@ module XMLRPC
def parser def parser
# if set_parser was not already called then call it now # if set_parser was not already called then call it now
if @parser.nil? then if @parser.nil? then
set_parser(Config::DEFAULT_PARSER.new) set_parser(Config::DEFAULT_PARSER.new)
end end
@parser @parser
end end

View file

@ -1464,7 +1464,7 @@ EOA
_assert_maker_atom_element(feed_type, maker_readers, feed_readers, _assert_maker_atom_element(feed_type, maker_readers, feed_readers,
maker_extractor, feed_extractor, maker_extractor, feed_extractor,
&block) &block)
end end
def assert_maker_atom_generator(feed_type, maker_readers, feed_readers, def assert_maker_atom_generator(feed_type, maker_readers, feed_readers,
not_set_error_name=nil, &block) not_set_error_name=nil, &block)

View file

@ -1260,7 +1260,7 @@ class TestArray < Test::Unit::TestCase
assert_equal(@cls[1,2], @cls[1, 2] | @cls[1, 2]) assert_equal(@cls[1,2], @cls[1, 2] | @cls[1, 2])
end end
def test_combination def test_combination
assert_equal(@cls[[]], @cls[1,2,3,4].combination(0).to_a) assert_equal(@cls[[]], @cls[1,2,3,4].combination(0).to_a)
assert_equal(@cls[[1],[2],[3],[4]], @cls[1,2,3,4].combination(1).to_a) assert_equal(@cls[[1],[2],[3],[4]], @cls[1,2,3,4].combination(1).to_a)
assert_equal(@cls[[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]], @cls[1,2,3,4].combination(2).to_a) assert_equal(@cls[[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]], @cls[1,2,3,4].combination(2).to_a)

View file

@ -263,5 +263,5 @@ EOS
# assert_raise(SyntaxError) { "\uDFFF" } # surrogate block # assert_raise(SyntaxError) { "\uDFFF" } # surrogate block
# assert_raise(SyntaxError) { "\uD847\uDD9A" } # surrogate pair # assert_raise(SyntaxError) { "\uD847\uDD9A" } # surrogate pair
end end
end end

View file

@ -16,7 +16,7 @@ class TestIOScanf < Test::Unit::TestCase;end
module ScanfTests module ScanfTests
def tests def tests
[ [
# Scratchpad # Scratchpad
@ -284,8 +284,8 @@ def tests
[" [%d,%f", " [10,1.1", [10,1.1] ], [" [%d,%f", " [10,1.1", [10,1.1] ],
] ]
end
end end
end
class TestStringScanf class TestStringScanf
include Scanf include Scanf