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

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


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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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