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:
parent
952385b712
commit
46321a9a31
40 changed files with 2198 additions and 2192 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(/"/, '"e;')}"^
|
||||
else
|
||||
"#@expanded_name='#{to_s().gsub(/'/, ''')}'"
|
||||
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(/"/, '"e;')}"^
|
||||
else
|
||||
"#@expanded_name='#{to_s().gsub(/'/, ''')}'"
|
||||
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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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><<<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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -263,5 +263,5 @@ EOS
|
|||
# assert_raise(SyntaxError) { "\uDFFF" } # surrogate block
|
||||
# assert_raise(SyntaxError) { "\uD847\uDD9A" } # surrogate pair
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue