xmlparser 0.6.81

Sign up to get free protection for your applications and to get access to all the features.
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