require "rexml/namespace"
require 'rexml/text'
module REXML
# Defines an Element Attribute; IE, a attribute=value pair, as in:
# . 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
NEEDS_A_SECOND_CHECK = /(<|&((#{Entity::NAME});|(#0*((?:\d+)|(?:x[a-fA-F0-9]+)));)?)/um
# Constructor.
# FIXME: The parser doesn't catch illegal characters in attributes
#
# first::
# Either: an Attribute, which this new attribute will become a
# clone of; or a String, which is the name of this attribute
# second::
# If +first+ is an Attribute, then this may be an Element, or nil.
# If nil, then the Element parent of this attribute is the parent
# of the +first+ Attribute. If the first argument is a String,
# then this must also be a String, and is the content of the attribute.
# If this is the content, it must be fully normalized (contain no
# illegal characters).
# parent::
# Ignored unless +first+ is a String; otherwise, may be the Element
# parent of this attribute, or nil.
#
#
# Attribute.new( attribute_to_clone )
# Attribute.new( attribute_to_clone, parent_element )
# Attribute.new( "attr", "attr_value" )
# Attribute.new( "attr", "attr_value", parent_element )
def initialize( first, second=nil, parent=nil )
@normalized = @unnormalized = @element = nil
if first.kind_of? Attribute
self.name = first.expanded_name
@unnormalized = first.value
if second.kind_of? Element
@element = second
else
@element = first.element
end
elsif first.kind_of? String
@element = parent
self.name = first
@normalized = second.to_s
else
raise "illegal argument #{first.class.name} to Attribute constructor"
end
end
# Returns the namespace of the attribute.
#
# e = Element.new( "elns:myelement" )
# e.add_attribute( "nsa:a", "aval" )
# e.add_attribute( "b", "bval" )
# e.attributes.get_attribute( "a" ).prefix # -> "nsa"
# e.attributes.get_attribute( "b" ).prefix # -> "elns"
# a = Attribute.new( "x", "y" )
# a.prefix # -> ""
def prefix
pf = super
if pf == ""
pf = @element.prefix if @element
end
pf
end
# Returns the namespace URL, if defined, or nil otherwise
#
# e = Element.new("el")
# e.add_attributes({"xmlns:ns", "http://url"})
# e.namespace( "ns" ) # -> "http://url"
def namespace arg=nil
arg = prefix if arg.nil?
@element.namespace arg
end
# Returns true if other is an Attribute and has the same name and value,
# false otherwise.
def ==( other )
other.kind_of?(Attribute) and other.name==name and other.value==value
end
# Creates (and returns) a hash from both the name and value
def hash
name.hash + value.hash
end
# Returns this attribute out as XML source, expanding the name
#
# a = Attribute.new( "x", "y" )
# a.to_string # -> "x='y'"
# b = Attribute.new( "ns:x", "y" )
# b.to_string # -> "ns:x='y'"
def to_string
if @element and @element.context and @element.context[:attribute_quote] == :quote
%Q^#@expanded_name="#{to_s().gsub(/"/, '"e;')}"^
else
"#@expanded_name='#{to_s().gsub(/'/, ''')}'"
end
end
def doctype
if @element
doc = @element.document
doctype = doc.doctype if doc
end
end
# Returns the attribute value, with entities replaced
def to_s
return @normalized if @normalized
@normalized = Text::normalize( @unnormalized, doctype )
@unnormalized = nil
@normalized
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
@unnormalized
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
if @normalized
Text.check( @normalized, NEEDS_A_SECOND_CHECK, doctype )
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
# Writes this attribute (EG, puts 'key="value"' to the output)
def write( output, indent=-1 )
output << to_string
end
def node_type
:attribute
end
def inspect
rv = ""
write( rv )
rv
end
def xpath
path = @element.xpath
path += "/@#{self.expanded_name}"
return path
end
end
end
#vim:ts=2 sw=2 noexpandtab:
Zu?X0Cobв$#
5QY!P
lmFNe'x @'Թs6LvK<]P4V+_X(֫iB<'JL?-X@0jX +n䈤{~M^B"-SW$ǰ |Uh_f`V<.Zy5^gxҶ+_ؠ
+
D55F,8;5OS=i>j~dZ(@,k)9%V'u="&"n
a[h&!u" />3磸9Ѭ`^VVPۯy,Cm@)ccٜJ0 &: T5fYZYG|72D1;.u"IJI;&P)Oi{&FuTPCB$_Ώ^!+P2
viVݠ:,K֪+NQ?`č}`љs,d`sm&eY1Q59?읆?W{*"i5FrM
xĉpZo{,%'rM8vJ$Yn5߱H&,<^Kƙa?xٵ|>s
v[{"Oc<)-g0oƜȑ$&mUW
r%tSV <ό{6M-Upz+3M2D67iMf!e%kF|ŽEaJu$ n{0yufrX0Bi9YYTzTTooH!QWXӔꞃnD{kǨmJ⒐Hv)
nYVe*. x>; aqqyHWu1@u_LrQ?S"<_붚[O ]ݯ88(yq9^fgLfx
1fV+P˒ִ-nJ0 1@,7[൹j
EC_1L>ϱPܧ4Ϯ&Oŕ7KT=gR
{(^^)V;WCT[Hy۠)
Gڈ*Eː[ku.:z
@c@;Ή8
lO[KY/:/Ixg>t2!?Wc#{k?|=K)8 q_& CN%IWI
Jc\zɞn[]{(i4PIXR g͖t~dOsS/ތLG^y0>oyz^!}GY,gv<ē7a5h{ gkx+3Xhaj#d
Vh)y}e9ܾ02qɯ0U6}d"~oݸIKjRgHԂ teC=BE(Ìn$Ƽv/z Iȯ6$L6@5 R4U=R[x.4ZĮ8[F=lŮ JTѭ`?hozt+>&
IEwДOֹmSiY]o 85 /w8m0&GQ8vKC$T P?f~Ηm.A)A% !AO`S+?3'FxHDԸ9,pBۇ[im
wGCI7$=
I"֭ Mem%A{Ucbi,7jͯfq]/'#*[Ix
cyfAH=+|R .s~nIWJN <+5,6K.r"3szqQi{
q<_Xo, #yzO;fc_]!rX.z