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

View file

@ -2,24 +2,24 @@ require "rexml/namespace"
require 'rexml/text'
module REXML
# Defines an Element Attribute; IE, a attribute=value pair, as in:
# <element attribute="value"/>. Attributes can be in their own
# namespaces. General users of REXML will not interact with the
# Attribute class much.
class Attribute
include Node
include Namespace
# Defines an Element Attribute; IE, a attribute=value pair, as in:
# <element attribute="value"/>. Attributes can be in their own
# namespaces. General users of REXML will not interact with the
# Attribute class much.
class Attribute
include Node
include Namespace
# The element to which this attribute belongs
attr_reader :element
# The normalized value of this attribute. That is, the attribute with
# entities intact.
attr_writer :normalized
PATTERN = /\s*(#{NAME_STR})\s*=\s*(["'])(.*?)\2/um
# The element to which this attribute belongs
attr_reader :element
# The normalized value of this attribute. That is, the attribute with
# entities intact.
attr_writer :normalized
PATTERN = /\s*(#{NAME_STR})\s*=\s*(["'])(.*?)\2/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
#
# first::
@ -36,137 +36,137 @@ module REXML
# Ignored unless +first+ is a String; otherwise, may be the Element
# parent of this attribute, or nil.
#
#
# Attribute.new( attribute_to_clone )
# Attribute.new( attribute_to_clone, parent_element )
# Attribute.new( "attr", "attr_value" )
# Attribute.new( "attr", "attr_value", parent_element )
def initialize( first, second=nil, parent=nil )
@normalized = @unnormalized = @element = nil
if first.kind_of? Attribute
self.name = first.expanded_name
@unnormalized = first.value
if second.kind_of? Element
@element = second
else
@element = first.element
end
elsif first.kind_of? String
@element = parent
self.name = first
@normalized = second.to_s
else
raise "illegal argument #{first.class.name} to Attribute constructor"
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
#
# Attribute.new( attribute_to_clone )
# Attribute.new( attribute_to_clone, parent_element )
# Attribute.new( "attr", "attr_value" )
# Attribute.new( "attr", "attr_value", parent_element )
def initialize( first, second=nil, parent=nil )
@normalized = @unnormalized = @element = nil
if first.kind_of? Attribute
self.name = first.expanded_name
@unnormalized = first.value
if second.kind_of? Element
@element = second
else
@element = first.element
end
elsif first.kind_of? String
@element = parent
self.name = first
@normalized = second.to_s
else
raise "illegal argument #{first.class.name} to Attribute constructor"
end
end
# Returns the attribute value, with entities replaced
def to_s
return @normalized if @normalized
# 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
@normalized = Text::normalize( @unnormalized, doctype )
@unnormalized = nil
# 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
# Returns the attribute value, with entities replaced
def to_s
return @normalized if @normalized
@normalized = Text::normalize( @unnormalized, doctype )
@unnormalized = nil
@normalized
end
end
# Returns the UNNORMALIZED value of this attribute. That is, entities
# have been expanded to their values
def value
return @unnormalized if @unnormalized
@unnormalized = Text::unnormalize( @normalized, doctype )
@normalized = nil
# Returns the UNNORMALIZED value of this attribute. That is, entities
# have been expanded to their values
def value
return @unnormalized if @unnormalized
@unnormalized = Text::unnormalize( @normalized, doctype )
@normalized = nil
@unnormalized
end
end
# Returns a copy of this attribute
def clone
Attribute.new self
end
# Returns a copy of this attribute
def clone
Attribute.new self
end
# Sets the element of which this object is an attribute. Normally, this
# is not directly called.
#
# Returns this attribute
def element=( element )
@element = element
# Sets the element of which this object is an attribute. Normally, this
# is not directly called.
#
# Returns this attribute
def element=( element )
@element = element
if @normalized
Text.check( @normalized, NEEDS_A_SECOND_CHECK, doctype )
end
self
end
self
end
# Removes this Attribute from the tree, and returns true if successfull
#
# This method is usually not called directly.
def remove
@element.attributes.delete self.name unless @element.nil?
end
# Removes this Attribute from the tree, and returns true if successfull
#
# This method is usually not called directly.
def remove
@element.attributes.delete self.name unless @element.nil?
end
# Writes this attribute (EG, puts 'key="value"' to the output)
def write( output, indent=-1 )
output << to_string
end
# Writes this attribute (EG, puts 'key="value"' to the output)
def write( output, indent=-1 )
output << to_string
end
def node_type
:attribute
@ -183,6 +183,6 @@ module REXML
path += "/@#{self.expanded_name}"
return path
end
end
end
end
#vim:ts=2 sw=2 noexpandtab:

View file

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

View file

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

View file

@ -1,80 +1,80 @@
require "rexml/child"
module REXML
##
# Represents an XML comment; that is, text between \<!-- ... -->
class Comment < Child
include Comparable
START = "<!--"
STOP = "-->"
##
# Represents an XML comment; that is, text between \<!-- ... -->
class Comment < Child
include Comparable
START = "<!--"
STOP = "-->"
# The content text
# The content text
attr_accessor :string
attr_accessor :string
##
# Constructor. The first argument can be one of three types:
# @param first If String, the contents of this comment are set to the
# argument. If Comment, the argument is duplicated. If
# Source, the argument is scanned for a comment.
# @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
# of this object
def initialize( first, second = nil )
#puts "IN COMMENT CONSTRUCTOR; SECOND IS #{second.type}"
super(second)
if first.kind_of? String
@string = first
elsif first.kind_of? Comment
@string = first.string
end
end
##
# Constructor. The first argument can be one of three types:
# @param first If String, the contents of this comment are set to the
# argument. If Comment, the argument is duplicated. If
# Source, the argument is scanned for a comment.
# @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
# of this object
def initialize( first, second = nil )
#puts "IN COMMENT CONSTRUCTOR; SECOND IS #{second.type}"
super(second)
if first.kind_of? String
@string = first
elsif first.kind_of? Comment
@string = first.string
end
end
def clone
Comment.new self
end
def clone
Comment.new self
end
# == DEPRECATED
# See REXML::Formatters
#
# output::
# Where to write the string
# indent::
# An integer. If -1, no indenting will be used; otherwise, the
# indentation will be this number of spaces, and children will be
# indented an additional amount.
# transitive::
# Ignored by this class. The contents of comments are never modified.
# ie_hack::
# Needed for conformity to the child API, but not used by this class.
def write( output, indent=-1, transitive=false, ie_hack=false )
# output::
# Where to write the string
# indent::
# An integer. If -1, no indenting will be used; otherwise, the
# indentation will be this number of spaces, and children will be
# indented an additional amount.
# transitive::
# Ignored by this class. The contents of comments are never modified.
# ie_hack::
# Needed for conformity to the child API, but not used by this class.
def write( output, indent=-1, transitive=false, ie_hack=false )
Kernel.warn("Comment.write is deprecated. See REXML::Formatters")
indent( output, indent )
output << START
output << @string
output << STOP
end
indent( output, indent )
output << START
output << @string
output << STOP
end
alias :to_s :string
alias :to_s :string
##
# Compares this Comment to another; the contents of the comment are used
# in the comparison.
def <=>(other)
other.to_s <=> @string
end
##
# Compares this Comment to another; the contents of the comment are used
# in the comparison.
def <=>(other)
other.to_s <=> @string
end
##
# Compares this Comment to another; the contents of the comment are used
# in the comparison.
def ==( other )
other.kind_of? Comment and
(other <=> self) == 0
end
##
# Compares this Comment to another; the contents of the comment are used
# in the comparison.
def ==( other )
other.kind_of? Comment and
(other <=> self) == 0
end
def node_type
:comment
end
end
end
end
#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().
# 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
# declaration for you. See |DECLARATION| and |write|.
class Document < Element
# A convenient default XML declaration. If you want an XML declaration,
# the easiest way to add one is mydoc << Document::DECLARATION
# declaration for you. See |DECLARATION| and |write|.
class Document < Element
# A convenient default XML declaration. If you want an XML declaration,
# the easiest way to add one is mydoc << Document::DECLARATION
# +DEPRECATED+
# Use: mydoc << XMLDecl.default
DECLARATION = XMLDecl.default
DECLARATION = XMLDecl.default
# Constructor
# @param source if supplied, must be a Document, String, or IO.
# Documents have their context and Element attributes cloned.
# Strings are expected to be valid XML documents. IOs are expected
# to be sources of valid XML documents.
# @param context if supplied, contains the context of the document;
# this should be a Hash.
def initialize( source = nil, context = {} )
# Constructor
# @param source if supplied, must be a Document, String, or IO.
# Documents have their context and Element attributes cloned.
# Strings are expected to be valid XML documents. IOs are expected
# to be sources of valid XML documents.
# @param context if supplied, contains the context of the document;
# this should be a Hash.
def initialize( source = nil, context = {} )
@entity_expansion_count = 0
super()
@context = context
return if source.nil?
if source.kind_of? Document
@context = source.context
super source
else
build( source )
end
end
super()
@context = context
return if source.nil?
if source.kind_of? Document
@context = source.context
super source
else
build( source )
end
end
def node_type
:document
end
# Should be obvious
def clone
Document.new self
end
# Should be obvious
def clone
Document.new self
end
# According to the XML spec, a root node has no expanded name
def expanded_name
''
#d = doc_type
#d ? d.name : "UNDEFINED"
end
# According to the XML spec, a root node has no expanded name
def expanded_name
''
#d = doc_type
#d ? d.name : "UNDEFINED"
end
alias :name :expanded_name
alias :name :expanded_name
# We override this, because XMLDecls and DocTypes must go at the start
# of the document
def add( child )
if child.kind_of? XMLDecl
@children.unshift child
# We override this, because XMLDecls and DocTypes must go at the start
# of the document
def add( child )
if child.kind_of? XMLDecl
@children.unshift child
child.parent = self
elsif child.kind_of? DocType
elsif child.kind_of? DocType
# 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
# 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
@children[insert_before_index] = child
end
child.parent = self
else
rv = super
raise "attempted adding second root element to document" if @elements.size > 1
rv
end
end
alias :<< :add
child.parent = self
else
rv = super
raise "attempted adding second root element to document" if @elements.size > 1
rv
end
end
alias :<< :add
def add_element(arg=nil, arg2=nil)
rv = super
raise "attempted adding second root element to document" if @elements.size > 1
rv
end
def add_element(arg=nil, arg2=nil)
rv = super
raise "attempted adding second root element to document" if @elements.size > 1
rv
end
# @return the root Element of the document, or nil if this document
# has no children.
def root
# @return the root Element of the document, or nil if this document
# has no children.
def root
elements[1]
#self
#@children.find { |item| item.kind_of? Element }
end
end
# @return the DocType child of the document, if one exists,
# and nil otherwise.
def doctype
@children.find { |item| item.kind_of? DocType }
end
# @return the DocType child of the document, if one exists,
# and nil otherwise.
def doctype
@children.find { |item| item.kind_of? DocType }
end
# @return the XMLDecl of this document; if no XMLDecl has been
# set, the default declaration is returned.
def xml_decl
rv = @children[0]
# @return the XMLDecl of this document; if no XMLDecl has been
# set, the default declaration is returned.
def xml_decl
rv = @children[0]
return rv if rv.kind_of? XMLDecl
rv = @children.unshift(XMLDecl.default)[0]
end
end
# @return the XMLDecl version of this document as a String.
# If no XMLDecl has been set, returns the default version.
def version
xml_decl().version
end
# @return the XMLDecl version of this document as a String.
# If no XMLDecl has been set, returns the default version.
def version
xml_decl().version
end
# @return the XMLDecl encoding of this document as a String.
# If no XMLDecl has been set, returns the default encoding.
def encoding
xml_decl().encoding
end
# @return the XMLDecl encoding of this document as a String.
# If no XMLDecl has been set, returns the default encoding.
def encoding
xml_decl().encoding
end
# @return the XMLDecl standalone value of this document as a String.
# If no XMLDecl has been set, returns the default setting.
def stand_alone?
xml_decl().stand_alone?
end
# @return the XMLDecl standalone value of this document as a String.
# If no XMLDecl has been set, returns the default setting.
def stand_alone?
xml_decl().stand_alone?
end
# Write the XML tree out, optionally with indent. This writes out the
# entire XML document, including XML declarations, doctype declarations,
@ -194,12 +194,12 @@ module REXML
REXML::Formatters::Default.new( ie_hack )
end
formatter.write( self, output )
end
end
def Document::parse_stream( source, listener )
Parsers::StreamParser.new( source, listener ).parse
end
def Document::parse_stream( source, listener )
Parsers::StreamParser.new( source, listener ).parse
end
@@entity_expansion_limit = 10_000
@ -222,9 +222,9 @@ module REXML
end
end
private
def build( source )
private
def build( source )
Parsers::TreeParser.new( source, self ).parse
end
end
end
end
end

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1464,7 +1464,7 @@ EOA
_assert_maker_atom_element(feed_type, maker_readers, feed_readers,
maker_extractor, feed_extractor,
&block)
end
end
def assert_maker_atom_generator(feed_type, maker_readers, feed_readers,
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])
end
def test_combination
def test_combination
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],[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) { "\uD847\uDD9A" } # surrogate pair
end
end
end

View file

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