xmlparser 0.6.81

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. data/MANIFEST +112 -0
  2. data/README +697 -0
  3. data/README.ja +789 -0
  4. data/Rakefile +34 -0
  5. data/ext/encoding.h +91 -0
  6. data/ext/xmlparser/mkrf_conf.rb +28 -0
  7. data/ext/xmlparser/xmlparser.c +2226 -0
  8. data/lib/sax.rb +1 -0
  9. data/lib/saxdriver.rb +1 -0
  10. data/lib/wget.rb +47 -0
  11. data/lib/xml/dom/builder-ja.rb +58 -0
  12. data/lib/xml/dom/builder.rb +310 -0
  13. data/lib/xml/dom/core.rb +3276 -0
  14. data/lib/xml/dom/digest.rb +94 -0
  15. data/lib/xml/dom/visitor.rb +182 -0
  16. data/lib/xml/dom2/attr.rb +213 -0
  17. data/lib/xml/dom2/cdatasection.rb +76 -0
  18. data/lib/xml/dom2/characterdata.rb +177 -0
  19. data/lib/xml/dom2/comment.rb +81 -0
  20. data/lib/xml/dom2/core.rb +19 -0
  21. data/lib/xml/dom2/document.rb +317 -0
  22. data/lib/xml/dom2/documentfragment.rb +82 -0
  23. data/lib/xml/dom2/documenttype.rb +102 -0
  24. data/lib/xml/dom2/dombuilder.rb +277 -0
  25. data/lib/xml/dom2/dombuilderfilter.rb +12 -0
  26. data/lib/xml/dom2/domentityresolver.rb +13 -0
  27. data/lib/xml/dom2/domentityresolverimpl.rb +37 -0
  28. data/lib/xml/dom2/domexception.rb +95 -0
  29. data/lib/xml/dom2/domimplementation.rb +61 -0
  30. data/lib/xml/dom2/dominputsource.rb +29 -0
  31. data/lib/xml/dom2/element.rb +533 -0
  32. data/lib/xml/dom2/entity.rb +110 -0
  33. data/lib/xml/dom2/entityreference.rb +107 -0
  34. data/lib/xml/dom2/namednodemap.rb +138 -0
  35. data/lib/xml/dom2/node.rb +587 -0
  36. data/lib/xml/dom2/nodelist.rb +231 -0
  37. data/lib/xml/dom2/notation.rb +86 -0
  38. data/lib/xml/dom2/processinginstruction.rb +155 -0
  39. data/lib/xml/dom2/text.rb +128 -0
  40. data/lib/xml/dom2/xpath.rb +398 -0
  41. data/lib/xml/encoding-ja.rb +42 -0
  42. data/lib/xml/parser.rb +13 -0
  43. data/lib/xml/parserns.rb +236 -0
  44. data/lib/xml/sax.rb +353 -0
  45. data/lib/xml/saxdriver.rb +370 -0
  46. data/lib/xml/xpath.rb +3284 -0
  47. data/lib/xml/xpath.ry +2352 -0
  48. data/lib/xmldigest.rb +1 -0
  49. data/lib/xmltree.rb +1 -0
  50. data/lib/xmltreebuilder.rb +1 -0
  51. data/lib/xmltreevisitor.rb +1 -0
  52. metadata +111 -0
data/lib/sax.rb ADDED
@@ -0,0 +1 @@
1
+ require 'xml/sax'
data/lib/saxdriver.rb ADDED
@@ -0,0 +1 @@
1
+ require 'xml/saxdriver'
data/lib/wget.rb ADDED
@@ -0,0 +1,47 @@
1
+ ## -*- Ruby -*-
2
+ ## URLopen
3
+ ## 1999 by yoshidam
4
+ ##
5
+ ## TODO: This module should be writen by Ruby instead of wget/lynx.
6
+
7
+ module WGET
8
+ PARAM = {
9
+ 'wget' => nil,
10
+ 'opts' => nil,
11
+ 'http_proxy' => nil,
12
+ 'ftp_proxy' => nil
13
+ }
14
+
15
+ def open(url, *rest)
16
+ raise TypeError.new("wrong argument type #{url.inspect}" +
17
+ " (expected String)") if url.class != String
18
+
19
+ if url =~ /^\/|^\./ || (url !~ /^http:|^ftp:/ && FileTest.exist?(url))
20
+ File::open(url, *rest)
21
+ else
22
+ ENV['http_proxy'] = PARAM['http_proxy'] if PARAM['http_proxy']
23
+ ENV['ftp_proxy'] = PARAM['ftp_proxy'] if PARAM['ftp_proxy']
24
+ IO::popen(PARAM['wget'] + ' ' + PARAM['opts'] + ' ' + url)
25
+ end
26
+ end
27
+ module_function :open
28
+ end
29
+
30
+ [ '/usr/local/bin/wget', '/usr/bin/wget',
31
+ '/usr/local/bin/lynx', '/usr/bin/lynx',
32
+ '/usr/local/bin/lwp-request', '/usr/bin/lwp-request' ].each do |p|
33
+ if FileTest.executable?(p)
34
+ WGET::PARAM['wget'] = p
35
+ case p
36
+ when /wget$/
37
+ WGET::PARAM['opts'] = '-q -O -'
38
+ when /lynx$/
39
+ WGET::PARAM['opts'] = '-source'
40
+ when /lwp-request$/
41
+ WGET::PARAM['opts'] = '-m GET'
42
+ end
43
+ break
44
+ end
45
+ end
46
+
47
+ raise "wget not found" if !WGET::PARAM['wget']
@@ -0,0 +1,58 @@
1
+ ## -*- Ruby -*-
2
+ ## Tree builder class for Japanese encoding
3
+ ## 1998 by yoshidam
4
+
5
+ require 'xml/dom/builder'
6
+
7
+ module XML
8
+ module DOM
9
+ class JapaneseBuilder<Builder
10
+ require 'kconv'
11
+ include Kconv
12
+ require 'uconv'
13
+ include Uconv
14
+
15
+ def nameConverter(str)
16
+ u8toeuc(str)
17
+ end
18
+ def cdataConverter(str)
19
+ u8toeuc(str)
20
+ end
21
+
22
+ def parseStream(stream, trim = false)
23
+ ## empty file
24
+ if ((xml = stream.gets).nil?); exit 1; end
25
+ ## rewrite encoding in XML decl.
26
+ if xml =~ /^<\?xml\sversion=.+\sencoding=.EUC-JP./i
27
+ xml.sub!(/EUC-JP/i, "UTF-8")
28
+ encoding = 'EUC-JP'
29
+ elsif xml =~ /^<\?xml\sversion=.+\sencoding=.Shift_JIS./i
30
+ xml.sub!(/Shift_JIS/i, "UTF-8")
31
+ encoding = "Shift_JIS"
32
+ elsif xml =~ /^<\?xml\sversion=.+\sencoding=.ISO-2022-JP./i
33
+ xml.sub!(/ISO-2022-JP/i, "UTF-8")
34
+ encoding = "ISO-2022-JP"
35
+ end
36
+
37
+ ## read body
38
+ xml += String(stream.read)
39
+
40
+ ## convert body encoding
41
+ if encoding == "EUC-JP"
42
+ xml = euctou8(xml)
43
+ elsif encoding == "Shift_JIS"
44
+ xml = euctou8(kconv(xml, EUC, SJIS))
45
+ elsif encoding == "ISO-2022-JP"
46
+ xml = euctou8(kconv(xml, EUC, JIS))
47
+ end
48
+
49
+ return parse(xml, trim)
50
+ end
51
+
52
+
53
+ def Uconv.unknown_unicode_handler(u)
54
+ return '®'
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,310 @@
1
+ ## -*- Ruby -*-
2
+ ## XML::DOM::Builder
3
+ ## 1999 by yoshidam
4
+
5
+ require 'xml/parser'
6
+ require 'xml/dom/core'
7
+
8
+ =begin
9
+ = XML::DOM::Builder
10
+
11
+ == Module XML
12
+
13
+ =end
14
+ module XML
15
+ module DOM
16
+
17
+ =begin
18
+ == Class XML::DOM::Builder (XML::SimpleTreeBuilder)
19
+
20
+ === superclass
21
+ XML::Parser
22
+
23
+ =end
24
+ class Builder<Parser
25
+ include XML::DOM
26
+
27
+ attr :createCDATASection, true
28
+ attr :createEntityReference, true
29
+
30
+ ## replace 'open' by WGET::open
31
+ begin
32
+ require 'wget'
33
+ include WGET
34
+ rescue
35
+ ## ignore
36
+ end
37
+
38
+ =begin
39
+ === Class Methods
40
+
41
+ --- DOM::Builder.new(level = 0, *args)
42
+
43
+ Constructor of DOM builder.
44
+
45
+ usage:
46
+ parser = XML::SimpleTreeBuilder.new(level)
47
+
48
+ level: 0 -- ignore default events (defualt)
49
+ 1 -- catch default events and create the Comment,
50
+ the EntityReference, the XML declaration (as PI) and
51
+ the non-DOM-compliant DocumentType nodes.
52
+
53
+ =end
54
+
55
+ def self.new(level = 0, *args)
56
+ document = Document.new
57
+ ret = super(*args)
58
+ external = false
59
+ external = true if args[0].is_a?(SimpleTreeBuilder)
60
+ ret.__initialize__(level, document, external)
61
+ ret
62
+ end
63
+
64
+ ## Constructor
65
+ ## parser = XML::SimpleTreeBuilder.new(level)
66
+ ## level: 0 -- ignore default events (defualt)
67
+ ## 1 -- catch default events and create the Comment,
68
+ ## the EntityReference, the XML declaration (as PI) and
69
+ ## the non-DOM-compliant DocumentType nodes.
70
+ def __initialize__(level, document, external)
71
+ @tree = nil
72
+ @level = level
73
+ @document = document
74
+ @external = external
75
+ @createCDATASection = false
76
+ @createEntityReference = false
77
+ if @level > 0
78
+ @createCDATASection = true
79
+ @createEntityReference = true
80
+ def self.default(data); defaultHandler(data); end
81
+ end
82
+ end
83
+
84
+ =begin
85
+ === Methods
86
+
87
+ --- Builder#nameConverter(str)
88
+
89
+ User redefinable name encoding converter
90
+
91
+ =end
92
+ ## User redefinable name encoding converter
93
+ def nameConverter(str)
94
+ str
95
+ end
96
+
97
+ =begin
98
+ --- Builder#cdataConverter(str)
99
+
100
+ User redefinable cdata encoding converter
101
+
102
+ =end
103
+ ## User redefinable cdata encoding converter
104
+ def cdataConverter(str)
105
+ str
106
+ end
107
+
108
+ =begin
109
+ === Methods
110
+ --- Builder#parse(xml, parse_ext = false)
111
+
112
+ parse string or stream of XML contents.
113
+
114
+ xml: string or stream of XML contents
115
+ parse_ext: flag whether parse external entities or not
116
+
117
+ ex. doctree = parser.parse(xml, parse_ext)
118
+
119
+ =end
120
+ ## Parse
121
+ ## doctree = parser.parse(xml, parse_ext)
122
+ ## xml: string or stream of XML contents
123
+ ## parse_ext: flag whether parse external entities or not
124
+ def parse(xml, parse_ext = false)
125
+ if @external
126
+ @tree = @document.createDocumentFragment
127
+ else
128
+ @tree = @document
129
+ end
130
+ @parse_ext = parse_ext
131
+ @current = @tree
132
+ @inDocDecl = 0
133
+ @decl = ""
134
+ @inDecl = 0
135
+ @idRest = 0
136
+ @extID = nil
137
+ @cdata_f = false
138
+ @cdata_buf = ''
139
+ super(xml)
140
+ @tree
141
+ end
142
+
143
+ def text
144
+ return if @cdata_buf == ''
145
+ textnode = @document.createTextNode(cdataConverter(@cdata_buf))
146
+ @current.appendChild(textnode)
147
+ @cdata_buf = ''
148
+ end
149
+
150
+ def startElement(name, data)
151
+ text
152
+ elem = @document.createElement(nameConverter(name))
153
+ data.each do |key, value|
154
+ attr = @document.createAttribute(nameConverter(key))
155
+ attr.appendChild(@document.createTextNode(cdataConverter(value)))
156
+ elem.setAttributeNode(attr)
157
+ end
158
+ @current.appendChild(elem)
159
+ @current = elem
160
+ end
161
+
162
+ def endElement(name)
163
+ text
164
+ @current = @current.parentNode
165
+ end
166
+
167
+ def character(data)
168
+ @cdata_buf << data
169
+ end
170
+
171
+ def processingInstruction(name, data)
172
+ text
173
+ pi = @document.createProcessingInstruction(nameConverter(name),
174
+ cdataConverter(data))
175
+ ## PI data should not be converted
176
+ @current.appendChild(pi)
177
+ end
178
+
179
+ def externalEntityRef(context, base, systemId, publicId)
180
+ text
181
+ tree = nil
182
+ if @parse_ext
183
+ extp = self.class.new(@level, self, context)
184
+ extp.setBase(base) if base
185
+ file = systemId
186
+ if systemId !~ /^\/|^\.|^http:|^ftp:/ && !base.nil?
187
+ file = base + systemId
188
+ end
189
+ begin
190
+ tree = extp.parse(open(file).read, @parse_ext)
191
+ rescue XML::ParserError
192
+ raise XML::ParserError.new("#{systemId}(#{extp.line}): #{$!}")
193
+ rescue Errno::ENOENT
194
+ raise Errno::ENOENT.new("#{$!}")
195
+ end
196
+ extp.done
197
+ end
198
+ if @createEntityReference
199
+ entref = @document.createEntityReference(nameConverter(context))
200
+ @current.appendChild(entref)
201
+ entref.appendChild(tree) if tree
202
+ else
203
+ @current.appendChild(tree) if tree
204
+ end
205
+ end
206
+
207
+ def startCdata
208
+ return unless @createCDATASection
209
+ text
210
+ @cdata_f = true
211
+ end
212
+
213
+ def endCdata
214
+ return unless @createCDATASection
215
+ cdata = @document.createCDATASection(cdataConverter(@cdata_buf))
216
+ @current.appendChild(cdata)
217
+ @cdata_buf = ''
218
+ @cdata_f = false
219
+ end
220
+
221
+ def comment(data)
222
+ text
223
+ comment = @document.createComment(cdataConverter(data))
224
+ ## Comment should not be converted
225
+ @current.appendChild(comment)
226
+ end
227
+
228
+ def defaultHandler(data)
229
+ if data =~ /^\&(.+);$/
230
+ eref = @document.createEntityReference(nameConverter($1))
231
+ @current.appendChild(eref)
232
+ elsif data =~ /^<\?xml\s*([\s\S]*)\?>$/
233
+ ## XML declaration should not be a PI.
234
+ pi = @document.createProcessingInstruction("xml",
235
+ cdataConverter($1))
236
+ @current.appendChild(pi)
237
+ elsif @inDocDecl == 0 && data =~ /^<\!DOCTYPE$/
238
+ @inDocDecl = 1
239
+ @inDecl = 0
240
+ @idRest = 0
241
+ @extID = nil
242
+ elsif @inDocDecl == 1
243
+ if data == "["
244
+ @inDocDecl = 2
245
+ elsif data == ">"
246
+ if !@extID.nil?
247
+ ## @current.nodeValue = @extID
248
+ end
249
+ @inDocDecl = 0
250
+ ## @current = @current.parentNode
251
+ elsif data == "SYSTEM"
252
+ @idRest = 1
253
+ @extID = data
254
+ elsif data == "PUBLIC"
255
+ @idRest = 2
256
+ @extID = data
257
+ elsif data !~ /^\s+$/
258
+ if @idRest > 0
259
+ ## SysID or PubID
260
+ @extID <<= " " + data
261
+ @idRest -= 1
262
+ else
263
+ ## Root Element Type
264
+ docType = data
265
+ ## doctype = DocumentType.new(nameConverter(docType))
266
+ ## @current.appendChild(doctype)
267
+ ## @current = doctype
268
+ end
269
+ end
270
+ elsif @inDocDecl == 2
271
+ if @inDecl == 0
272
+ if data == "]"
273
+ @inDocDecl = 1
274
+ elsif data =~ /^<\!/
275
+ @decl = data
276
+ @inDecl = 1
277
+ elsif data =~ /^%(.+);$/
278
+ ## PERef
279
+ ## cdata = @document.createTextNode(nameConverter(data))
280
+ ## @current.appendChild(cdata)
281
+ else
282
+ ## WHITESPCAE
283
+ end
284
+ else ## inDecl == 1
285
+ if data == ">"
286
+ @decl <<= data
287
+ @inDecl = 0
288
+ ## Markup Decl
289
+ ## cdata = @document.createTextNode(cdataConverter(@decl))
290
+ ## Markup decl should not be converted
291
+ ## @current.appendChild(cdata)
292
+ elsif data =~ /^\s+$/
293
+ ## WHITESPACE
294
+ @decl << " "
295
+ else
296
+ @decl << data
297
+ end
298
+ end
299
+ else
300
+ ## maybe WHITESPACE
301
+ ## cdata = @document.createTextNode(cdataConverter(data))
302
+ ## @current.appendChild(cdata)
303
+ end
304
+ end
305
+
306
+ end
307
+ end
308
+
309
+ SimpleTreeBuilder = DOM::Builder
310
+ end
@@ -0,0 +1,3276 @@
1
+ ## -*- Ruby -*-
2
+ ## XML::SimpleTree
3
+ ## 1998-2000 by yoshidam
4
+ ##
5
+ ## XPointer support is contributed by Masaki Fukushima
6
+ ## <fukusima@goto.info.waseda.ac.jp>
7
+ ##
8
+
9
+ require 'singleton'
10
+
11
+ =begin
12
+
13
+ = XML::DOM (XML::SimpleTree)
14
+
15
+ =end
16
+
17
+
18
+ =begin
19
+
20
+ == Module XML
21
+
22
+ =end
23
+
24
+ module XML
25
+
26
+ =begin
27
+ === Class Methods
28
+
29
+ --- XML.charRef(s)
30
+
31
+ replace character '&','<','>',"'",'"' in string s to character reference.
32
+ =end
33
+
34
+ def XML.charRef(s)
35
+ str = s.dup
36
+ str.gsub!("&", "&amp;")
37
+ str.gsub!("<", "&lt;")
38
+ str.gsub!(">", "&gt;")
39
+ str.gsub!("'", "&apos;")
40
+ str.gsub!('"', "&quot;")
41
+ str
42
+ end
43
+
44
+ =begin
45
+
46
+ == Module XML::Spec
47
+
48
+ Constants related to XML Specification.
49
+
50
+ =end
51
+ ## [Masaki Fukushima]
52
+ module Spec
53
+ ## Constants related to XML Specification
54
+ ## (W3C Recommendation or Working Draft)
55
+
56
+ # XML
57
+ Letter_s = '[a-zA-Z]'
58
+ Digit_s = '\d'
59
+ NameChar_s = "(#{Letter_s}|#{Digit_s}|[\\.\\-_:])"
60
+ Name_s = "(#{Letter_s}|[_:])#{NameChar_s}*"
61
+ SkipLit_s = "(\"[^\"]*\"|'[^']*')"
62
+ Name = /^#{Name_s}$/o
63
+ SkipList = /^#{SkipLit_s}$/o
64
+
65
+ # XPointer
66
+ Instance_s = "(\\+|-)?[1-9]#{Digit_s}*"
67
+ Instance = /^#{Instance_s}$/o
68
+
69
+ end
70
+
71
+ =begin
72
+
73
+ == Module XML::DOM (XML::SimpleTree)
74
+
75
+ DOM-like APIs module.
76
+
77
+ =end
78
+
79
+ module DOM
80
+
81
+ ## Fundamental Interfaces
82
+
83
+ =begin
84
+
85
+ == Class XML::DOM::DOMException
86
+
87
+ === superclass
88
+ Exception
89
+
90
+ DOM exception.
91
+ =end
92
+
93
+ class DOMException<Exception
94
+ INDEX_SIZE_ERR = 1
95
+ WSTRING_SIZE_ERR = 2
96
+ HIERARCHY_REQUEST_ERR = 3
97
+ WRONG_DOCUMENT_ERR = 4
98
+ INVALID_NAME_ERR = 5
99
+ NO_DATA_ALLOWED_ERR = 6
100
+ NO_MODIFICATION_ALLOWED_ERR = 7
101
+ NOT_FOUND_ERR = 8
102
+ NOT_SUPPORTED_ERR = 9
103
+ INUSE_ATTRIBUTE_ERR = 10
104
+ ERRMSG = [
105
+ "no error",
106
+ "index size",
107
+ "wstring size",
108
+ "hierarchy request",
109
+ "wrong document",
110
+ "invalid name",
111
+ "no data allowed",
112
+ "no modification allowed",
113
+ "not found",
114
+ "not supported",
115
+ "inuse attribute"
116
+ ]
117
+
118
+ =begin
119
+ === Class Methods
120
+
121
+ --- DOMException.new(code = 0)
122
+
123
+ generate DOM exception.
124
+ =end
125
+
126
+ def initialize(code = 0)
127
+ @code = code
128
+ end
129
+
130
+ =begin
131
+ === Methods
132
+
133
+ --- DOMException#code()
134
+
135
+ return code of exception.
136
+
137
+ =end
138
+ def code
139
+ @code
140
+ end
141
+
142
+ =begin
143
+
144
+ --- DOMException#to_s()
145
+
146
+ return the string representation of the error.
147
+
148
+ =end
149
+ def to_s
150
+ ERRMSG[@code]
151
+ end
152
+ end
153
+
154
+ =begin
155
+ == Class XML::DOM::DOMImplementation
156
+
157
+ =end
158
+ class DOMImplementation
159
+ include Singleton
160
+
161
+ =begin
162
+ --- DOMImplementation#hasFeature(feature, version)
163
+
164
+ test if DOM implementation has correct feature and version.
165
+
166
+ =end
167
+ def hasFeature(feature, version)
168
+ if feature =~ /^XML$/i && (version.nil? || version == "1.0")
169
+ return true
170
+ end
171
+ false
172
+ end
173
+ end
174
+
175
+ =begin
176
+ == Class XML::DOM::Node
177
+
178
+ =end
179
+ class Node
180
+ ## [DOM]
181
+ NODE_NODE = 0
182
+ ELEMENT_NODE = 1
183
+ ATTRIBUTE_NODE = 2
184
+ TEXT_NODE = 3
185
+ CDATA_SECTION_NODE = 4
186
+ ENTITY_REFERENCE_NODE = 5
187
+ ENTITY_NODE = 6
188
+ PROCESSING_INSTRUCTION_NODE = 7
189
+ COMMENT_NODE = 8
190
+ DOCUMENT_NODE = 9
191
+ DOCUMENT_TYPE_NODE = 10
192
+ DOCUMENT_FRAGMENT_NODE = 11
193
+ NOTATION_NODE = 12
194
+
195
+ ## non-DOM
196
+ # NODE = 0
197
+ # ELEMENT = 1
198
+ # ATTRIBUTE = 2
199
+ # TEXT = 3
200
+ # CDATA_SECTION = 4
201
+ # ENTITY_REFERENCE = 5
202
+ # ENTITY = 6
203
+ # PI = 7
204
+ # PROCESSING_INSTRUCTION = 7
205
+ # COMMENT = 8
206
+ # DOCUMENT = 9
207
+ # DOCUMENT_TYPE = 10
208
+ # DOCUMENT_FRAGMENT = 11
209
+ # NOTATION = 12
210
+
211
+ =begin
212
+ === Class Methods
213
+
214
+ --- Node.new(*children)
215
+
216
+ make a Node.
217
+ children is a Array of child, or sequence of child.
218
+ child is a String or Node.
219
+
220
+ =end
221
+ ## new([child1, child2, ...]) or
222
+ ## new(child1, child2, ...)
223
+ ## child?: String or Node
224
+ def initialize(*children)
225
+ @parent = nil
226
+ @children = nil
227
+ self.childNodes = children if children.length > 0
228
+ end
229
+
230
+ =begin
231
+ === Methods
232
+
233
+ --- Node#parentNode
234
+
235
+ [DOM]
236
+ return parent node.
237
+
238
+ =end
239
+ ## [DOM]
240
+ def parentNode
241
+ @parent
242
+ end
243
+
244
+ =begin
245
+ --- Node#parentNode=(p)
246
+
247
+ set node p as parent.
248
+ =end
249
+
250
+ def parentNode=(p)
251
+ @parent = p
252
+ end
253
+
254
+ =begin
255
+ --- Node#nodeType
256
+
257
+ [DOM]
258
+ return nodetype.
259
+
260
+ =end
261
+ ## [DOM]
262
+ def nodeType
263
+ NODE_NODE
264
+ end
265
+
266
+ =begin
267
+ --- Node#nodeName
268
+
269
+ [DOM]
270
+ return nodename.
271
+
272
+ =end
273
+ ## [DOM]
274
+ def nodeName
275
+ "#node"
276
+ end
277
+
278
+ # def nodeName=(p)
279
+ # @name = p
280
+ # end
281
+
282
+ =begin
283
+ --- Node#nodeValue
284
+
285
+ [DOM]
286
+ return nodevalue.
287
+
288
+ =end
289
+ ## [DOM]
290
+ def nodeValue; nil; end
291
+
292
+ =begin
293
+ --- Node#nodeValue=(p)
294
+
295
+ [DOM]
296
+ set nodevalue as p.
297
+ =end
298
+ ## [DOM]
299
+ def nodeValue=(p)
300
+ ## no effect
301
+ end
302
+
303
+ =begin
304
+ --- Node#childNodes()
305
+
306
+ [DOM]
307
+ if method has block, apply block for children nodes.
308
+ without block, return children nodelist.
309
+ =end
310
+ ## [DOM]
311
+ def childNodes
312
+ if iterator?
313
+ @children.each do |child|
314
+ yield(child)
315
+ end if @children
316
+ else
317
+ return @children if !@children.nil?
318
+ @children = NodeList.new
319
+ end
320
+ end
321
+
322
+
323
+ =begin
324
+ --- Node#childNodes=(p)
325
+
326
+ set child node as p.
327
+ =end
328
+ def childNodes=(p)
329
+ if @children.nil?
330
+ @children = NodeList.new
331
+ else
332
+ @children.to_a.clear
333
+ end
334
+ if p.nil? || (p.is_a?(Array) && p.length == 0)
335
+ return
336
+ end
337
+ p.flatten!
338
+ p.each do |child|
339
+ if child.is_a?(String)
340
+ c = Text.new(child)
341
+ @children.push(c)
342
+ c.parentNode = self
343
+ elsif child.is_a?(Node)
344
+ @children.push(child)
345
+ child.parentNode = self
346
+ else
347
+ raise "parameter error"
348
+ end
349
+ end if p
350
+ end
351
+
352
+ =begin
353
+ --- Node#attributes
354
+
355
+ [DOM]
356
+ return attributes of node(but always return nil?).
357
+ =end
358
+ ## [DOM]
359
+ def attributes
360
+ nil
361
+ end
362
+
363
+ ## proper parameter type?
364
+ # def attributes=(p)
365
+ # end
366
+
367
+ =begin
368
+ --- Node#[]=(index, nodes)
369
+
370
+ set children node as nodes with []-style.
371
+ =end
372
+ def []=(index, nodes)
373
+ @children[index..index] = nodes
374
+ @children.each do |child|
375
+ child.parentNode = self
376
+ end if @children
377
+ end
378
+
379
+ =begin
380
+ --- Node#[](index)
381
+
382
+ get children node with []-style.
383
+ =end
384
+ def [](index)
385
+ @children[index]
386
+ end
387
+
388
+ =begin
389
+ --- Node#+(node)
390
+
391
+ concat node to Node.
392
+ =end
393
+ def +(node)
394
+ [self, node]
395
+ end
396
+
397
+ =begin
398
+ --- Node#to_s
399
+
400
+ returns the string representation of the Node.
401
+ =end
402
+ def to_s
403
+ @children.to_s
404
+ end
405
+
406
+ =begin
407
+ --- Node#dump(depth = 0)
408
+
409
+ dump the Node.
410
+ =end
411
+ def dump(depth = 0)
412
+ print ' ' * depth * 2
413
+ print nodeName + "\n"
414
+ @children.each do |child|
415
+ child.dump(depth + 1)
416
+ end if @children
417
+ end
418
+
419
+ =begin
420
+ --- Node#inspect()
421
+
422
+ returns the human-readable string representation.
423
+ =end
424
+ def inspect
425
+ "#<#{self.class}: #{self.nodeName}>"
426
+ end
427
+
428
+ =begin
429
+ --- Node#firstChild()
430
+
431
+ [DOM]
432
+ return the first child node.
433
+ =end
434
+ ## [DOM]
435
+ def firstChild
436
+ return nil if !@children || @children.length == 0
437
+ return @children[0]
438
+ end
439
+
440
+ =begin
441
+ --- Node#lastChild()
442
+
443
+ [DOM]
444
+ return the last child node.
445
+ =end
446
+ ## [DOM]
447
+ def lastChild
448
+ return nil if !@children || @children.length == 0
449
+ return @children[-1]
450
+ end
451
+
452
+ =begin
453
+ --- Node#previousSibling()
454
+
455
+ [DOM]
456
+ return the previous sibling node.
457
+ =end
458
+ ## [DOM]
459
+ def previousSibling
460
+ return nil if !@parent
461
+ prev = nil
462
+ @parent.childNodes do |child|
463
+ return prev if child == self
464
+ prev = child
465
+ end
466
+ nil
467
+ end
468
+
469
+ =begin
470
+ --- Node#nextSibling()
471
+
472
+ [DOM]
473
+ return the next sibling node.
474
+ =end
475
+ ## [DOM]
476
+ def nextSibling
477
+ return nil if !@parent
478
+ nexts = nil
479
+ @parent.childNodes.reverse.each do |child|
480
+ return nexts if child == self
481
+ nexts = child
482
+ end
483
+ nil
484
+ end
485
+
486
+ def _getChildIndex(node)
487
+ index = 0
488
+ @children.each do |child|
489
+ if child == node
490
+ return index
491
+ end
492
+ index += 1
493
+ end
494
+ nil
495
+ end
496
+
497
+ def _removeFromTree
498
+ parent = parentNode
499
+ if parent
500
+ parent.removeChild(self)
501
+ end
502
+ end
503
+
504
+ def _checkNode(node)
505
+ raise DOMException.new(DOMException::HIERARCHY_REQUEST_ERR)
506
+ end
507
+
508
+ def _insertNodes(index, node)
509
+ if node.nodeType == DOCUMENT_FRAGMENT_NODE
510
+
511
+ node.childNodes.to_a.each_with_index do |n, i|
512
+ if index == -1
513
+ _insertNodes(-1, n)
514
+ else
515
+ _insertNodes(index + i, n)
516
+ end
517
+ end
518
+ elsif node.is_a?(Node)
519
+ ## to be checked
520
+ _checkNode(node)
521
+ node._removeFromTree
522
+ if index == -1
523
+ @children.push(node)
524
+ else
525
+ @children[index, 0] = node
526
+ end
527
+ node.parentNode = self
528
+ else
529
+ raise ArgumentError, "invalid value for Node"
530
+ end
531
+ end
532
+
533
+ def _removeNode(index, node)
534
+ @children[index, 1] = nil
535
+ node.parentNode = nil
536
+ end
537
+
538
+ # =begin
539
+ # --- Node#insertAfter(newChild, refChild)
540
+ #
541
+ # insert newChild into the node after refChild.
542
+ # =end
543
+ # def insertAfter(newChild, refChild)
544
+ # if @children.nil? || @children.length == 0
545
+ # raise DOMException.new(DOMException::NOT_FOUND_ERR)
546
+ # end
547
+ # index = _getChildIndex(refChild)
548
+ # raise DOMException.new(DOMException::NOT_FOUND_ERR) if index.nil?
549
+ # _insertNodes(index, newChild)
550
+ # end
551
+
552
+ =begin
553
+ --- Node#insertBefore(newChild, refChild)
554
+
555
+ [DOM]
556
+ insert newChild into the node before refChild.
557
+ =end
558
+ ## [DOM]
559
+ def insertBefore(newChild, refChild)
560
+ if @children.nil? || @children.length == 0
561
+ raise DOMException.new(DOMException::NOT_FOUND_ERR)
562
+ end
563
+ index = _getChildIndex(refChild)
564
+ raise DOMException.new(DOMException::NOT_FOUND_ERR) if !index
565
+ _insertNodes(index, newChild)
566
+ end
567
+
568
+ =begin
569
+ --- Node#replaceChild(newChild, oldChild)
570
+
571
+ [DOM]
572
+ replace the child node oldChild with newChild.
573
+ =end
574
+ ## [DOM]
575
+ def replaceChild(newChild, oldChild)
576
+ if @children.nil? || @children.length == 0
577
+ raise DOMException.new(DOMException::NOT_FOUND_ERR)
578
+ end
579
+ index = _getChildIndex(oldChild)
580
+ raise DOMException.new(DOMException::NOT_FOUND_ERR) if !index
581
+ _removeNode(index, oldChild)
582
+ _insertNodes(index, newChild)
583
+ end
584
+
585
+ =begin
586
+ --- Node#removeChild(oldChild)
587
+
588
+ [DOM]
589
+ remove the children node oldChild.
590
+ =end
591
+ ## [DOM]
592
+ def removeChild(oldChild)
593
+ if @children.nil? || @children.length == 0
594
+ raise DOMException.new(DOMException::NOT_FOUND_ERR)
595
+ end
596
+ index = _getChildIndex(oldChild)
597
+ raise DOMException.new(DOMException::NOT_FOUND_ERR) if !index
598
+ _removeNode(index, oldChild)
599
+ oldChild
600
+ end
601
+
602
+ =begin
603
+ --- Node#appendChild(newChild)
604
+
605
+ [DOM]
606
+ adds the node newChild to the end of the list of children of this node.
607
+ =end
608
+ ## [DOM]
609
+ def appendChild(newChild)
610
+ @children = NodeList.new if !@children
611
+ _insertNodes(-1, newChild)
612
+ end
613
+
614
+ =begin
615
+ --- Node#hasChildNodes()
616
+
617
+ [DOM]
618
+ returns true if node has children, or return false if node has no children.
619
+ =end
620
+ ## [DOM]
621
+ def hasChildNodes
622
+ !@children.nil? && @children.length > 0
623
+ end
624
+
625
+ ## get the Node object by IDs
626
+ ## [experimental implement]
627
+ def _searchID(value, ids = nil)
628
+ if ids.nil?
629
+ doc = nil
630
+ if nodeType == DOCUMENT_NODE
631
+ doc = self
632
+ elsif !ownerDocument.nil?
633
+ doc = ownerDocument
634
+ else
635
+ return nil
636
+ end
637
+ ids = doc._getIDAttrs
638
+ end
639
+ if nodeType == ELEMENT_NODE && _getIDVals(ids).include?(value)
640
+ return self
641
+ elsif !@children.nil?
642
+ @children.each do |node|
643
+ if !(match = node._searchID(value, ids)).nil?
644
+ return match
645
+ end
646
+ end
647
+ end
648
+ return nil
649
+ end
650
+
651
+ def _getMyLocation(parent)
652
+ index = parent._getChildIndex(self)
653
+ if !index.nil?
654
+ "child(#{index + 1},#all)"
655
+ else
656
+ nil
657
+ end
658
+ end
659
+
660
+ =begin
661
+ --- Node#makeXPointer(use_id = true)
662
+
663
+ return XPointer's expression of this node.
664
+ =end
665
+ def makeXPointer(use_id = true)
666
+ if use_id && !attributes.nil? && !(idvals = _getIDVals).empty?
667
+ "id(#{idvals[0]})"
668
+ elsif @parent.nil? || @parent.nodeType == DOCUMENT_NODE
669
+ "root()"
670
+ else
671
+ @parent.makeXPointer(use_id) + "." + self._getMyLocation(@parent)
672
+ end
673
+ end
674
+
675
+ ## [Masaki Fukushima]
676
+ def _child(reverse = false)
677
+ return if @children.nil?
678
+ @children.reversible_each(reverse) do |child|
679
+ yield child
680
+ end
681
+ end
682
+
683
+ ## [Masaki Fukushima]
684
+ def _descendant(reverse = false)
685
+ return if @children.nil?
686
+ @children.reversible_each(reverse) do |child|
687
+ yield child
688
+ child._descendant(reverse) do |node|
689
+ yield node
690
+ end
691
+ end
692
+ end
693
+
694
+ ## [Masaki Fukushima]
695
+ def _ancestor(reverse = false)
696
+ return if @parent.nil?
697
+ yield @parent if !reverse
698
+ @parent._ancestor(reverse) do |node| yield node end
699
+ yield @parent if reverse
700
+ end
701
+
702
+ ## [Masaki Fukushima]
703
+ def __sibling(reverse, only_appeared_before_self)
704
+ return if @parent.nil?
705
+ self_appeared = false
706
+ @parent.childNodes.reversible_each(reverse) do |node|
707
+ if node == self
708
+ self_appeared = true
709
+ next
710
+ end
711
+ if only_appeared_before_self
712
+ break if self_appeared
713
+ yield node
714
+ else # only appeared after self
715
+ yield node if self_appeared
716
+ end
717
+ end
718
+ end
719
+
720
+ ## [Masaki Fukushima]
721
+ def _psibling(reverse = false)
722
+ __sibling(!reverse, reverse) do |sib|
723
+ yield sib
724
+ end
725
+ end
726
+
727
+ ## [Masaki Fukushima]
728
+ def _fsibling(reverse = false)
729
+ __sibling(reverse, reverse) do |sib|
730
+ yield sib
731
+ end
732
+ end
733
+
734
+ ## [Masaki Fukushima]
735
+ def _preceding(reverse = false)
736
+ return if @parent.nil?
737
+ prev_sib = previousSibling
738
+ if prev_sib
739
+ prev_sib._preceding(reverse) {|node| yield node} if reverse
740
+ yield prev_sib
741
+ prev_sib._descendant(!reverse) {|node| yield node}
742
+ prev_sib._preceding(reverse) {|node| yield node} if !reverse
743
+ else
744
+ @parent._preceding(reverse) {|node| yield node} if reverse
745
+ yield @parent
746
+ @parent._preceding(reverse) {|node| yield node} if !reverse
747
+ end
748
+ end
749
+
750
+ ## [Masaki Fukushima]
751
+ def _following(reverse = false)
752
+ return if @parent.nil?
753
+ next_sib = nextSibling
754
+ if next_sib
755
+ next_sib._following(reverse) {|node| yield node} if reverse
756
+ yield next_sib
757
+ next_sib._descendant(reverse) {|node| yield node}
758
+ next_sib._following(reverse) {|node| yield node} if !reverse
759
+ else
760
+ @parent._following(reverse) {|node| yield node} if reverse
761
+ yield @parent
762
+ @parent._following(reverse) {|node| yield node} if !reverse
763
+ end
764
+ end
765
+
766
+ ## [Masaki Fukushima]
767
+ def _matchAttribute?(attr, value)
768
+ case value
769
+ when '*'
770
+ return !attr.nil?
771
+ when '#IMPLIED'
772
+ return attr.nil?
773
+ else
774
+ return false if attr.nil?
775
+ end
776
+
777
+ case value
778
+ when /^"([^"]*)"$/, /^'([^']*)'$/
779
+ ignore_case = false
780
+ value = $1
781
+ when Spec::Name
782
+ ignore_case = true
783
+ else
784
+ raise "invalid attribute value: #{value}"
785
+ end
786
+ if ignore_case
787
+ return attr.nodeValue.downcase == value.downcase
788
+ else
789
+ return attr.nodeValue == value
790
+ end
791
+ end
792
+
793
+ ## [Masaki Fukushima]
794
+ def _matchNodeAttributes?(node, attributes)
795
+ return true if attributes.nil?
796
+ raise TypeError if !attributes.is_a?(Hash)
797
+ return true if attributes.length == 0
798
+ return false if node.nodeType != ELEMENT_NODE
799
+
800
+ attributes.each do |name, value|
801
+ case name
802
+ when '*'
803
+ return catch(:match) {
804
+ node.attributes.each do |attr|
805
+ throw(:match, true) if _matchAttribute?(attr, value)
806
+ end
807
+ false
808
+ }
809
+ when Spec::Name
810
+ attr = node.attributes[name] unless node.attributes.nil?
811
+ return _matchAttribute?(attr, value)
812
+ else
813
+ raise "invalid attribute name: '#{name}'"
814
+ end
815
+ end
816
+ end
817
+
818
+ ## [Masaki Fukushima]
819
+ def _matchNodeType?(node, ntype)
820
+ case ntype
821
+ when '#element'
822
+ return (node.nodeType == ELEMENT_NODE)
823
+ when '#pi'
824
+ return (node.nodeType == PROCESSING_INSTRUCTION_NODE)
825
+ when '#comment'
826
+ return (node.nodeType == COMMENT_NODE)
827
+ when '#text'
828
+ return (node.nodeType == TEXT_NODE ||
829
+ node.nodeType == CDATA_SECTION_NODE)
830
+ when '#cdata'
831
+ return (node.nodeType == CDATA_SECTION_NODE)
832
+ when '#all'
833
+ case node.nodeType
834
+ when ELEMENT_NODE, PROCESSING_INSTRUCTION_NODE, COMMENT_NODE,
835
+ TEXT_NODE, CDATA_SECTION_NODE
836
+ return true
837
+ else
838
+ return false
839
+ end
840
+ when /^#/
841
+ raise "unknown node type: '#{ntype}'"
842
+ when Spec::Name
843
+ return (node.nodeType == ELEMENT_NODE && node.nodeName == ntype)
844
+ else
845
+ raise "invalid element type: '#{ntype}'"
846
+ end
847
+ end
848
+
849
+ ## [Masaki Fukushima]
850
+ def _matchNode?(node, ntype, attributes)
851
+ _matchNodeType?(node, ntype) &&
852
+ _matchNodeAttributes?(node, attributes)
853
+ end
854
+
855
+ ## [Masaki Fukushima]
856
+ def _nodesByRelativeLocationTerm(location)
857
+ if location !~ /^([a-z]+)\(([^\)]*)\)$/
858
+ raise "invalid relative location: '#{location}'"
859
+ end
860
+ keyword = $1
861
+ args = $2.split(/,/)
862
+ number = args.shift
863
+ ntype = args.shift
864
+ ntype = '#element' if ntype.nil?
865
+ attributes = args
866
+
867
+ reverse = false
868
+ # check instance number
869
+ case number
870
+ when nil, ''
871
+ raise "missing instance number: '#{location}'"
872
+ when 'all'
873
+ when Spec::Instance
874
+ number = number.to_i
875
+ if number < 0
876
+ reverse = true
877
+ number = -number
878
+ end
879
+ else
880
+ raise "unknown instance number: '#{number}'"
881
+ end
882
+
883
+ # check attributes
884
+ if attributes.length % 2 != 0
885
+ raise " missing attribute value: '#{location}'"
886
+ end
887
+ attributes = Hash[*attributes]
888
+
889
+ # iterate over nodes specified with keyword
890
+ i = 0
891
+ self.send("_#{keyword}", reverse) do |node|
892
+ next unless _matchNode?(node, ntype, attributes)
893
+ if number == "all"
894
+ yield node
895
+ else
896
+ i += 1
897
+ if i >= number
898
+ yield node
899
+ break
900
+ end
901
+ end
902
+ end
903
+ end
904
+
905
+ ## [Masaki Fukushima]
906
+ def _nodesByLocationTerms(location, pre_keyword = nil)
907
+ if location !~ /^([a-z]*)\(([^)]*)\)(\.(.+))?$/
908
+ raise "invalid location: \"#{location}\""
909
+ end
910
+ keyword = $1
911
+ args = $2
912
+ rest = $4
913
+ ## omitted keyword
914
+ keyword = pre_keyword if keyword == ''
915
+ if keyword.nil?
916
+ raise "cannot determine preceding keyword: \"#{location}\""
917
+ end
918
+
919
+ case keyword
920
+ when 'child', 'descendant', 'ancestor', 'psibling', 'fsibling',
921
+ 'preceding', 'following'
922
+ # relative location term
923
+ _nodesByRelativeLocationTerm("#{keyword}(#{args})") do |node|
924
+ if rest.nil?
925
+ yield node
926
+ else
927
+ node._nodesByLocationTerms(rest, keyword) do |n|
928
+ yield n
929
+ end
930
+ end
931
+ end
932
+ when 'attr'
933
+ # attribute location term
934
+ if args !~ Spec::Name
935
+ raise "invalid attribute name: '#{args}'"
936
+ end
937
+ attr = attributes[args]
938
+ value = (attr.nil? ? nil : Text.new(attr.nodeValue))
939
+ if rest.nil?
940
+ yield value
941
+ elsif !value.nil?
942
+ value._nodesByLocationTerms(rest) do |node|
943
+ yield node
944
+ end
945
+ end
946
+ when 'span', 'string'
947
+ raise "unsupported keyword: '#{keyword}'"
948
+ else
949
+ raise "unknown keyword: '#{keyword}'"
950
+ end
951
+ end
952
+
953
+ ## [Masaki Fukushima]
954
+ def _getNodeByAbsoluteLocationTerm(location)
955
+ case location
956
+ when 'root()', ''
957
+ if nodeType == DOCUMENT_NODE
958
+ root = documentElement
959
+ elsif !ownerDocument.nil?
960
+ root = ownerDocument.documentElement
961
+ end
962
+ root = self if root.nil?
963
+ return root
964
+ when 'origin()'
965
+ return self
966
+ when /^id\(([^\)]*)\)$/
967
+ value = $1
968
+ raise "invalid id value: #{value}" if value !~ Spec::Name
969
+ return _searchID(value)
970
+ when /^html\(([^\)]*)\)$/
971
+ value = $1
972
+ return getNodesByXPointer("root().descendant(1,A,NAME,\"#{value}\")")[0]
973
+ else
974
+ raise "unknown keyword: #{location}"
975
+ end
976
+ end
977
+
978
+ =begin
979
+ --- Node#getNodeByXPointer(pointer)
980
+
981
+ return node indicated by the XPointer pointer.
982
+ =end
983
+ ## [Masaki Fukushima]
984
+ def getNodesByXPointer(pointer)
985
+ if pointer !~ /^([a-z]+)\(([^)]*)\)(\.(.+))?$/
986
+ raise "invalid XPointer: \"#{pointer}\""
987
+ end
988
+ keyword = $1
989
+ args = $2
990
+ rest = $4
991
+
992
+ case keyword
993
+ when 'root', 'origin', 'id', 'html'
994
+ src = _getNodeByAbsoluteLocationTerm("#{keyword}(#{args})")
995
+ else
996
+ src = _getNodeByAbsoluteLocationTerm("root()")
997
+ rest = pointer
998
+ end
999
+
1000
+ ret = NodeList.new
1001
+ if src.nil?
1002
+ # no match
1003
+ elsif rest.nil?
1004
+ yield src if iterator?
1005
+ ret << src
1006
+ else
1007
+ src._nodesByLocationTerms(rest) do |node|
1008
+ yield node if iterator?
1009
+ ret << node
1010
+ end
1011
+ end
1012
+ ret
1013
+ end
1014
+
1015
+ =begin
1016
+ --- Node#ownerDocument()
1017
+
1018
+ [DOM]
1019
+ Document object associated with this node.
1020
+ =end
1021
+ ## [DOM]
1022
+ ## Floating objects are not owned by any documents.
1023
+ def ownerDocument
1024
+ return @ownerDocument if @ownerDocument
1025
+ parent = self.parentNode
1026
+ return nil if parent.nil?
1027
+ if parent.nodeType == DOCUMENT_NODE
1028
+ return parent
1029
+ else
1030
+ return parent.ownerDocument
1031
+ end
1032
+ end
1033
+
1034
+ def ownerDocument=(document); @ownerDocument = document; end
1035
+
1036
+
1037
+ =begin
1038
+ --- Node#cloneNode()
1039
+
1040
+ [DOM]
1041
+ return the copy of the Node.
1042
+ =end
1043
+ ## [DOM]
1044
+ def cloneNode(deep = true, *args)
1045
+ ret = self.class.new(*args)
1046
+ if (deep)
1047
+ @children.each do |child|
1048
+ ret.appendChild(child.cloneNode(true))
1049
+ end
1050
+ end if @children
1051
+ ret
1052
+ end
1053
+
1054
+ =begin
1055
+ --- Node#trim(preserve = false)
1056
+
1057
+ trim extra whitespaces.
1058
+ =end
1059
+ ## trim extra whitespaces
1060
+ ## if attribute 'xml:space' is 'preserve',
1061
+ ## don't trim any white spaces
1062
+ def trim(preserve = false)
1063
+ return nil if @children.nil?
1064
+ children = @children.to_a.dup
1065
+ children.each do |child|
1066
+ if !preserve && (child.nodeType == TEXT_NODE ||
1067
+ child.nodeType == CDATA_SECTION_NODE)
1068
+ if child.trim == ""
1069
+ self.removeChild(child)
1070
+ end
1071
+ else
1072
+ child.trim(preserve)
1073
+ end
1074
+ end
1075
+ nil
1076
+ end
1077
+
1078
+
1079
+ end
1080
+
1081
+ =begin
1082
+ == Class XML::DOM::NamedNodeMap
1083
+
1084
+ =end
1085
+
1086
+ class NamedNodeMap
1087
+
1088
+ =begin
1089
+ === Class Methods
1090
+
1091
+ --- NamedNodeMap.new(nodes = nil)
1092
+
1093
+ creates a new NamedNodeMap.
1094
+ =end
1095
+ def initialize(nodes = nil)
1096
+ @nodes = {}
1097
+ nodes.each do |node|
1098
+ @nodes[node.nodeName] = node
1099
+ end if nodes
1100
+ end
1101
+
1102
+ =begin
1103
+ === Methods
1104
+
1105
+ --- NamedNodeMap#getNamedItem(name)
1106
+
1107
+ [DOM]
1108
+ retrieves a node specified by name.
1109
+ =end
1110
+ ## [DOM]
1111
+ def getNamedItem(name)
1112
+ @nodes[name]
1113
+ end
1114
+
1115
+ =begin
1116
+ --- NamedNodeMap#setNamedItem(node)
1117
+
1118
+ [DOM]
1119
+ adds a node using its nodeName attribute.
1120
+ =end
1121
+ ## [DOM]
1122
+ def setNamedItem(node)
1123
+ @nodes[node.nodeName] = node
1124
+ end
1125
+
1126
+ =begin
1127
+ --- NamedNodeMap#removeNamedItem(name)
1128
+
1129
+ [DOM]
1130
+ removes a node specified by name.
1131
+ =end
1132
+ ## [DOM]
1133
+ def removeNamedItem(name)
1134
+ ret = @nodes[name]
1135
+ @nodes[name] = nil
1136
+ ret
1137
+ end
1138
+
1139
+ =begin
1140
+ --- NamedNodeMap#item(index)
1141
+
1142
+ [DOM]
1143
+ returns the index item in the map.
1144
+ =end
1145
+ ## [DOM]
1146
+ def item(index)
1147
+ v = @nodes.to_a[index]
1148
+ return v[1] if v
1149
+ nil
1150
+ end
1151
+
1152
+ =begin
1153
+ --- NamedNodeMap#[](name)
1154
+
1155
+ returns nodes associated to name.
1156
+ =end
1157
+ def [](name)
1158
+ @nodes[name]
1159
+ end
1160
+
1161
+ =begin
1162
+ --- NamedNodeMap#[]=(name, node)
1163
+
1164
+ sets node named name.
1165
+ =end
1166
+ def []=(name, node)
1167
+ raise "parameter error" if node.nodeName != name
1168
+ @nodes[name] = node
1169
+ end
1170
+
1171
+ =begin
1172
+ --- NamedNodeMap#each()
1173
+
1174
+ iterates over each pair of name and node(name, node) of the namedNodeMap.
1175
+ =end
1176
+ def each
1177
+ @nodes.each do |key, value|
1178
+ yield(value)
1179
+ end
1180
+ end
1181
+
1182
+ =begin
1183
+ --- NamedNodeMap#size()
1184
+
1185
+ [DOM]
1186
+ returns the number of nodes in the map.
1187
+ =end
1188
+ ## [DOM]
1189
+ def size
1190
+ @nodes.length
1191
+ end
1192
+ alias length size
1193
+
1194
+ ## get nodeValues by names
1195
+ ## names ::= name ('|' name)*
1196
+ def _getValues(names)
1197
+ ret = []
1198
+ names.split('|').each do |name|
1199
+ if !@nodes[name].nil?
1200
+ ret.push(@nodes[name].nodeValue)
1201
+ end
1202
+ end
1203
+ ret
1204
+ end
1205
+ end
1206
+
1207
+ =begin
1208
+ == Class XML::DOM::NodeList
1209
+
1210
+
1211
+ =end
1212
+ class NodeList
1213
+
1214
+ =begin
1215
+ === Class Methods
1216
+
1217
+ --- NodeList.new(nodes = nil)
1218
+
1219
+ creates a new NodeList.
1220
+ =end
1221
+ def initialize(nodes = nil)
1222
+ if nodes.nil?
1223
+ @nodes = []
1224
+ elsif nodes.is_a?(Array)
1225
+ @nodes = nodes
1226
+ else
1227
+ raise "parameter error"
1228
+ end
1229
+ end
1230
+
1231
+ =begin
1232
+ === Methods
1233
+
1234
+ --- NodeList#item(index)
1235
+
1236
+ [DOM]
1237
+ return the indexth item in the NodeList.
1238
+ =end
1239
+ ## [DOM]
1240
+ def item(index)
1241
+ @nodes[index]
1242
+ end
1243
+
1244
+ =begin
1245
+ --- NodeList#size()
1246
+
1247
+ return size of NodeList.
1248
+ =end
1249
+ def size
1250
+ @nodes.length
1251
+ end
1252
+ alias length size
1253
+
1254
+ =begin
1255
+ --- NodeList#[](index)
1256
+
1257
+ return indexth node of the NodeList.
1258
+ =end
1259
+ def [](index)
1260
+ @nodes[index]
1261
+ end
1262
+
1263
+ =begin
1264
+ --- NodeList#[]=(*p)
1265
+
1266
+ set node of indexth node of the NodeList.
1267
+ =end
1268
+ def []=(*p)
1269
+ if p.length == 2
1270
+ @nodes[p[0]] = p[1]
1271
+ elsif p.length == 3
1272
+ @nodes[p[0], p[1]] = p[2]
1273
+ end
1274
+ end
1275
+
1276
+ =begin
1277
+ --- NodeList#each
1278
+
1279
+ iterates over each node of the NodeList.
1280
+ =end
1281
+ def each
1282
+ @nodes.each do |value|
1283
+ yield(value)
1284
+ end
1285
+ end
1286
+
1287
+ =begin
1288
+ --- NodeList#reversible_each(reverse = false)
1289
+
1290
+ iterates over each node of the reversed NodeList.
1291
+ =end
1292
+ ## [Masaki Fukushima]
1293
+ def reversible_each(reverse = false)
1294
+ if !reverse
1295
+ @nodes.each do |value|
1296
+ yield(value)
1297
+ end
1298
+ else
1299
+ @nodes.reverse_each do |value|
1300
+ yield(value)
1301
+ end
1302
+ end
1303
+ end
1304
+
1305
+ =begin
1306
+ --- NodeList#push(*nodes)
1307
+
1308
+ adds nodes into the NodeList.
1309
+ =end
1310
+ def push(*nodes)
1311
+ nodes.each do |node|
1312
+ if node.is_a?(Array)
1313
+ self.push(*node)
1314
+ elsif node.is_a?(NodeList)
1315
+ @nodes.concat(node.to_a)
1316
+ elsif node.is_a?(Node)
1317
+ @nodes << node
1318
+ else
1319
+ raise "parameter error"
1320
+ end
1321
+ end
1322
+ self
1323
+ end
1324
+
1325
+ =begin
1326
+ --- NodeList#concat(*nodes)
1327
+
1328
+ alias of NodeList#push.
1329
+ =end
1330
+ alias concat push
1331
+
1332
+ =begin
1333
+ --- NodeList#pop
1334
+
1335
+ pops and returns the last node of the NodeList.
1336
+ =end
1337
+ def pop
1338
+ @nodes.pop
1339
+ end
1340
+
1341
+ =begin
1342
+ --- NodeList#shift
1343
+
1344
+ removes and returns the first node of the NodeList.
1345
+ =end
1346
+ def shift
1347
+ @nodes.shift
1348
+ end
1349
+
1350
+ =begin
1351
+ --- NodeList#to_s
1352
+
1353
+ returns the string representation of the NodeList.
1354
+ =end
1355
+ def to_s
1356
+ @nodes.to_s
1357
+ end
1358
+
1359
+ =begin
1360
+ --- NodeList#reverse
1361
+
1362
+ returns the reversed NodeList.
1363
+ =end
1364
+ def reverse
1365
+ @nodes.reverse
1366
+ end
1367
+
1368
+ =begin
1369
+ --- NodeList#to_a
1370
+
1371
+ converts the NodeList into an array.
1372
+ =end
1373
+ def to_a
1374
+ @nodes
1375
+ end
1376
+
1377
+ =begin
1378
+ --- NodeList#+(nodes)
1379
+
1380
+ return the newly created concatenated NodeList.
1381
+ =end
1382
+ def +(nodes)
1383
+ if nodes.nil?
1384
+ NodeList.new(@nodes)
1385
+ elsif nodes.is_a?(Array)
1386
+ NodeList.new(@nodes + nodes)
1387
+ elsif nodes.is_a?(NodeList)
1388
+ NodeList.new(@nodes + nodes.to_a)
1389
+ elsif nodes.is_a?(Node)
1390
+ NodeList.new(@nodes + [nodes])
1391
+ else
1392
+ raise "parameter error"
1393
+ end
1394
+ end
1395
+
1396
+ =begin
1397
+ --- NodeList#<<(nodes)
1398
+
1399
+ appends nodes to the NodeList.
1400
+ =end
1401
+ ## modified by Masaki Fukushima
1402
+ def <<(nodes)
1403
+ if nodes.nil?
1404
+ ## no change
1405
+ elsif nodes.is_a?(Array)
1406
+ @nodes.concat(nodes)
1407
+ elsif nodes.is_a?(NodeList)
1408
+ @nodes.concat(nodes.to_a)
1409
+ elsif nodes.is_a?(Node)
1410
+ @nodes << nodes
1411
+ else
1412
+ raise "parameter error"
1413
+ end
1414
+ self
1415
+ end
1416
+
1417
+ ## get nodeValues by names
1418
+ ## names ::= name ('|' name)*
1419
+ def _getValues(names)
1420
+ ret = []
1421
+ names.split('|').each do |name|
1422
+ if !@nodes[name].nil?
1423
+ ret.push(@nodes[name].nodeValue)
1424
+ end
1425
+ end
1426
+ ret
1427
+ end
1428
+ end
1429
+
1430
+ =begin
1431
+ == Class XML::DOM::DocumentFragment
1432
+
1433
+ === superclass
1434
+ Node
1435
+
1436
+ =end
1437
+ class DocumentFragment<Node
1438
+
1439
+ =begin
1440
+ === Class Methods
1441
+
1442
+ --- DocumentFragment.new(*children)
1443
+
1444
+ creates a new DocumentFragment.
1445
+ =end
1446
+
1447
+ def initialize(*children)
1448
+ super(*children)
1449
+ end
1450
+
1451
+ =begin
1452
+ === Methods
1453
+
1454
+ --- DocumentFragment#nodeType
1455
+
1456
+ [DOM]
1457
+ returns the nodeType.
1458
+ =end
1459
+ ## [DOM]
1460
+ def nodeType
1461
+ DOCUMENT_FRAGMENT_NODE
1462
+ end
1463
+
1464
+ =begin
1465
+ --- DocumentFragment#nodeName
1466
+
1467
+ [DOM]
1468
+ returns the nodeName.
1469
+ =end
1470
+ ## [DOM]
1471
+ def nodeName
1472
+ "#document-fragment"
1473
+ end
1474
+
1475
+ =begin
1476
+ --- DocumentFragment#parentNode=(p)
1477
+
1478
+ returns the parent of this node.
1479
+ =end
1480
+ ## DocumentFragment should not have the parent node.
1481
+ def parentNode=(p)
1482
+ @children.each do |child|
1483
+ child.parentNode = p
1484
+ end if @children
1485
+ end
1486
+
1487
+ def _checkNode(node)
1488
+ unless node.nodeType == ELEMENT_NODE ||
1489
+ node.nodeType == PROCESSING_INSTRUCTION_NODE ||
1490
+ node.nodeType == COMMENT_NODE ||
1491
+ node.nodeType == TEXT_NODE ||
1492
+ node.nodeType == CDATA_SECTION_NODE ||
1493
+ node.nodeType == ENTITY_REFERENCE_NODE
1494
+ raise DOMException.new(DOMException::HIERARCHY_REQUEST_ERR)
1495
+ end
1496
+ end
1497
+
1498
+ end
1499
+
1500
+ =begin
1501
+ == Class XML::DOM::Document
1502
+
1503
+ === superclass
1504
+ Node
1505
+
1506
+ =end
1507
+ class Document<Node
1508
+ =begin
1509
+ === Class Methods
1510
+ --- Document.new(*children)
1511
+
1512
+ creates a new Document.
1513
+ =end
1514
+
1515
+ ## new([child1, child2, ...]) or
1516
+ ## new(child1, child2, ...)
1517
+ ## child?: String or Node
1518
+ def initialize(*children)
1519
+ super(*children)
1520
+ end
1521
+
1522
+ =begin
1523
+ === Methods
1524
+
1525
+ --- Document#nodeType
1526
+
1527
+ [DOM]
1528
+ returns the nodeType.
1529
+ =end
1530
+ ## [DOM]
1531
+ def nodeType
1532
+ DOCUMENT_NODE
1533
+ end
1534
+
1535
+ =begin
1536
+ --- Document#nodeName
1537
+
1538
+ [DOM]
1539
+ returns the nodeName.
1540
+ =end
1541
+ ## [DOM]
1542
+ def nodeName
1543
+ "#document"
1544
+ end
1545
+
1546
+ =begin
1547
+ --- Document#documentElement
1548
+
1549
+ [DOM]
1550
+ returns root element of the Docuemnt.
1551
+ =end
1552
+ ## [DOM]
1553
+ def documentElement
1554
+ @children.each do |child|
1555
+ if child.nodeType == ELEMENT_NODE
1556
+ return child
1557
+ end
1558
+ end if @children
1559
+ nil
1560
+ end
1561
+
1562
+ =begin
1563
+ --- Document#doctype
1564
+
1565
+ [DOM]
1566
+ returns DTD associated with this document.
1567
+ =end
1568
+ ## [DOM]
1569
+ def doctype
1570
+ @children.each do |child|
1571
+ if child.nodeType == DOCUMENT_TYPE_NODE
1572
+ return child
1573
+ end
1574
+ end if @children
1575
+ nil
1576
+ end
1577
+
1578
+ =begin
1579
+ --- Document#getElementsByTagName(tagname)
1580
+
1581
+ [DOM]
1582
+ returns a NodeList of all the Elements with a given tag name.
1583
+ =end
1584
+ ## [DOM] (but this is not "live")
1585
+ def getElementsByTagName(tagname)
1586
+ ret = NodeList.new
1587
+ @children.each do |node|
1588
+ if node.nodeType == ELEMENT_NODE
1589
+ if tagname == '*' || node.nodeName == tagname
1590
+ ret << node
1591
+ end
1592
+ ret << node.getElementsByTagName(tagname)
1593
+ end
1594
+ end if @children
1595
+ ret
1596
+ end
1597
+
1598
+ =begin
1599
+ --- Document#createElement(tagName)
1600
+
1601
+ [DOM]
1602
+ creates a Element.
1603
+ =end
1604
+ ## [DOM]
1605
+ def createElement(tagName)
1606
+ ret = Element.new(tagName)
1607
+ ret.ownerDocument = self
1608
+ ret
1609
+ end
1610
+
1611
+ =begin
1612
+ --- Document#createTextNode(data)
1613
+
1614
+ [DOM]
1615
+ creates a TextNode.
1616
+ =end
1617
+ ## [DOM]
1618
+ def createTextNode(data)
1619
+ ret = Text.new(data)
1620
+ ret.ownerDocument = self
1621
+ ret
1622
+ end
1623
+
1624
+ =begin
1625
+ --- Document#createCDATASection(data)
1626
+
1627
+ [DOM]
1628
+ creates a CDATASection.
1629
+ =end
1630
+ ## [DOM]
1631
+ def createCDATASection(data)
1632
+ ret = CDATASection.new(data)
1633
+ ret.ownerDocument = self
1634
+ ret
1635
+ end
1636
+
1637
+ =begin
1638
+ --- Document#createComment(data)
1639
+
1640
+ [DOM]
1641
+ create a Comment.
1642
+ =end
1643
+ ## [DOM]
1644
+ def createComment(data)
1645
+ ret = Comment.new(data)
1646
+ ret.ownerDocument = self
1647
+ ret
1648
+ end
1649
+
1650
+ =begin
1651
+ --- Document#createProcessingInstruction(target, data)
1652
+
1653
+ [DOM]
1654
+ create a ProcessingInstruction.
1655
+ =end
1656
+ ## [DOM]
1657
+ def createProcessingInstruction(target, data)
1658
+ ret = ProcessingInstruction.new(target, data)
1659
+ ret.ownerDocument = self
1660
+ ret
1661
+ end
1662
+
1663
+ =begin
1664
+ --- Document#createAttribute(name)
1665
+
1666
+ [DOM]
1667
+ create a Attribute.
1668
+ =end
1669
+ ## [DOM]
1670
+ def createAttribute(name)
1671
+ ret = Attr.new(name)
1672
+ ret.ownerDocument = self
1673
+ ret
1674
+ end
1675
+
1676
+ =begin
1677
+ --- Document#createEntityReference(name)
1678
+
1679
+ [DOM]
1680
+ create a EntityReference.
1681
+ =end
1682
+ ## [DOM]
1683
+ def createEntityReference(name)
1684
+ ret = EntityReference.new(name)
1685
+ ret.ownerDocument = self
1686
+ ret
1687
+ end
1688
+
1689
+ =begin
1690
+ --- Document#createDocumentFragment()
1691
+
1692
+ [DOM]
1693
+ create a DocumentFragment.
1694
+ =end
1695
+ ## [DOM]
1696
+ def createDocumentFragment
1697
+ ret = DocumentFragment.new
1698
+ ret.ownerDocument = self
1699
+ ret
1700
+ end
1701
+
1702
+ ## set the ID list by the attribute name with the element name
1703
+ ## (or wildcard)
1704
+ ## [experimental implement]
1705
+ def _setIDAttr(attrname, elemname = '*')
1706
+ @idattrs = {} if @idattrs.nil?
1707
+ @idattrs[elemname] = attrname
1708
+ end
1709
+
1710
+ ## get the ID list
1711
+ ## [experimental implement]
1712
+ def _getIDAttrs
1713
+ return {'*'=>'id'} if @idattrs.nil?
1714
+ @idattrs
1715
+ end
1716
+
1717
+ ## [DOM]
1718
+ def implementation
1719
+ return @implemantation if @implemantation
1720
+ ## singleton
1721
+ @implemantation = DOMImplementation.instance
1722
+ end
1723
+
1724
+ def implementation=(impl)
1725
+ @implemantation = impl
1726
+ end
1727
+
1728
+ def _checkNode(node)
1729
+ unless node.nodeType == ELEMENT_NODE ||
1730
+ node.nodeType == PROCESSING_INSTRUCTION_NODE ||
1731
+ node.nodeType == COMMENT_NODE ||
1732
+ node.nodeType == DOCUMENT_TYPE_NODE
1733
+ raise DOMException.new(DOMException::HIERARCHY_REQUEST_ERR)
1734
+ end
1735
+
1736
+ if node.nodeType == ELEMENT_NODE
1737
+ @children.each do |n|
1738
+ if n.nodeType == ELEMENT_NODE
1739
+ raise DOMException.new(DOMException::HIERARCHY_REQUEST_ERR)
1740
+ end
1741
+ end
1742
+ end
1743
+
1744
+ if node.nodeType == DOCUMENT_TYPE_NODE
1745
+ @children.each do |n|
1746
+ if n.nodeType == DOCUMENT_TYPE_NODE
1747
+ raise DOMException.new(DOMException::HIERARCHY_REQUEST_ERR)
1748
+ end
1749
+ end
1750
+ end
1751
+ end
1752
+
1753
+ end
1754
+
1755
+ =begin
1756
+ == Class XML::DOM::Attr
1757
+
1758
+ === superclass
1759
+ Node
1760
+
1761
+ =end
1762
+ class Attr<Node
1763
+ ## new(name, [text1, text2, ...]) or
1764
+ ## new(name, text1, text2, ...)
1765
+ ## name: String
1766
+ ## text?: String or Node
1767
+
1768
+ =begin
1769
+ === Class Methods
1770
+
1771
+ --- Attr.new(name = nil, *text)
1772
+
1773
+ create a new Attr.
1774
+ =end
1775
+ def initialize(name = nil, *text)
1776
+ super(text)
1777
+ raise "parameter error" if !name
1778
+ @name = name
1779
+ @name.freeze
1780
+ end
1781
+
1782
+ =begin
1783
+ === Methods
1784
+
1785
+ --- Attr#nodeType()
1786
+
1787
+ [DOM]
1788
+ returns the nodeType.
1789
+ =end
1790
+ ## [DOM]
1791
+ def nodeType
1792
+ ATTRIBUTE_NODE
1793
+ end
1794
+
1795
+ =begin
1796
+ --- Attr#nodeName()
1797
+
1798
+ [DOM]
1799
+ returns the nodeName.
1800
+ =end
1801
+ ## [DOM]
1802
+ def nodeName
1803
+ @name
1804
+ end
1805
+
1806
+ =begin
1807
+ --- Attr#nodeValue()
1808
+
1809
+ [DOM]
1810
+ returns the nodeValue.
1811
+ =end
1812
+ ## [DOM]
1813
+ def nodeValue
1814
+ ret = ""
1815
+ @children.each do |child|
1816
+ ret << child.nodeValue
1817
+ end if @children
1818
+ ret
1819
+ end
1820
+
1821
+ =begin
1822
+ --- Attr#nodeValue=(text)
1823
+
1824
+ [DOM]
1825
+ returns the value of this node.
1826
+ =end
1827
+ ## [DOM]
1828
+ def nodeValue=(text)
1829
+ self.childNodes = [text]
1830
+ end
1831
+
1832
+ =begin
1833
+ --- Attr#to_s()
1834
+
1835
+ return the string representation of the Attr.
1836
+ =end
1837
+ def to_s
1838
+ value = ""
1839
+ nodeValue.each_byte do |code|
1840
+ case code
1841
+ when 9, 10, 13
1842
+ value << sprintf("&#x%X;", code)
1843
+ when ?&
1844
+ value << "&amp;"
1845
+ when ?"
1846
+ value << "&quot;"
1847
+ when ?<
1848
+ value << "&lt;"
1849
+ else
1850
+ value << code
1851
+ end
1852
+ end
1853
+ "#{@name}=\"#{value}\""
1854
+ end
1855
+
1856
+ =begin
1857
+ --- Attr#dump(depth = 0)
1858
+
1859
+ dump the Attr.
1860
+ =end
1861
+ def dump(depth = 0)
1862
+ print ' ' * depth * 2
1863
+ print "// #{self.to_s}\n"
1864
+ end
1865
+
1866
+ =begin
1867
+ --- Attr#cloneNode(deep = true)
1868
+
1869
+ [DOM]
1870
+ returns the copy of the Attr.
1871
+ =end
1872
+ ## [DOM]
1873
+ def cloneNode(deep = true)
1874
+ super(deep, @name)
1875
+ end
1876
+
1877
+ =begin
1878
+ --- Attr#name()
1879
+
1880
+ [DOM]
1881
+ alias of nodeName.
1882
+ =end
1883
+ ## [DOM]
1884
+ alias name nodeName
1885
+
1886
+ =begin
1887
+ --- Attr#value()
1888
+
1889
+ alias of nodeValue.
1890
+
1891
+ --- Attr#value=(value)
1892
+
1893
+ [DOM]
1894
+ alias of nodeValue=.
1895
+ =end
1896
+ ## [DOM]
1897
+ alias value nodeValue
1898
+ alias value= nodeValue=
1899
+
1900
+ ## [DOM]
1901
+ def specified; @specified; end
1902
+ def specified=(is_specified); @specified = is_specified; end
1903
+
1904
+ def _checkNode(node)
1905
+ unless node.nodeType == TEXT_NODE ||
1906
+ node.nodeType == ENTITY_REFERENCE_NODE
1907
+ raise DOMException.new(DOMException::HIERARCHY_REQUEST_ERR)
1908
+ end
1909
+ end
1910
+
1911
+ end
1912
+
1913
+ =begin
1914
+ == Class XML::DOM::Attribute
1915
+
1916
+ alias of Attr.
1917
+ =end
1918
+ Attribute = Attr
1919
+
1920
+ =begin
1921
+ == Class XML::DOM::Element
1922
+
1923
+ === superclass
1924
+ Node
1925
+
1926
+ =end
1927
+ class Element<Node
1928
+
1929
+ =begin
1930
+ === Class Methods
1931
+
1932
+ --- Element.new(tag = nil, attrs = nil, *children)
1933
+
1934
+ create a new Element.
1935
+ =end
1936
+ ## new(tag, attrs, [child1, child2, ...]) or
1937
+ ## new(tag, attrs, child1, child2, ...)
1938
+ ## tag: String
1939
+ ## attrs: Hash, Attr or Array of Attr (or nil)
1940
+ ## child?: String or Node
1941
+ def initialize(tag = nil, attr = nil, *children)
1942
+ super(*children)
1943
+ raise "parameter error" if !tag
1944
+ @name = tag.freeze
1945
+ if attr.nil?
1946
+ @attr = NamedNodeMap.new([])
1947
+ elsif attr.is_a?(Hash)
1948
+ nodes = []
1949
+ attr.each do |key, value|
1950
+ nodes.push(Attr.new(key, value))
1951
+ end
1952
+ @attr = NamedNodeMap.new(nodes)
1953
+ elsif attr.is_a?(Array)
1954
+ @attr = NamedNodeMap.new(attr)
1955
+ elsif attr.is_a?(Attr)
1956
+ @attr = NamedNodeMap.new([attr])
1957
+ else
1958
+ raise "parameter error: #{attr}"
1959
+ end
1960
+ end
1961
+
1962
+ =begin
1963
+ === Methods
1964
+
1965
+ --- Element#nodeType()
1966
+
1967
+ [DOM]
1968
+ returns the nodeType.
1969
+ =end
1970
+ ## [DOM]
1971
+ def nodeType
1972
+ ELEMENT_NODE
1973
+ end
1974
+
1975
+ =begin
1976
+ --- Element#nodeName()
1977
+
1978
+ [DOM]
1979
+ returns the nodeName.
1980
+ =end
1981
+ ## [DOM]
1982
+ def nodeName
1983
+ @name
1984
+ end
1985
+
1986
+ =begin
1987
+ --- Element#attributes()
1988
+
1989
+ [DOM]
1990
+ returns the attributes of this Element.
1991
+ =end
1992
+ ## [DOM]
1993
+ def attributes
1994
+ if iterator?
1995
+ @attr.each do |key, value|
1996
+ yield(value)
1997
+ end if @attr
1998
+ else
1999
+ @attr
2000
+ end
2001
+ end
2002
+
2003
+ =begin
2004
+ --- Element#to_s()
2005
+
2006
+ return the string representation of the Element.
2007
+ =end
2008
+ def to_s
2009
+ attr = ''
2010
+ @attr.each do |a|
2011
+ attr << ' ' + a.to_s
2012
+ end if @attr
2013
+ content = super
2014
+ if content != ''
2015
+ ret = "<#{@name}#{attr}>#{content}</#{@name}>"
2016
+ else
2017
+ ret = "<#{@name}#{attr}/>"
2018
+ end
2019
+ ret << "\n" if parentNode.nodeType == DOCUMENT_NODE
2020
+ ret
2021
+ end
2022
+
2023
+ =begin
2024
+ --- Element#dump(depth = 0)
2025
+
2026
+ dumps the Element.
2027
+ =end
2028
+ def dump(depth = 0)
2029
+ attr = ''
2030
+ @attr.each do |a| ## self.attributes do |a|
2031
+ attr += a.to_s + ", "
2032
+ end if @attr
2033
+ attr.chop!
2034
+ attr.chop!
2035
+ print ' ' * depth * 2
2036
+ print "#{@name}(#{attr})\n"
2037
+ @children.each do |child|
2038
+ child.dump(depth + 1)
2039
+ end if @children
2040
+ end
2041
+
2042
+ =begin
2043
+ --- Element#tagName()
2044
+
2045
+ [DOM]
2046
+ alias of nodeName.
2047
+ =end
2048
+ ## [DOM]
2049
+ alias tagName nodeName
2050
+
2051
+ =begin
2052
+ --- Element#getAttribute(name)
2053
+
2054
+ [DOM]
2055
+ retrieves an attribute value by name.
2056
+ =end
2057
+ ## [DOM]
2058
+ def getAttribute(name)
2059
+ attr = getAttributeNode(name)
2060
+ if attr.nil?
2061
+ ''
2062
+ else
2063
+ attr.nodeValue
2064
+ end
2065
+ end
2066
+
2067
+ =begin
2068
+ --- Element#setAttribute(name, value)
2069
+
2070
+ [DOM]
2071
+ adds a new attribute.
2072
+ =end
2073
+ ## [DOM]
2074
+ def setAttribute(name, value)
2075
+ if @ownerDocument
2076
+ attr = @ownerDocument.createAttribute(name)
2077
+ attr.appendChild(@ownerDocument.createTextNode(value))
2078
+ else
2079
+ attr = Attribute.new(name)
2080
+ attr.appendChild(Text.new(value))
2081
+ end
2082
+ setAttributeNode(attr)
2083
+ end
2084
+
2085
+ =begin
2086
+ --- Element#removeAttribute(name)
2087
+
2088
+ [DOM]
2089
+ remove an attribute by name.
2090
+ =end
2091
+ ## [DOM]
2092
+ def removeAttribute(name)
2093
+ ret = getAttributeNode(name)
2094
+ removeAttributeNode(ret) if ret
2095
+ end
2096
+
2097
+ =begin
2098
+ --- Element#getAttributeNode(name)
2099
+
2100
+ [DOM]
2101
+ retrieves an Attr node by name.
2102
+ =end
2103
+ ## [DOM]
2104
+ def getAttributeNode(name)
2105
+ @attr.getNamedItem(name)
2106
+ end
2107
+
2108
+ =begin
2109
+ --- Element#setAttributeNode(newAttr)
2110
+
2111
+ [DOM]
2112
+ adds a new attribute.
2113
+ =end
2114
+ ## [DOM]
2115
+ def setAttributeNode(newAttr)
2116
+ ret = getAttributeNode(newAttr.nodeName)
2117
+ if ret == newAttr
2118
+ raise DOMException.new(DOMException::INUSE_ATTRIBUTE_ERR)
2119
+ end
2120
+ @attr.setNamedItem(newAttr)
2121
+ ret
2122
+ end
2123
+
2124
+ =begin
2125
+ --- Element#removeAttributeNode(oldAttr)
2126
+
2127
+ [DOM]
2128
+ removes the specified attribute.
2129
+ =end
2130
+ ## [DOM]
2131
+ def removeAttributeNode(oldAttr)
2132
+ ret = getAttributeNode(oldAttr.nodeName)
2133
+ if ret.nil? || ret != oldAttr
2134
+ raise DOMException.new(DOMException::NOT_FOUND_ERR)
2135
+ end
2136
+ @attr.removeNamedItem(oldAttr.nodeName)
2137
+ ret
2138
+ end
2139
+
2140
+ =begin
2141
+ --- Element#getElementsByTagName(tagname)
2142
+
2143
+ [DOM]
2144
+ returns a NodeList of all descendant elements with given tag name.
2145
+ =end
2146
+ ## [DOM] (but this is not "live")
2147
+ def getElementsByTagName(tagname)
2148
+ ret = NodeList.new
2149
+ @children.each do |node|
2150
+ if node.nodeType == ELEMENT_NODE
2151
+ if tagname == '*' || node.nodeName == tagname
2152
+ ret << node
2153
+ end
2154
+ ret << node.getElementsByTagName(tagname)
2155
+ end
2156
+ end if @children
2157
+ ret
2158
+ end
2159
+
2160
+ def _getMyLocation(parent)
2161
+ index = 1
2162
+ parent.childNodes do |child|
2163
+ if child == self
2164
+ return "child(#{index},#{@name})"
2165
+ end
2166
+ if child.nodeType == ELEMENT_NODE && child.nodeName == @name
2167
+ index += 1
2168
+ end
2169
+ end
2170
+ nil
2171
+ end
2172
+
2173
+
2174
+ =begin
2175
+ --- Element#normalize
2176
+
2177
+ [DOM]
2178
+ puts all Text nodes in the full depth of the sub-tree under this
2179
+ Eelemnt.
2180
+ =end
2181
+ ## [DOM]
2182
+ def normalize
2183
+ return if @children.nil?
2184
+ old = nil
2185
+ children = @children.to_a.dup
2186
+ children.each do |child|
2187
+ if !old.nil? && old.nodeType == TEXT_NODE &&
2188
+ child.nodeType == TEXT_NODE
2189
+ old.appendData(child.nodeValue)
2190
+ self.removeChild(child)
2191
+ else
2192
+ if child.nodeType == ELEMENT_NODE
2193
+ child.normalize
2194
+ end
2195
+ old = child
2196
+ end
2197
+ end
2198
+ end
2199
+
2200
+ =begin
2201
+ --- Element#cloneNode(deep = true)
2202
+
2203
+ [DOM]
2204
+ returns the copy of the Element.
2205
+ =end
2206
+ ## [DOM]
2207
+ def cloneNode(deep = true)
2208
+ attrs = []
2209
+ @attr.each do |attr|
2210
+ attrs.push(attr.cloneNode(true))
2211
+ end
2212
+ super(deep, @name, attrs)
2213
+ end
2214
+
2215
+ ## get the list of nodeValues by IDs
2216
+ ## [experimental implement]
2217
+ def _getIDVals(ids = nil)
2218
+ if ids.nil?
2219
+ doc = ownerDocument
2220
+ return [] if doc.nil?
2221
+ ids = doc._getIDAttrs
2222
+ end
2223
+
2224
+ idelem = []
2225
+ if !ids[nodeName].nil?
2226
+ return attributes._getValues(ids[nodeName])
2227
+ elsif !ids['*'].nil?
2228
+ return attributes._getValues(ids['*'])
2229
+ end
2230
+ return []
2231
+ end
2232
+
2233
+ =begin
2234
+ --- Element#trim(preserve = false)
2235
+
2236
+ trim extra whitespaces.
2237
+ =end
2238
+ ## trim extra whitespaces
2239
+ ## if attribute 'xml:space' is 'preserve',
2240
+ ## don't trim any white spaces
2241
+ def trim(preserve = false)
2242
+ if !attributes['xml:space'].nil?
2243
+ value = attributes['xml:space'].nodeValue
2244
+ if value == 'preserve'
2245
+ preserve = true
2246
+ elsif value == 'default'
2247
+ preserve = false
2248
+ end
2249
+ end
2250
+ return nil if @children.nil?
2251
+ children = @children.to_a.dup
2252
+ children.each do |child|
2253
+ if !preserve && (child.nodeType == TEXT_NODE ||
2254
+ child.nodeType == CDATA_SECTION_NODE)
2255
+ if child.trim == ""
2256
+ self.removeChild(child)
2257
+ end
2258
+ else
2259
+ child.trim(preserve)
2260
+ end
2261
+ end
2262
+ nil
2263
+ end
2264
+
2265
+ def _checkNode(node)
2266
+ unless node.nodeType == ELEMENT_NODE ||
2267
+ node.nodeType == TEXT_NODE ||
2268
+ node.nodeType == COMMENT_NODE ||
2269
+ node.nodeType == PROCESSING_INSTRUCTION_NODE ||
2270
+ node.nodeType == CDATA_SECTION_NODE ||
2271
+ node.nodeType == ENTITY_REFERENCE_NODE
2272
+ raise DOMException.new(DOMException::HIERARCHY_REQUEST_ERR)
2273
+ end
2274
+ end
2275
+
2276
+ end
2277
+
2278
+ =begin
2279
+ == Class XML::DOM::CharacterData
2280
+
2281
+ === superclass
2282
+ Node
2283
+
2284
+ =end
2285
+ class CharacterData<Node
2286
+
2287
+ =begin
2288
+ === Class Methods
2289
+
2290
+ --- CharacterData.new(text)
2291
+
2292
+ creates a new CharacterData.
2293
+ =end
2294
+ ## new(text)
2295
+ ## text: String
2296
+ def initialize(text = nil)
2297
+ super()
2298
+ raise "parameter error" if !text
2299
+ @value = text
2300
+ end
2301
+
2302
+ =begin
2303
+ === Methods
2304
+
2305
+ --- CharacterData#data()
2306
+
2307
+ [DOM]
2308
+ returns the character data of the node.
2309
+ =end
2310
+ ## [DOM]
2311
+ def data
2312
+ @value.dup
2313
+ end
2314
+
2315
+ =begin
2316
+ --- CharacterData#data=(p)
2317
+
2318
+ [DOM]
2319
+ set the character data of the node.
2320
+ =end
2321
+ ## [DOM]
2322
+ def data=(p)
2323
+ @value = p
2324
+ end
2325
+
2326
+ =begin
2327
+ --- CharacterData#length()
2328
+
2329
+ [DOM]
2330
+ returns length of this CharacterData.
2331
+ =end
2332
+ ## [DOM]
2333
+ def length
2334
+ @value.length
2335
+ end
2336
+
2337
+ =begin
2338
+ --- CharacterData#substringData(start, count)
2339
+
2340
+ [DOM]
2341
+ extracts a range of data from the node.
2342
+ =end
2343
+ ## [DOM]
2344
+ def substringData(start, count)
2345
+ if start < 0 || start > @value.length || count < 0
2346
+ raise DOMException.new(DOMException::INDEX_SIZE_ERR)
2347
+ end
2348
+ ## if the sum of start and count > length,
2349
+ ## return all characters to the end of the value.
2350
+ @value[start, count]
2351
+ end
2352
+
2353
+ =begin
2354
+ --- CharacterData#appendData(str)
2355
+
2356
+ [DOM]
2357
+ append the string to the end of the character data.
2358
+ =end
2359
+ ## [DOM]
2360
+ def appendData(str)
2361
+ @value << str
2362
+ end
2363
+
2364
+ =begin
2365
+ --- CharacterData#insertData(offset, str)
2366
+
2367
+ [DOM]
2368
+ insert a string at the specified character offset.
2369
+ =end
2370
+ ## [DOM]
2371
+ def insertData(offset, str)
2372
+ if offset < 0 || offset > @value.length
2373
+ raise DOMException.new(DOMException::INDEX_SIZE_ERR)
2374
+ end
2375
+ @value[offset, 0] = str
2376
+ end
2377
+
2378
+ =begin
2379
+ --- CharacterData#deleteData(offset, count)
2380
+
2381
+ [DOM]
2382
+ removes a range of characters from the node.
2383
+ =end
2384
+ ## [DOM]
2385
+ def deleteData(offset, count)
2386
+ if offset < 0 || offset > @value.length || count < 0
2387
+ raise DOMException.new(DOMException::INDEX_SIZE_ERR)
2388
+ end
2389
+ @value[offset, count] = ''
2390
+ end
2391
+
2392
+ =begin
2393
+ --- CharacterData#replaceData(offset, count, str)
2394
+
2395
+ [DOM]
2396
+ replaces the characters starting at the specified character offset
2397
+ with specified string.
2398
+ =end
2399
+ ## [DOM]
2400
+ def replaceData(offset, count, str)
2401
+ if offset < 0 || offset > @value.length || count < 0
2402
+ raise DOMException.new(DOMException::INDEX_SIZE_ERR)
2403
+ end
2404
+ @value[offset, count] = str
2405
+ end
2406
+
2407
+ =begin
2408
+ --- CharacterData#cloneData(deep = true)
2409
+
2410
+ [DOM]
2411
+ returns the copy of the CharacterData.
2412
+ =end
2413
+ ## [DOM]
2414
+ def cloneNode(deep = true)
2415
+ super(deep, @value.dup)
2416
+ end
2417
+
2418
+ =begin
2419
+ --- Text#nodeValue
2420
+
2421
+ [DOM]
2422
+ return nodevalue.
2423
+
2424
+ =end
2425
+ ## [DOM]
2426
+ def nodeValue
2427
+ @value
2428
+ end
2429
+
2430
+ =begin
2431
+ --- CharacterData#nodeValue=(p)
2432
+
2433
+ [DOM]
2434
+ set nodevalue as p.
2435
+ =end
2436
+ ## [DOM]
2437
+ def nodeValue=(p)
2438
+ @value = p
2439
+ end
2440
+
2441
+ end
2442
+
2443
+ =begin
2444
+ == Class XML::DOM::Text
2445
+
2446
+ === superclass
2447
+ Node
2448
+
2449
+ =end
2450
+ class Text<CharacterData
2451
+
2452
+ =begin
2453
+ === Class Methods
2454
+
2455
+ --- Text.new(text)
2456
+
2457
+ creates a new Text.
2458
+ =end
2459
+ ## new(text)
2460
+ ## text: String
2461
+ def initialize(text = nil)
2462
+ super(text)
2463
+ end
2464
+
2465
+ =begin
2466
+ === Methods
2467
+
2468
+ --- Text#nodeType
2469
+
2470
+ [DOM]
2471
+ returns the nodeType.
2472
+ =end
2473
+ ## [DOM]
2474
+ def nodeType
2475
+ TEXT_NODE
2476
+ end
2477
+
2478
+ =begin
2479
+ --- Text#nodeName
2480
+
2481
+ [DOM]
2482
+ returns the nodeName.
2483
+ =end
2484
+ ## [DOM]
2485
+ def nodeName
2486
+ "#text"
2487
+ end
2488
+
2489
+ =begin
2490
+ --- Text#to_s
2491
+
2492
+ return the string representation of the Text.
2493
+ =end
2494
+ def to_s
2495
+ ret = ""
2496
+ @value.each_byte do |code|
2497
+ case (code)
2498
+ when 13
2499
+ ret << sprintf("&#x%X;", code)
2500
+ when ?&
2501
+ ret << "&amp;"
2502
+ when ?<
2503
+ ret << "&lt;"
2504
+ when ?>
2505
+ ret << "&gt;"
2506
+ else
2507
+ ret << code
2508
+ end
2509
+ end
2510
+ ret
2511
+ end
2512
+
2513
+ =begin
2514
+ --- Text#dump(depth = 0)
2515
+
2516
+ dumps the Text.
2517
+ =end
2518
+ def dump(depth = 0)
2519
+ print ' ' * depth * 2
2520
+ print "#{@value.inspect}\n"
2521
+ end
2522
+
2523
+ def _getMyLocation(parent)
2524
+ index = 1
2525
+ parent.childNodes do |child|
2526
+ if child == self
2527
+ return "child(#{index},#text)"
2528
+ end
2529
+ if child.nodeType == TEXT_NODE
2530
+ index += 1
2531
+ end
2532
+ end
2533
+ nil
2534
+ end
2535
+
2536
+ =begin
2537
+ --- Text#splitText(offset)
2538
+
2539
+ [DOM]
2540
+ breaks this Text node into two Text nodes at the specified offset.
2541
+ =end
2542
+ ## [DOM]
2543
+ def splitText(offset)
2544
+ if offset > @value.length || offset < 0
2545
+ raise DOMException.new(DOMException::INDEX_SIZE_ERR)
2546
+ end
2547
+ newText = @value[offset, @value.length]
2548
+ newNode = Text.new(newText)
2549
+ if !self.parentNode.nil?
2550
+ self.parentNode.insertAfter(newNode, self)
2551
+ end
2552
+ @value[offset, @value.length] = ""
2553
+ newNode
2554
+ end
2555
+
2556
+ =begin
2557
+ --- Text#trim(preserve = false)
2558
+
2559
+ trim extra whitespaces.
2560
+ =end
2561
+ def trim(preserve = false)
2562
+ if !preserve
2563
+ @value.sub!(/\A\s*([\s\S]*?)\s*\Z/, "\\1")
2564
+ return @value
2565
+ end
2566
+ nil
2567
+ end
2568
+
2569
+ end
2570
+
2571
+ =begin
2572
+ == Class XML::DOM::Comment
2573
+
2574
+ === superclass
2575
+ CharacterData
2576
+
2577
+ =end
2578
+ class Comment<CharacterData
2579
+
2580
+ =begin
2581
+ === Class Methods
2582
+
2583
+ --- Comment.new(text)
2584
+
2585
+ creates a new Comment.
2586
+ =end
2587
+ ## new(text)
2588
+ ## text: String
2589
+ def initialize(text = nil)
2590
+ super(text)
2591
+ raise "parameter error" if !text
2592
+ end
2593
+
2594
+ =begin
2595
+ === Methods
2596
+
2597
+ --- Comment#nodeType
2598
+
2599
+ [DOM]
2600
+ returns the nodeType.
2601
+ =end
2602
+ ## [DOM]
2603
+ def nodeType
2604
+ COMMENT_NODE
2605
+ end
2606
+
2607
+ =begin
2608
+ --- Comment#nodeName
2609
+
2610
+ [DOM]
2611
+ returns the nodeName.
2612
+ =end
2613
+ ## [DOM]
2614
+ def nodeName
2615
+ "#comment"
2616
+ end
2617
+
2618
+ =begin
2619
+ --- Comment#to_s
2620
+
2621
+ returns the string representation of the Comment.
2622
+ =end
2623
+ def to_s
2624
+ ret = "<!--#{@value}-->"
2625
+ ret << "\n" if parentNode.nodeType == DOCUMENT_NODE
2626
+ ret
2627
+ end
2628
+
2629
+ =begin
2630
+ --- Comment#dump(depth =0)
2631
+
2632
+ dumps the Comment.
2633
+ =end
2634
+ def dump(depth = 0)
2635
+ print ' ' * depth * 2
2636
+ print "<!--#{@value.inspect}-->\n"
2637
+ end
2638
+
2639
+ def _getMyLocation(parent)
2640
+ index = 1
2641
+ parent.childNodes do |child|
2642
+ if child == self
2643
+ return "child(#{index},#comment)"
2644
+ end
2645
+ if child.nodeType == COMMENT_NODE
2646
+ index += 1
2647
+ end
2648
+ end
2649
+ nil
2650
+ end
2651
+ end
2652
+
2653
+
2654
+ ## Extended Interfaces
2655
+
2656
+ =begin
2657
+ == Class XML::DOM::CDATASection
2658
+
2659
+ === superclass
2660
+ Text
2661
+
2662
+ =end
2663
+ class CDATASection<Text
2664
+ =begin
2665
+ === Class Methods
2666
+
2667
+ --- CDATASection.new(text = nil)
2668
+
2669
+ creates a new CDATASection.
2670
+ =end
2671
+ def initialize(text = nil)
2672
+ super(text)
2673
+ raise "parameter error" if !text
2674
+ end
2675
+
2676
+ =begin
2677
+ === Methods
2678
+
2679
+ --- CDATASection#nodeType
2680
+
2681
+ [DOM]
2682
+ returns the nodeType.
2683
+ =end
2684
+ ## [DOM]
2685
+ def nodeType
2686
+ CDATA_SECTION_NODE
2687
+ end
2688
+
2689
+ =begin
2690
+ --- CDATASection#nodeName
2691
+
2692
+ [DOM]
2693
+ returns the nodeName.
2694
+ =end
2695
+ ## [DOM]
2696
+ def nodeName
2697
+ "#cdata-section"
2698
+ end
2699
+
2700
+ =begin
2701
+ --- CDATASection#to_s
2702
+
2703
+ returns the string representation of the CDATASection.
2704
+ =end
2705
+ def to_s
2706
+ "<![CDATA[#{@value}]]>"
2707
+ end
2708
+
2709
+ =begin
2710
+ --- CDATASection#dump(depth = 0)
2711
+
2712
+ dumps the CDATASection.
2713
+ =end
2714
+ def dump(depth = 0)
2715
+ print ' ' * depth * 2
2716
+ print "<![CDATA[#{@value.inspect}]]>\n"
2717
+ end
2718
+
2719
+ def _getMyLocation(parent)
2720
+ index = 1
2721
+ parent.childNodes do |child|
2722
+ if child == self
2723
+ return "child(#{index},#cdata)"
2724
+ end
2725
+ if child.nodeType == CDATA_SECTION_NODE
2726
+ index += 1
2727
+ end
2728
+ end
2729
+ nil
2730
+ end
2731
+ end
2732
+
2733
+ =begin
2734
+ == Class XML::DOM::DocumentType
2735
+
2736
+ === superclass
2737
+ Node
2738
+ =end
2739
+ class DocumentType<Node
2740
+
2741
+ =begin
2742
+ === Class Methods
2743
+
2744
+ --- DocumentType.new(name, value = nil, *children)
2745
+
2746
+ creates a new DocuemntType.
2747
+ =end
2748
+ def initialize(name, value = nil, *children)
2749
+ super(*children)
2750
+ raise "parameter error" if !name
2751
+ @name = name.freeze
2752
+ @value = value.freeze
2753
+ end
2754
+
2755
+ =begin
2756
+ === Methods
2757
+
2758
+ --- DocumentType#nodeType
2759
+
2760
+ [DOM]
2761
+ returns the nodeType.
2762
+ =end
2763
+ ## [DOM]
2764
+ def nodeType
2765
+ DOCUMENT_TYPE_NODE
2766
+ end
2767
+
2768
+ =begin
2769
+ --- DocumentType#nodeName
2770
+
2771
+ [DOM]
2772
+ returns the nodeName.
2773
+ =end
2774
+ ## [DOM]
2775
+ def nodeName
2776
+ @name
2777
+ end
2778
+
2779
+ =begin
2780
+ --- DocumentType#to_s
2781
+
2782
+ returns the string representation of the DocumentType.
2783
+ =end
2784
+ def to_s
2785
+ ret = "<!DOCTYPE " + @name
2786
+ if !@value.nil?
2787
+ ret <<= " " + @value
2788
+ end
2789
+ if !@children.nil? && @children.length > 0
2790
+ ret <<= " [\n"
2791
+ @children.each do |child|
2792
+ if child.nodeType == PROCESSING_INSTRUCTION_NODE ||
2793
+ child.nodeType == COMMENT_NODE
2794
+ ret <<= child.to_s + "\n"
2795
+ else
2796
+ ret <<= child.nodeValue + "\n"
2797
+ end
2798
+ end
2799
+ ret <<= "]"
2800
+ end
2801
+ ret <<= ">"
2802
+ end
2803
+
2804
+ =begin
2805
+ --- DocumentType#dump(depth = 0)
2806
+
2807
+ dumps the DocumentType.
2808
+ =end
2809
+ def dump(depth = 0)
2810
+ print ' ' * depth * 2
2811
+ print "<!DOCTYPE #{@name} #{@value} [\n"
2812
+ @children.each do |child|
2813
+ print ' ' * (depth + 1) * 2
2814
+ if child.nodeType == PROCESSING_INSTRUCTION_NODE ||
2815
+ child.nodeType == COMMENT_NODE
2816
+ child.dump
2817
+ else
2818
+ print child.nodeValue, "\n"
2819
+ end
2820
+ end if @children
2821
+ print ' ' * depth * 2
2822
+ print "]>\n"
2823
+ end
2824
+
2825
+ =begin
2826
+ --- DocumentType#cloneNode(deep = true)
2827
+
2828
+ [DOM]
2829
+ returns the copy of the DocumentType.
2830
+ =end
2831
+ ## [DOM]
2832
+ def cloneNode(deep = true)
2833
+ super(deep, @name, @value)
2834
+ end
2835
+
2836
+ ## [DOM]
2837
+ ## def entities; @entities; end
2838
+ ## def notations; @notations; end
2839
+ end
2840
+
2841
+ =begin
2842
+ == Class XML::DOM::Notation
2843
+
2844
+ === superclass
2845
+ Node
2846
+ =end
2847
+ class Notation<Node
2848
+ =begin
2849
+ === Class Methods
2850
+
2851
+ --- Notation.new(name, pubid, sysid)
2852
+
2853
+ creates a new Notation.
2854
+ =end
2855
+ def initialize(name, pubid, sysid)
2856
+ super()
2857
+ @name = name.freeze
2858
+ @pubid = pubid.freeze
2859
+ @sysid = sysid.freeze
2860
+ end
2861
+
2862
+ =begin
2863
+ === Methods
2864
+
2865
+ --- Notation#nodeType
2866
+
2867
+ [DOM]
2868
+ returns the nodeType.
2869
+ =end
2870
+ ## [DOM]
2871
+ def nodeType
2872
+ NOTATION_NODE
2873
+ end
2874
+
2875
+ =begin
2876
+ --- Notation#nodeName
2877
+
2878
+ [DOM]
2879
+ returns the nodeName.
2880
+ =end
2881
+ ## [DOM]
2882
+ def nodeName
2883
+ @name
2884
+ end
2885
+
2886
+ =begin
2887
+ --- Notation#publicId
2888
+
2889
+ returns the publicId of the Notation.
2890
+ =end
2891
+ def publicId
2892
+ @pubid
2893
+ end
2894
+
2895
+ =begin
2896
+ --- Notation#systemId
2897
+
2898
+ returns the systemId of the Notation.
2899
+ =end
2900
+ def systemId
2901
+ @sysid
2902
+ end
2903
+
2904
+ =begin
2905
+ --- Notation#cloneNode(deep = true)
2906
+
2907
+ [DOM]
2908
+ returns the copy of the Notation.
2909
+ =end
2910
+ ## [DOM]
2911
+ def cloneNode(deep = true)
2912
+ super(deep, @name, @pubid, @sysid)
2913
+ end
2914
+ end
2915
+
2916
+ =begin
2917
+ == Class XML::DOM::Entity
2918
+
2919
+ === superclass
2920
+ Node
2921
+ =end
2922
+ class Entity<Node
2923
+
2924
+ =begin
2925
+ === Class Methods
2926
+
2927
+ --- Entity.new(name, pubid, sysid, notation)
2928
+
2929
+ creates a new Entity.
2930
+ =end
2931
+ def initialize(name, pubid, sysid, notation)
2932
+ super()
2933
+ @name = name.freeze
2934
+ @pubid = pubid.freeze
2935
+ @sysid = sysid.freeze
2936
+ @notation = notation.freeze
2937
+ end
2938
+
2939
+ =begin
2940
+ === Methods
2941
+
2942
+ --- Entity#nodeType
2943
+
2944
+ [DOM]
2945
+ returns the nodeType.
2946
+ =end
2947
+ ## [DOM]
2948
+ def nodeType
2949
+ ENTITY_NODE
2950
+ end
2951
+
2952
+ =begin
2953
+ --- Entity#nodeName
2954
+
2955
+ [DOM]
2956
+ returns the nodeName.
2957
+ =end
2958
+ ## [DOM]
2959
+ def nodeName
2960
+ @name
2961
+ end
2962
+
2963
+ =begin
2964
+ --- Entity#publicId
2965
+
2966
+ returns the publicId of the Entity.
2967
+ =end
2968
+ def publicId
2969
+ @pubid
2970
+ end
2971
+
2972
+ =begin
2973
+ --- Entity#systemId
2974
+
2975
+ returns the systemId of the Entity.
2976
+ =end
2977
+ def systemId
2978
+ @sysid
2979
+ end
2980
+
2981
+ =begin
2982
+ --- Entity#notationName
2983
+
2984
+ returns the notationname of the Entity.
2985
+ =end
2986
+ def notationName
2987
+ @notation
2988
+ end
2989
+
2990
+ =begin
2991
+ --- Entity#cloneNode(deep = true)
2992
+
2993
+ [DOM]
2994
+ returns the copy of the Entity.
2995
+ =end
2996
+ ## [DOM]
2997
+ def cloneNode(deep = true)
2998
+ super(deep, @name, @pubid, @sysid, @notation)
2999
+ end
3000
+
3001
+ def _checkNode(node)
3002
+ unless node.nodeType == ELEMENT_NODE ||
3003
+ node.nodeType == PROCESSING_INSTRUCTION_NODE ||
3004
+ node.nodeType == COMMENT_NODE ||
3005
+ node.nodeType == TEXT_NODE ||
3006
+ node.nodeType == CDATA_SECTION_NODE ||
3007
+ node.nodeType == ENTITY_REFERENCE_NODE
3008
+ raise DOMException.new(DOMException::HIERARCHY_REQUEST_ERR)
3009
+ end
3010
+ end
3011
+
3012
+ end
3013
+
3014
+ =begin
3015
+ == Class XML::DOM::EntityReference
3016
+
3017
+ === superclass
3018
+ Node
3019
+ =end
3020
+ class EntityReference<Node
3021
+
3022
+ =begin
3023
+ === Class Methods
3024
+
3025
+ --- EntityReference.new(name, *children)
3026
+
3027
+ creates a new EntityReference.
3028
+ =end
3029
+ def initialize(name, *children)
3030
+ super(*children)
3031
+ raise "parameter error" if !name
3032
+ @name = name.freeze
3033
+ end
3034
+
3035
+ =begin
3036
+ === Methods
3037
+
3038
+ --- EntityReference#nodeType
3039
+
3040
+ [DOM]
3041
+ returns the nodeType.
3042
+ =end
3043
+ ## [DOM]
3044
+ def nodeType
3045
+ ENTITY_REFERENCE_NODE
3046
+ end
3047
+
3048
+ =begin
3049
+ --- EntityReference#nodeName
3050
+
3051
+ [DOM]
3052
+ returns the nodeName.
3053
+ =end
3054
+ ## [DOM]
3055
+ def nodeName
3056
+ @name
3057
+ end
3058
+
3059
+ =begin
3060
+ --- EntityReference#to_s
3061
+
3062
+ returns the string representation of the EntityReference.
3063
+ =end
3064
+ ## reference form or expanded form?
3065
+ def to_s
3066
+ "&#{@name};"
3067
+ end
3068
+
3069
+ =begin
3070
+ --- EntityReference#dump(depth = 0)
3071
+
3072
+ dumps the EntityReference.
3073
+ =end
3074
+ def dump(depth = 0)
3075
+ print ' ' * depth * 2
3076
+ print "&#{@name}{\n"
3077
+ @children.each do |child|
3078
+ child.dump(depth + 1)
3079
+ end if @children
3080
+ print ' ' * depth * 2
3081
+ print "}\n"
3082
+ end
3083
+
3084
+ =begin
3085
+ --- EntityReference#cloneNode(deep = true)
3086
+
3087
+ [DOM]
3088
+ returns the copy of the EntityReference.
3089
+ =end
3090
+ ## [DOM]
3091
+ def cloneNode(deep = true)
3092
+ super(deep, @name)
3093
+ end
3094
+
3095
+ def _checkNode(node)
3096
+ unless node.nodeType == ELEMENT_NODE ||
3097
+ node.nodeType == PROCESSING_INSTRUCTION_NODE ||
3098
+ node.nodeType == COMMENT_NODE ||
3099
+ node.nodeType == TEXT_NODE ||
3100
+ node.nodeType == CDATA_SECTION_NODE ||
3101
+ node.nodeType == ENTITY_REFERENCE_NODE
3102
+ raise DOMException.new(DOMException::HIERARCHY_REQUEST_ERR)
3103
+ end
3104
+ end
3105
+
3106
+ end
3107
+
3108
+ =begin
3109
+ == Class XML::DOM::ProcessingInstruction
3110
+
3111
+ === superclass
3112
+ Node
3113
+
3114
+ =end
3115
+ class ProcessingInstruction<Node
3116
+
3117
+ =begin
3118
+ === Class Methods
3119
+
3120
+ --- ProcessingInstruction.new(target = nil, data = nil)
3121
+
3122
+ creates a new ProcessingInstruction.
3123
+ =end
3124
+ ## new(target, data)
3125
+ ## target: String
3126
+ ## data: String
3127
+ def initialize(target = nil, data = nil)
3128
+ super()
3129
+ raise "parameter error" if !data
3130
+ @target = target.freeze
3131
+ @data = data.freeze
3132
+ @value = target.dup
3133
+ @value << " #{data}" if data != ""
3134
+ @value.freeze
3135
+ end
3136
+
3137
+ =begin
3138
+ === Methods
3139
+
3140
+ --- ProcessingInstruction#nodeType
3141
+
3142
+ [DOM]
3143
+ returns the nodeType.
3144
+ =end
3145
+ ## [DOM]
3146
+ def nodeType
3147
+ PROCESSING_INSTRUCTION_NODE
3148
+ end
3149
+
3150
+ =begin
3151
+ --- ProcessingInstruction#nodeName
3152
+
3153
+ [DOM]
3154
+ returns the nodeName.
3155
+ =end
3156
+ ## [DOM]
3157
+ def nodeName
3158
+ "#proccessing-instruction"
3159
+ end
3160
+
3161
+ =begin
3162
+ --- ProcessingInstruction#target
3163
+
3164
+ [DOM]
3165
+ returns the target of the ProcessingInstruction.
3166
+ =end
3167
+ ## [DOM]
3168
+ def target
3169
+ @target
3170
+ end
3171
+
3172
+ =begin
3173
+ --- ProcessingInstruction#target=(p)
3174
+
3175
+ [DOM]
3176
+ set p to the target of the ProcessingInstruction.
3177
+ =end
3178
+ ## [DOM]
3179
+ def target=(p)
3180
+ @target = p.freeze
3181
+ @value = @target.dup
3182
+ @value << " #{@data}" if @data != ""
3183
+ @value.freeze
3184
+ end
3185
+
3186
+ =begin
3187
+ --- ProcessingInstruction#data
3188
+
3189
+ [DOM]
3190
+ return the content of the ProcessingInstruction.
3191
+ =end
3192
+ ## [DOM]
3193
+ def data
3194
+ @data
3195
+ end
3196
+
3197
+ =begin
3198
+ --- ProcessingInstruction#data=(p)
3199
+
3200
+ [DOM]
3201
+ sets p to the content of the ProcessingInstruction.
3202
+ =end
3203
+ ## [DOM]
3204
+ def data=(p)
3205
+ @data = p.freeze
3206
+ @value = @target.dup
3207
+ @value << " #{@data}" if @data != ""
3208
+ @value.freeze
3209
+ end
3210
+
3211
+ =begin
3212
+ --- ProcessingInstruction#nodeValue
3213
+
3214
+ [DOM]
3215
+ return nodevalue.
3216
+
3217
+ =end
3218
+ ## [DOM]
3219
+ def nodeValue
3220
+ @value
3221
+ end
3222
+
3223
+ ## inhibit changing value without target= or data=
3224
+ undef nodeValue=
3225
+
3226
+ =begin
3227
+ --- ProcessingInstruction#to_s
3228
+
3229
+ returns the string representation of the ProcessingInstruction.
3230
+ =end
3231
+ def to_s
3232
+ ret = "<?#{@value}?>"
3233
+ ret << "\n" if parentNode.nodeType == DOCUMENT_NODE
3234
+ ret
3235
+ end
3236
+
3237
+ =begin
3238
+ --- ProcessingInstruction#dump(depth = 0)
3239
+
3240
+ dumps the ProcessingInstruction.
3241
+ =end
3242
+ def dump(depth = 0)
3243
+ print ' ' * depth * 2
3244
+ print "<?#{@value.inspect}?>\n"
3245
+ end
3246
+
3247
+ def _getMyLocation(parent)
3248
+ index = 1
3249
+ parent.childNodes do |child|
3250
+ if child == self
3251
+ return "child(#{index},#pi)"
3252
+ end
3253
+ if child.nodeType == PROCESSING_INSTRUCTION_NODE
3254
+ index += 1
3255
+ end
3256
+ end
3257
+ nil
3258
+ end
3259
+
3260
+ =begin
3261
+ --- ProcessingInstruction#cloneNode(deep = true)
3262
+
3263
+ [DOM]
3264
+ returns the copy of the ProcessingInstruction.
3265
+ =end
3266
+ ## [DOM]
3267
+ def cloneNode(deep = true)
3268
+ super(deep, @target.dup, @data.dup)
3269
+ end
3270
+ end
3271
+
3272
+ end
3273
+
3274
+ SimpleTree = DOM
3275
+
3276
+ end