## -*- Ruby -*- ## XML::SimpleTree ## 1998-2000 by yoshidam ## ## XPointer support is contributed by Masaki Fukushima ## ## require 'singleton' =begin = XML::DOM (XML::SimpleTree) =end =begin == Module XML =end module XML =begin === Class Methods --- XML.charRef(s) replace character '&','<','>',"'",'"' in string s to character reference. =end def XML.charRef(s) str = s.dup str.gsub!("&", "&") str.gsub!("<", "<") str.gsub!(">", ">") str.gsub!("'", "'") str.gsub!('"', """) str end =begin == Module XML::Spec Constants related to XML Specification. =end ## [Masaki Fukushima] module Spec ## Constants related to XML Specification ## (W3C Recommendation or Working Draft) # XML Letter_s = '[a-zA-Z]' Digit_s = '\d' NameChar_s = "(#{Letter_s}|#{Digit_s}|[\\.\\-_:])" Name_s = "(#{Letter_s}|[_:])#{NameChar_s}*" SkipLit_s = "(\"[^\"]*\"|'[^']*')" Name = /^#{Name_s}$/o SkipList = /^#{SkipLit_s}$/o # XPointer Instance_s = "(\\+|-)?[1-9]#{Digit_s}*" Instance = /^#{Instance_s}$/o end =begin == Module XML::DOM (XML::SimpleTree) DOM-like APIs module. =end module DOM ## Fundamental Interfaces =begin == Class XML::DOM::DOMException === superclass Exception DOM exception. =end class DOMException 0 end =begin === Methods --- Node#parentNode [DOM] return parent node. =end ## [DOM] def parentNode @parent end =begin --- Node#parentNode=(p) set node p as parent. =end def parentNode=(p) @parent = p end =begin --- Node#nodeType [DOM] return nodetype. =end ## [DOM] def nodeType NODE_NODE end =begin --- Node#nodeName [DOM] return nodename. =end ## [DOM] def nodeName "#node" end # def nodeName=(p) # @name = p # end =begin --- Node#nodeValue [DOM] return nodevalue. =end ## [DOM] def nodeValue; nil; end =begin --- Node#nodeValue=(p) [DOM] set nodevalue as p. =end ## [DOM] def nodeValue=(p) ## no effect end =begin --- Node#childNodes() [DOM] if method has block, apply block for children nodes. without block, return children nodelist. =end ## [DOM] def childNodes if iterator? @children.each do |child| yield(child) end if @children else return @children if !@children.nil? @children = NodeList.new end end =begin --- Node#childNodes=(p) set child node as p. =end def childNodes=(p) if @children.nil? @children = NodeList.new else @children.to_a.clear end if p.nil? || (p.is_a?(Array) && p.length == 0) return end p.flatten! p.each do |child| if child.is_a?(String) c = Text.new(child) @children.push(c) c.parentNode = self elsif child.is_a?(Node) @children.push(child) child.parentNode = self else raise "parameter error" end end if p end =begin --- Node#attributes [DOM] return attributes of node(but always return nil?). =end ## [DOM] def attributes nil end ## proper parameter type? # def attributes=(p) # end =begin --- Node#[]=(index, nodes) set children node as nodes with []-style. =end def []=(index, nodes) @children[index..index] = nodes @children.each do |child| child.parentNode = self end if @children end =begin --- Node#[](index) get children node with []-style. =end def [](index) @children[index] end =begin --- Node#+(node) concat node to Node. =end def +(node) [self, node] end =begin --- Node#to_s returns the string representation of the Node. =end def to_s @children.to_s end =begin --- Node#dump(depth = 0) dump the Node. =end def dump(depth = 0) print ' ' * depth * 2 print nodeName + "\n" @children.each do |child| child.dump(depth + 1) end if @children end =begin --- Node#inspect() returns the human-readable string representation. =end def inspect "#<#{self.class}: #{self.nodeName}>" end =begin --- Node#firstChild() [DOM] return the first child node. =end ## [DOM] def firstChild return nil if !@children || @children.length == 0 return @children[0] end =begin --- Node#lastChild() [DOM] return the last child node. =end ## [DOM] def lastChild return nil if !@children || @children.length == 0 return @children[-1] end =begin --- Node#previousSibling() [DOM] return the previous sibling node. =end ## [DOM] def previousSibling return nil if !@parent prev = nil @parent.childNodes do |child| return prev if child == self prev = child end nil end =begin --- Node#nextSibling() [DOM] return the next sibling node. =end ## [DOM] def nextSibling return nil if !@parent nexts = nil @parent.childNodes.reverse.each do |child| return nexts if child == self nexts = child end nil end def _getChildIndex(node) index = 0 @children.each do |child| if child == node return index end index += 1 end nil end def _removeFromTree parent = parentNode if parent parent.removeChild(self) end end def _checkNode(node) raise DOMException.new(DOMException::HIERARCHY_REQUEST_ERR) end def _insertNodes(index, node) if node.nodeType == DOCUMENT_FRAGMENT_NODE node.childNodes.to_a.each_with_index do |n, i| if index == -1 _insertNodes(-1, n) else _insertNodes(index + i, n) end end elsif node.is_a?(Node) ## to be checked _checkNode(node) node._removeFromTree if index == -1 @children.push(node) else @children[index, 0] = node end node.parentNode = self else raise ArgumentError, "invalid value for Node" end end def _removeNode(index, node) @children[index, 1] = nil node.parentNode = nil end # =begin # --- Node#insertAfter(newChild, refChild) # # insert newChild into the node after refChild. # =end # def insertAfter(newChild, refChild) # if @children.nil? || @children.length == 0 # raise DOMException.new(DOMException::NOT_FOUND_ERR) # end # index = _getChildIndex(refChild) # raise DOMException.new(DOMException::NOT_FOUND_ERR) if index.nil? # _insertNodes(index, newChild) # end =begin --- Node#insertBefore(newChild, refChild) [DOM] insert newChild into the node before refChild. =end ## [DOM] def insertBefore(newChild, refChild) if @children.nil? || @children.length == 0 raise DOMException.new(DOMException::NOT_FOUND_ERR) end index = _getChildIndex(refChild) raise DOMException.new(DOMException::NOT_FOUND_ERR) if !index _insertNodes(index, newChild) end =begin --- Node#replaceChild(newChild, oldChild) [DOM] replace the child node oldChild with newChild. =end ## [DOM] def replaceChild(newChild, oldChild) if @children.nil? || @children.length == 0 raise DOMException.new(DOMException::NOT_FOUND_ERR) end index = _getChildIndex(oldChild) raise DOMException.new(DOMException::NOT_FOUND_ERR) if !index _removeNode(index, oldChild) _insertNodes(index, newChild) end =begin --- Node#removeChild(oldChild) [DOM] remove the children node oldChild. =end ## [DOM] def removeChild(oldChild) if @children.nil? || @children.length == 0 raise DOMException.new(DOMException::NOT_FOUND_ERR) end index = _getChildIndex(oldChild) raise DOMException.new(DOMException::NOT_FOUND_ERR) if !index _removeNode(index, oldChild) oldChild end =begin --- Node#appendChild(newChild) [DOM] adds the node newChild to the end of the list of children of this node. =end ## [DOM] def appendChild(newChild) @children = NodeList.new if !@children _insertNodes(-1, newChild) end =begin --- Node#hasChildNodes() [DOM] returns true if node has children, or return false if node has no children. =end ## [DOM] def hasChildNodes !@children.nil? && @children.length > 0 end ## get the Node object by IDs ## [experimental implement] def _searchID(value, ids = nil) if ids.nil? doc = nil if nodeType == DOCUMENT_NODE doc = self elsif !ownerDocument.nil? doc = ownerDocument else return nil end ids = doc._getIDAttrs end if nodeType == ELEMENT_NODE && _getIDVals(ids).include?(value) return self elsif !@children.nil? @children.each do |node| if !(match = node._searchID(value, ids)).nil? return match end end end return nil end def _getMyLocation(parent) index = parent._getChildIndex(self) if !index.nil? "child(#{index + 1},#all)" else nil end end =begin --- Node#makeXPointer(use_id = true) return XPointer's expression of this node. =end def makeXPointer(use_id = true) if use_id && !attributes.nil? && !(idvals = _getIDVals).empty? "id(#{idvals[0]})" elsif @parent.nil? || @parent.nodeType == DOCUMENT_NODE "root()" else @parent.makeXPointer(use_id) + "." + self._getMyLocation(@parent) end end ## [Masaki Fukushima] def _child(reverse = false) return if @children.nil? @children.reversible_each(reverse) do |child| yield child end end ## [Masaki Fukushima] def _descendant(reverse = false) return if @children.nil? @children.reversible_each(reverse) do |child| yield child child._descendant(reverse) do |node| yield node end end end ## [Masaki Fukushima] def _ancestor(reverse = false) return if @parent.nil? yield @parent if !reverse @parent._ancestor(reverse) do |node| yield node end yield @parent if reverse end ## [Masaki Fukushima] def __sibling(reverse, only_appeared_before_self) return if @parent.nil? self_appeared = false @parent.childNodes.reversible_each(reverse) do |node| if node == self self_appeared = true next end if only_appeared_before_self break if self_appeared yield node else # only appeared after self yield node if self_appeared end end end ## [Masaki Fukushima] def _psibling(reverse = false) __sibling(!reverse, reverse) do |sib| yield sib end end ## [Masaki Fukushima] def _fsibling(reverse = false) __sibling(reverse, reverse) do |sib| yield sib end end ## [Masaki Fukushima] def _preceding(reverse = false) return if @parent.nil? prev_sib = previousSibling if prev_sib prev_sib._preceding(reverse) {|node| yield node} if reverse yield prev_sib prev_sib._descendant(!reverse) {|node| yield node} prev_sib._preceding(reverse) {|node| yield node} if !reverse else @parent._preceding(reverse) {|node| yield node} if reverse yield @parent @parent._preceding(reverse) {|node| yield node} if !reverse end end ## [Masaki Fukushima] def _following(reverse = false) return if @parent.nil? next_sib = nextSibling if next_sib next_sib._following(reverse) {|node| yield node} if reverse yield next_sib next_sib._descendant(reverse) {|node| yield node} next_sib._following(reverse) {|node| yield node} if !reverse else @parent._following(reverse) {|node| yield node} if reverse yield @parent @parent._following(reverse) {|node| yield node} if !reverse end end ## [Masaki Fukushima] def _matchAttribute?(attr, value) case value when '*' return !attr.nil? when '#IMPLIED' return attr.nil? else return false if attr.nil? end case value when /^"([^"]*)"$/, /^'([^']*)'$/ ignore_case = false value = $1 when Spec::Name ignore_case = true else raise "invalid attribute value: #{value}" end if ignore_case return attr.nodeValue.downcase == value.downcase else return attr.nodeValue == value end end ## [Masaki Fukushima] def _matchNodeAttributes?(node, attributes) return true if attributes.nil? raise TypeError if !attributes.is_a?(Hash) return true if attributes.length == 0 return false if node.nodeType != ELEMENT_NODE attributes.each do |name, value| case name when '*' return catch(:match) { node.attributes.each do |attr| throw(:match, true) if _matchAttribute?(attr, value) end false } when Spec::Name attr = node.attributes[name] unless node.attributes.nil? return _matchAttribute?(attr, value) else raise "invalid attribute name: '#{name}'" end end end ## [Masaki Fukushima] def _matchNodeType?(node, ntype) case ntype when '#element' return (node.nodeType == ELEMENT_NODE) when '#pi' return (node.nodeType == PROCESSING_INSTRUCTION_NODE) when '#comment' return (node.nodeType == COMMENT_NODE) when '#text' return (node.nodeType == TEXT_NODE || node.nodeType == CDATA_SECTION_NODE) when '#cdata' return (node.nodeType == CDATA_SECTION_NODE) when '#all' case node.nodeType when ELEMENT_NODE, PROCESSING_INSTRUCTION_NODE, COMMENT_NODE, TEXT_NODE, CDATA_SECTION_NODE return true else return false end when /^#/ raise "unknown node type: '#{ntype}'" when Spec::Name return (node.nodeType == ELEMENT_NODE && node.nodeName == ntype) else raise "invalid element type: '#{ntype}'" end end ## [Masaki Fukushima] def _matchNode?(node, ntype, attributes) _matchNodeType?(node, ntype) && _matchNodeAttributes?(node, attributes) end ## [Masaki Fukushima] def _nodesByRelativeLocationTerm(location) if location !~ /^([a-z]+)\(([^\)]*)\)$/ raise "invalid relative location: '#{location}'" end keyword = $1 args = $2.split(/,/) number = args.shift ntype = args.shift ntype = '#element' if ntype.nil? attributes = args reverse = false # check instance number case number when nil, '' raise "missing instance number: '#{location}'" when 'all' when Spec::Instance number = number.to_i if number < 0 reverse = true number = -number end else raise "unknown instance number: '#{number}'" end # check attributes if attributes.length % 2 != 0 raise " missing attribute value: '#{location}'" end attributes = Hash[*attributes] # iterate over nodes specified with keyword i = 0 self.send("_#{keyword}", reverse) do |node| next unless _matchNode?(node, ntype, attributes) if number == "all" yield node else i += 1 if i >= number yield node break end end end end ## [Masaki Fukushima] def _nodesByLocationTerms(location, pre_keyword = nil) if location !~ /^([a-z]*)\(([^)]*)\)(\.(.+))?$/ raise "invalid location: \"#{location}\"" end keyword = $1 args = $2 rest = $4 ## omitted keyword keyword = pre_keyword if keyword == '' if keyword.nil? raise "cannot determine preceding keyword: \"#{location}\"" end case keyword when 'child', 'descendant', 'ancestor', 'psibling', 'fsibling', 'preceding', 'following' # relative location term _nodesByRelativeLocationTerm("#{keyword}(#{args})") do |node| if rest.nil? yield node else node._nodesByLocationTerms(rest, keyword) do |n| yield n end end end when 'attr' # attribute location term if args !~ Spec::Name raise "invalid attribute name: '#{args}'" end attr = attributes[args] value = (attr.nil? ? nil : Text.new(attr.nodeValue)) if rest.nil? yield value elsif !value.nil? value._nodesByLocationTerms(rest) do |node| yield node end end when 'span', 'string' raise "unsupported keyword: '#{keyword}'" else raise "unknown keyword: '#{keyword}'" end end ## [Masaki Fukushima] def _getNodeByAbsoluteLocationTerm(location) case location when 'root()', '' if nodeType == DOCUMENT_NODE root = documentElement elsif !ownerDocument.nil? root = ownerDocument.documentElement end root = self if root.nil? return root when 'origin()' return self when /^id\(([^\)]*)\)$/ value = $1 raise "invalid id value: #{value}" if value !~ Spec::Name return _searchID(value) when /^html\(([^\)]*)\)$/ value = $1 return getNodesByXPointer("root().descendant(1,A,NAME,\"#{value}\")")[0] else raise "unknown keyword: #{location}" end end =begin --- Node#getNodeByXPointer(pointer) return node indicated by the XPointer pointer. =end ## [Masaki Fukushima] def getNodesByXPointer(pointer) if pointer !~ /^([a-z]+)\(([^)]*)\)(\.(.+))?$/ raise "invalid XPointer: \"#{pointer}\"" end keyword = $1 args = $2 rest = $4 case keyword when 'root', 'origin', 'id', 'html' src = _getNodeByAbsoluteLocationTerm("#{keyword}(#{args})") else src = _getNodeByAbsoluteLocationTerm("root()") rest = pointer end ret = NodeList.new if src.nil? # no match elsif rest.nil? yield src if iterator? ret << src else src._nodesByLocationTerms(rest) do |node| yield node if iterator? ret << node end end ret end =begin --- Node#ownerDocument() [DOM] Document object associated with this node. =end ## [DOM] ## Floating objects are not owned by any documents. def ownerDocument return @ownerDocument if @ownerDocument parent = self.parentNode return nil if parent.nil? if parent.nodeType == DOCUMENT_NODE return parent else return parent.ownerDocument end end def ownerDocument=(document); @ownerDocument = document; end =begin --- Node#cloneNode() [DOM] return the copy of the Node. =end ## [DOM] def cloneNode(deep = true, *args) ret = self.class.new(*args) if (deep) @children.each do |child| ret.appendChild(child.cloneNode(true)) end end if @children ret end =begin --- Node#trim(preserve = false) trim extra whitespaces. =end ## trim extra whitespaces ## if attribute 'xml:space' is 'preserve', ## don't trim any white spaces def trim(preserve = false) return nil if @children.nil? children = @children.to_a.dup children.each do |child| if !preserve && (child.nodeType == TEXT_NODE || child.nodeType == CDATA_SECTION_NODE) if child.trim == "" self.removeChild(child) end else child.trim(preserve) end end nil end end =begin == Class XML::DOM::NamedNodeMap =end class NamedNodeMap =begin === Class Methods --- NamedNodeMap.new(nodes = nil) creates a new NamedNodeMap. =end def initialize(nodes = nil) @nodes = {} nodes.each do |node| @nodes[node.nodeName] = node end if nodes end =begin === Methods --- NamedNodeMap#getNamedItem(name) [DOM] retrieves a node specified by name. =end ## [DOM] def getNamedItem(name) @nodes[name] end =begin --- NamedNodeMap#setNamedItem(node) [DOM] adds a node using its nodeName attribute. =end ## [DOM] def setNamedItem(node) @nodes[node.nodeName] = node end =begin --- NamedNodeMap#removeNamedItem(name) [DOM] removes a node specified by name. =end ## [DOM] def removeNamedItem(name) ret = @nodes[name] @nodes[name] = nil ret end =begin --- NamedNodeMap#item(index) [DOM] returns the index item in the map. =end ## [DOM] def item(index) v = @nodes.to_a[index] return v[1] if v nil end =begin --- NamedNodeMap#[](name) returns nodes associated to name. =end def [](name) @nodes[name] end =begin --- NamedNodeMap#[]=(name, node) sets node named name. =end def []=(name, node) raise "parameter error" if node.nodeName != name @nodes[name] = node end =begin --- NamedNodeMap#each() iterates over each pair of name and node(name, node) of the namedNodeMap. =end def each @nodes.each do |key, value| yield(value) end end =begin --- NamedNodeMap#size() [DOM] returns the number of nodes in the map. =end ## [DOM] def size @nodes.length end alias length size ## get nodeValues by names ## names ::= name ('|' name)* def _getValues(names) ret = [] names.split('|').each do |name| if !@nodes[name].nil? ret.push(@nodes[name].nodeValue) end end ret end end =begin == Class XML::DOM::NodeList =end class NodeList =begin === Class Methods --- NodeList.new(nodes = nil) creates a new NodeList. =end def initialize(nodes = nil) if nodes.nil? @nodes = [] elsif nodes.is_a?(Array) @nodes = nodes else raise "parameter error" end end =begin === Methods --- NodeList#item(index) [DOM] return the indexth item in the NodeList. =end ## [DOM] def item(index) @nodes[index] end =begin --- NodeList#size() return size of NodeList. =end def size @nodes.length end alias length size =begin --- NodeList#[](index) return indexth node of the NodeList. =end def [](index) @nodes[index] end =begin --- NodeList#[]=(*p) set node of indexth node of the NodeList. =end def []=(*p) if p.length == 2 @nodes[p[0]] = p[1] elsif p.length == 3 @nodes[p[0], p[1]] = p[2] end end =begin --- NodeList#each iterates over each node of the NodeList. =end def each @nodes.each do |value| yield(value) end end =begin --- NodeList#reversible_each(reverse = false) iterates over each node of the reversed NodeList. =end ## [Masaki Fukushima] def reversible_each(reverse = false) if !reverse @nodes.each do |value| yield(value) end else @nodes.reverse_each do |value| yield(value) end end end =begin --- NodeList#push(*nodes) adds nodes into the NodeList. =end def push(*nodes) nodes.each do |node| if node.is_a?(Array) self.push(*node) elsif node.is_a?(NodeList) @nodes.concat(node.to_a) elsif node.is_a?(Node) @nodes << node else raise "parameter error" end end self end =begin --- NodeList#concat(*nodes) alias of NodeList#push. =end alias concat push =begin --- NodeList#pop pops and returns the last node of the NodeList. =end def pop @nodes.pop end =begin --- NodeList#shift removes and returns the first node of the NodeList. =end def shift @nodes.shift end =begin --- NodeList#to_s returns the string representation of the NodeList. =end def to_s @nodes.to_s end =begin --- NodeList#reverse returns the reversed NodeList. =end def reverse @nodes.reverse end =begin --- NodeList#to_a converts the NodeList into an array. =end def to_a @nodes end =begin --- NodeList#+(nodes) return the newly created concatenated NodeList. =end def +(nodes) if nodes.nil? NodeList.new(@nodes) elsif nodes.is_a?(Array) NodeList.new(@nodes + nodes) elsif nodes.is_a?(NodeList) NodeList.new(@nodes + nodes.to_a) elsif nodes.is_a?(Node) NodeList.new(@nodes + [nodes]) else raise "parameter error" end end =begin --- NodeList#<<(nodes) appends nodes to the NodeList. =end ## modified by Masaki Fukushima def <<(nodes) if nodes.nil? ## no change elsif nodes.is_a?(Array) @nodes.concat(nodes) elsif nodes.is_a?(NodeList) @nodes.concat(nodes.to_a) elsif nodes.is_a?(Node) @nodes << nodes else raise "parameter error" end self end ## get nodeValues by names ## names ::= name ('|' name)* def _getValues(names) ret = [] names.split('|').each do |name| if !@nodes[name].nil? ret.push(@nodes[name].nodeValue) end end ret end end =begin == Class XML::DOM::DocumentFragment === superclass Node =end class DocumentFragment'id'} if @idattrs.nil? @idattrs end ## [DOM] def implementation return @implemantation if @implemantation ## singleton @implemantation = DOMImplementation.instance end def implementation=(impl) @implemantation = impl end def _checkNode(node) unless node.nodeType == ELEMENT_NODE || node.nodeType == PROCESSING_INSTRUCTION_NODE || node.nodeType == COMMENT_NODE || node.nodeType == DOCUMENT_TYPE_NODE raise DOMException.new(DOMException::HIERARCHY_REQUEST_ERR) end if node.nodeType == ELEMENT_NODE @children.each do |n| if n.nodeType == ELEMENT_NODE raise DOMException.new(DOMException::HIERARCHY_REQUEST_ERR) end end end if node.nodeType == DOCUMENT_TYPE_NODE @children.each do |n| if n.nodeType == DOCUMENT_TYPE_NODE raise DOMException.new(DOMException::HIERARCHY_REQUEST_ERR) end end end end end =begin == Class XML::DOM::Attr === superclass Node =end class Attr @value.length || count < 0 raise DOMException.new(DOMException::INDEX_SIZE_ERR) end ## if the sum of start and count > length, ## return all characters to the end of the value. @value[start, count] end =begin --- CharacterData#appendData(str) [DOM] append the string to the end of the character data. =end ## [DOM] def appendData(str) @value << str end =begin --- CharacterData#insertData(offset, str) [DOM] insert a string at the specified character offset. =end ## [DOM] def insertData(offset, str) if offset < 0 || offset > @value.length raise DOMException.new(DOMException::INDEX_SIZE_ERR) end @value[offset, 0] = str end =begin --- CharacterData#deleteData(offset, count) [DOM] removes a range of characters from the node. =end ## [DOM] def deleteData(offset, count) if offset < 0 || offset > @value.length || count < 0 raise DOMException.new(DOMException::INDEX_SIZE_ERR) end @value[offset, count] = '' end =begin --- CharacterData#replaceData(offset, count, str) [DOM] replaces the characters starting at the specified character offset with specified string. =end ## [DOM] def replaceData(offset, count, str) if offset < 0 || offset > @value.length || count < 0 raise DOMException.new(DOMException::INDEX_SIZE_ERR) end @value[offset, count] = str end =begin --- CharacterData#cloneData(deep = true) [DOM] returns the copy of the CharacterData. =end ## [DOM] def cloneNode(deep = true) super(deep, @value.dup) end =begin --- Text#nodeValue [DOM] return nodevalue. =end ## [DOM] def nodeValue @value end =begin --- CharacterData#nodeValue=(p) [DOM] set nodevalue as p. =end ## [DOM] def nodeValue=(p) @value = p end end =begin == Class XML::DOM::Text === superclass Node =end class Text ret << ">" else ret << code end end ret end =begin --- Text#dump(depth = 0) dumps the Text. =end def dump(depth = 0) print ' ' * depth * 2 print "#{@value.inspect}\n" end def _getMyLocation(parent) index = 1 parent.childNodes do |child| if child == self return "child(#{index},#text)" end if child.nodeType == TEXT_NODE index += 1 end end nil end =begin --- Text#splitText(offset) [DOM] breaks this Text node into two Text nodes at the specified offset. =end ## [DOM] def splitText(offset) if offset > @value.length || offset < 0 raise DOMException.new(DOMException::INDEX_SIZE_ERR) end newText = @value[offset, @value.length] newNode = Text.new(newText) if !self.parentNode.nil? self.parentNode.insertAfter(newNode, self) end @value[offset, @value.length] = "" newNode end =begin --- Text#trim(preserve = false) trim extra whitespaces. =end def trim(preserve = false) if !preserve @value.sub!(/\A\s*([\s\S]*?)\s*\Z/, "\\1") return @value end nil end end =begin == Class XML::DOM::Comment === superclass CharacterData =end class Comment\n" end def _getMyLocation(parent) index = 1 parent.childNodes do |child| if child == self return "child(#{index},#comment)" end if child.nodeType == COMMENT_NODE index += 1 end end nil end end ## Extended Interfaces =begin == Class XML::DOM::CDATASection === superclass Text =end class CDATASection" end =begin --- CDATASection#dump(depth = 0) dumps the CDATASection. =end def dump(depth = 0) print ' ' * depth * 2 print "\n" end def _getMyLocation(parent) index = 1 parent.childNodes do |child| if child == self return "child(#{index},#cdata)" end if child.nodeType == CDATA_SECTION_NODE index += 1 end end nil end end =begin == Class XML::DOM::DocumentType === superclass Node =end class DocumentType 0 ret <<= " [\n" @children.each do |child| if child.nodeType == PROCESSING_INSTRUCTION_NODE || child.nodeType == COMMENT_NODE ret <<= child.to_s + "\n" else ret <<= child.nodeValue + "\n" end end ret <<= "]" end ret <<= ">" end =begin --- DocumentType#dump(depth = 0) dumps the DocumentType. =end def dump(depth = 0) print ' ' * depth * 2 print "\n" end =begin --- DocumentType#cloneNode(deep = true) [DOM] returns the copy of the DocumentType. =end ## [DOM] def cloneNode(deep = true) super(deep, @name, @value) end ## [DOM] ## def entities; @entities; end ## def notations; @notations; end end =begin == Class XML::DOM::Notation === superclass Node =end class Notation\n" end def _getMyLocation(parent) index = 1 parent.childNodes do |child| if child == self return "child(#{index},#pi)" end if child.nodeType == PROCESSING_INSTRUCTION_NODE index += 1 end end nil end =begin --- ProcessingInstruction#cloneNode(deep = true) [DOM] returns the copy of the ProcessingInstruction. =end ## [DOM] def cloneNode(deep = true) super(deep, @target.dup, @data.dup) end end end SimpleTree = DOM end