Class: SCXML::Element

Inherits:
Object
  • Object
show all
Includes:
XPath
Defined in:
lib/scxml/element.rb

Instance Attribute Summary collapse

Attributes included from XPath

#content_range

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(arg, range = nil, string = nil) ⇒ Element

Returns a new instance of Element.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/scxml/element.rb', line 15

def initialize(arg, range=nil, string=nil)
	case arg
	when String
		@doc = Document.new(arg)
		@string_range = @doc.content_range			
	when Document
		@doc = arg
		@string_range = arg.content_range				
	when Element
		@parent = arg
		@doc = arg.doc
		@string_range = join_range(arg.string_range, range)
	else
		raise ArgumentError, "Cannot initialize using: #{arg.class}"
	end
	
	@string = string unless doc.lightweight?
	@name, @content_range = parse(self.string)
end

Instance Attribute Details

#docObject (readonly)

Returns the value of attribute doc.



13
14
15
# File 'lib/scxml/element.rb', line 13

def doc
  @doc
end

#nameObject (readonly)

Returns the value of attribute name.



13
14
15
# File 'lib/scxml/element.rb', line 13

def name
  @name
end

#parentObject (readonly)

Returns the value of attribute parent.



13
14
15
# File 'lib/scxml/element.rb', line 13

def parent
  @parent
end

Class Method Details

.new(*args) ⇒ Object



5
6
7
8
# File 'lib/scxml/element.rb', line 5

def new(*args)
	obj = super
	(obj.string_range == obj.doc.content_range && !obj.doc.root.nil?)  ? obj.doc.root : obj
end

Instance Method Details

#attribute(key) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/scxml/element.rb', line 63

def attribute(key)
	return @attributes[key] unless @attributes.nil?
	
	attr_range_begin = string_range.begin + name.length + 1
	attr_range_end = string_range.begin + content_range.begin - 1
	
	scanner = doc.scanner
	scanner.pos = attr_range_begin
	scanner.skip_until(Regexp.new("#{key}="))
	
	return nil if scanner.pos > attr_range_end
	
	result = scanner.scan(/'[^']*'|\"[^\"]*\"/)
	result ? result[1...-1] : nil
	
	#attr_range = (string_range.begin + name.length + 1)...(string_range.begin + content_range.begin - 1)
	#doc.string[attr_range] =~ Regexp.new("#{key}=('[^']*'|\"[^\"]*\")", Regexp::MULTILINE)
	
	#$1 ? $1[1...-1] : nil
end

#attributesObject



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/scxml/element.rb', line 84

def attributes
	return @attributes unless @attributes.nil?
	
	attrs = {}
	
	# indexing and selection is vs the doc.string rather than element.string
	# because in lightweight mode this will require an additional string selection 
	# to get element.string.  Better to go straight to the source
	attr_range = (string_range.begin + name.length + 1)...(string_range.begin + content_range.begin - 1)
	doc.string[attr_range].scan(/(\w+)=('[^']*'|\"[^\"]*\")/m).each do |attr|
		key, value = attr
		attrs[key] = value[1...-1]
	end
		
	@attributes = attrs unless doc.lightweight?
	attrs
end

#childrenObject



102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/scxml/element.rb', line 102

def children
	unless @children
		@children = []

		scanner = StringScanner.new(content)
		while node = content_node(scanner)
			@children << node
		end	
	end
	
	@children
end

#content(objectify = false) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/scxml/element.rb', line 47

def content(objectify=false)
	content_str = doc.lightweight? ? super() : (@content_str ||= super())
	return content_str unless objectify
	
	stripped = content_str.strip
	
	case stripped
	when /^\d+$/ then stripped.to_i
	when /^\d*\.?\d+$/ then stripped.to_f
	when /^true$/i then true
	when /^false$/i then false
	else
		content_str
	end
end

#hashify(xpath = '*', &block) ⇒ Object



126
127
128
129
130
131
132
133
# File 'lib/scxml/element.rb', line 126

def hashify(xpath='*', &block)
	hash = {}
	select(xpath).each do |element|
		key = block_given? ? yield(element) : element.name
		hash[key] = element.content
	end
	hash
end

#rewrite(options = {}) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/scxml/element.rb', line 139

def rewrite(options={})
	n = options[:indent] || 0
	
	attributes = options[:attributes] || self.attributes
	attributes.merge!(options[:merge_attributes]) if options[:merge_attributes]
		
	content = options[:content] || self.content
	content += options[:add_content] if options[:add_content]
	
	attr_string = attributes_to_s(attributes)
	attr_string.insert(0, ' ') unless attr_string.strip.empty? 
	
	if content.empty?
		closed = (string[-2..-1] == '/>')
		closed ?
			"#{indentation(n)}<#{name}#{attr_string}/>" :
			"#{indentation(n)}<#{name}#{attr_string}></#{name}>"
	else
		content_str = reindent(content, n)
		content_str = "#{content_str}#{indentation(n, true)}" unless content_str.strip.empty? || content_str == content
		
		"#{indentation(n)}<#{name}#{attr_string}>#{content_str}</#{name}>"
	end
end

#select(xpath) ⇒ Object



115
116
117
118
119
120
121
122
123
124
# File 'lib/scxml/element.rb', line 115

def select(xpath)
	return [] if xpath.nil?
	
	if xpath =~ /^\//
		doc.select(xpath)
	else
		paths = xpath.scan(/\/*[^\/]+/)
		select_by_paths(paths)
	end
end

#stringObject



35
36
37
38
39
40
41
# File 'lib/scxml/element.rb', line 35

def string
	if doc.lightweight?
		doc.string[string_range]
	else
		@string ||= doc.string[string_range]
	end
end

#string_rangeObject



43
44
45
# File 'lib/scxml/element.rb', line 43

def string_range
	@string_range ||= doc.content_range
end

#to_sObject



135
136
137
# File 'lib/scxml/element.rb', line 135

def to_s
	string
end