ooRexx logo
   1: /**
   2:   **********************************************************************
   3: 
   4:   Copyright (c) 2011-2015 Ruurd J. Idenburg. All rights reserved.                                             
   5: 
   6:   This program and the accompanying materials are made available under
   7:   the terms of the Common Public License v1.0 which accompanies this
   8:   distribution. A copy is also available at the following address:
   9:   
  10:   http://www.opensource.org/licenses/cpl1.0.php                         
  11: 
  12:   Redistribution and use in source and binary forms, with or without
  13:   modification, are permitted provided that the following conditions
  14:   are met:                                                              
  15: 
  16:   Redistributions of source code must retain the above copyright
  17:   notice, this list of conditions and the following disclaimer.         
  18: 
  19:   Redistributions in binary form must reproduce the above copyright
  20:   notice, this list of conditions and the following disclaimer in the
  21:   documentation and/or other materials provided with the distribution.  
  22:  
  23:   Neither the name or trademarks of Ruurd J. Idenburg nor the names
  24:   of any  contributors may be used to endorse or promote products
  25:   derived from this software without specific prior written permission. 
  26:  
  27:   DISCLAIMER                                                            
  28: 
  29:   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  30:   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  31:   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  32:   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  33:   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  34:   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  35:   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  36:   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  37:   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  38:   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  39:   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  40:   
  41:   ********************************************************************** 
  42: */
  43: /* CLASS: xmlUtil */
  44: /**
  45:   xmlDom basic types and other useful things
  46: */
  47: 
  48: /**
  49:   XML name valid characters. For (oo)Rexx, which only supports ASCII at the moment the valid range is alpha (lower and
  50:   upper) and digits, plus '.', '-', '_' and' :' (this last one for qualified names (i.e. namespace:tag)). 
  51:   @return valid - A string containing the valid characters for a XML name
  52: */
  53: ::routine xmlValidName public
  54: valid = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-_:'
  55: return valid
  56: /**
  57:   Generates a "under construction" message for things not yet operational.
  58:   @param name - The name of the thing the message is about
  59:   @return message - The message text
  60: */
  61: ::routine isUnderConstruction public
  62:   use strict arg name
  63:   message = name "is currently under construction!"
  64: return message 
  65: /**
  66:   xmlDomString is a subclass of String, for the time being without any modifications.
  67: */  
  68: ::class xmlDomString public subclass string
  69: /**
  70:   xmlDomTimeStamp represents a number of milliseconds
  71: */
  72: ::class xmlDomTimeStamp public subclass string
  73: /**
  74:   xmlDomUserData represents a reference to application data.
  75: */
  76: ::class xmlDomUserData public
  77: /**
  78:   xmlDomObject represents an object reference. 
  79: */
  80: ::class xmlDomObject public
  81: 
  82: /**
  83:   domExceptions and their codes.
  84: 
  85:   DOM operations only raise exceptions in "exceptional" circumstances, i.e., when an operation is impossible to perform
  86:   (either for logical reasons, because data is lost, or because the implementation has become unstable). In general, DOM
  87:   methods return specific error values in ordinary processing situations, such as out-of-bound errors when using 
  88:   NodeList.
  89: 
  90:   Implementations should raise other exceptions under other circumstances. For example, implementations should raise an 
  91:   implementation-dependent exception if a .nil argument is passed when null was not expected.
  92: 
  93:   Some languages and object systems do not support the concept of exceptions. For such systems, error conditions may be
  94:   indicated using native error reporting mechanisms. For some bindings, for example, methods may return error codes 
  95:   similar to those listed in the corresponding method descriptions. 
  96: 
  97: */
  98: ::class domException public
  99: /**
 100:   INDEX_SIZE_ERR - If index or size is negative, or greater than the allowed 
 101:   value.
 102: */
 103: ::method index_size_err class
 104: return 1
 105: /**
 106:   DOMSTRING_SIZE_ERR - If the specified range of text does not fit into a 
 107:   DOMString.
 108: */
 109: ::method domstring_size_err class
 110: return 2
 111: /**
 112:   HIERARCHY_REQUEST_ERR - If any Node is inserted somewhere it doesn't belong.
 113: */
 114: ::method hierarchy_request_err class
 115: return 3
 116: /**
 117:   WRONG_DOCUMENT_ERR - If a Node is used in a different document than the one 
 118:   that created it (that doesn't support it).
 119: */
 120: ::method wrong_document_err class
 121: return 4
 122: /**
 123:   INVALID_CHARACTER_ERR - If an invalid or illegal character is specified, such 
 124:   as in an XML name.
 125: */
 126: ::method invalid_character_err class
 127: return 5
 128: /**
 129:   NO_DATA_ALLOWED_ERR - If data is specified for a Node which does not support 
 130:   data
 131: */
 132: ::method no_data_allowed_err class
 133: return 6
 134: /**
 135:  NO_MODIFICATION_ALLOWED_ERR - If an attempt is made to modify an object where 
 136:  modifications are not allowed.
 137: */
 138: ::method no_modification_allowed_err class
 139: return 7
 140: /**
 141:   NOT_FOUND_ERR - If an attempt is made to reference a Node in a context where 
 142:   it does not exist.
 143: */
 144: ::method not_found_err class
 145: return 8
 146: /**
 147:   NOT_SUPPORTED_ERR - If the implementation does not support the requested type of object or operation.
 148: */
 149: ::method not_supported_err class
 150: return 9
 151: /**
 152:   INUSE_method_ERR - If an attempt is made to add an method that is already in use elsewhere.
 153: */
 154: ::method inuse_method_err class
 155: return 10
 156: /**
 157:   INVALID_STATE_ERR - If an attempt is made to use an object that is not, or is no longer, usable.
 158: */
 159: ::method invalid_state_err class
 160: return 11
 161: /**
 162:   SYNTAX_ERR - If an invalid or illegal string is specified.
 163: */
 164: ::method syntax_err class
 165: return 12
 166: /**
 167:   INVALID_MODIFICATION_ERR - If an attempt is made to modify the type of the underlying object.
 168: */
 169: ::method invalid_modification_err class
 170: return 13
 171: /**
 172:   NAMESPACE_ERR - If an attempt is made to create or change an object in a way which is incorrect with regard to
 173:   namespaces.
 174: */
 175: ::method namespace_err class
 176: return 14
 177: /**
 178:  INVALID_ACCESS_ERR - If a parameter or an operation is not supported by the underlying object.
 179: */
 180: ::method invalid_access_err class
 181: return 15
 182: /**
 183:   VALIDATION_ERR - If a call to a method such as insertBefore or removeChild would make the Node invalid with respect to
 184:   "partial validity", this exception would be raised and the operation would not be done. This code is used in [DOM 
 185:   Level 3 Validation]. Refer to this specification for further information.
 186: */
 187: ::method validation_err class
 188: return 16
 189: /**
 190:   TYPE_MISMATCH_ERR - If the type of an object is incompatible with the expected type of the parameter associated to the
 191:   object. 
 192: */
 193: ::method type_mismatch_err class
 194: return 17
 195: /* :end */
 196: 
 197: /* CLASS: xmlNodeList */ 
 198: /**
 199:   The xmlNodeList interface provides the abstraction of an ordered collection of xmlNodes, without defining or 
 200:   constraining how this collection is implemented. xmlNodeList objects in the DOM are live.
 201:   
 202:   For this ooRexx implementation a xmlNodeLIst is defined as a resticted array, whose members must be an instance of
 203:   xmLNode.
 204:   
 205:   The items in the xmlNodeList are accessible via an integral index, starting from 0. 
 206: */
 207: ::class xmlNodeList public 
 208: /**
 209:   Provide the number of xmlNodes in the xmlNodeList.
 210:   @return count - The number of items (xmlNodes) in the xmlNodeList.
 211: */
 212: ::method length 
 213: return self~nodeList~items
 214: /**
 215:   The nodeList array can only be set by the xmlNodeList self
 216: */
 217: ::attribute nodeList get
 218: ::attribute nodeList set
 219: /**
 220:   xmlNodeList instance constructor.
 221:   
 222:   As the creation of the xmlNodeList is left to the implementer, for ooRexx the constructor expects to get the
 223:   representation of the complete xmlNodeList as an ooRexx array.
 224:   @param nodeList=(.array~new) - an ooRexx array of xmlNodes.
 225: */
 226: ::method init
 227:   use strict arg nodeList=(.array~new)
 228:   if \nodeList~isA(.array) 
 229:     then raise syntax 93.914 array (nodeList, .Array)
 230:   self~nodeList = nodeList
 231: exit
 232: /**
 233:   Retrieve the xmlNode at index position.
 234:   @param index - The index (base 0) of the wanted Node. 
 235:   @return node - The xmlNode at the index in the xmlNodeList, or .nil if not a valid index.
 236: */
 237: ::method item 
 238:   use strict arg index
 239:   node = .nil
 240:   if index>=0 
 241:     then node = self~nodeList[index+1]
 242: return node
 243: /**
 244:   Add a xmlNode to the xmlNodeList.
 245:   @param node - The xmlNode to be added to the xmlNodeList.
 246:   @raises user domException - HIERARCHY_REQUEST_ERR
 247:   
 248: */
 249: ::method append
 250:   use strict arg node
 251:   if \node~isA(.xmlNode)
 252:     then raise syntax 88.914 array (node, .xmlNode)
 253:   self~nodeList~append(node)
 254: return
 255: /**
 256:   Removes a xmlNode from the xmlNodeList.
 257:   @param node - The xmlNode to be removed.
 258:   @return node - The removed xmlNode or .nil, if not present.
 259: 
 260:   Note: On hold for possible future use
 261: */
 262: ::method remove private protected
 263:   use strict arg node
 264:   node = self~nodelist~remove(node)
 265: return node
 266: /**
 267:   @return array - A native ooRexx array representing the xmlNodeList.
 268: */
 269: ::method toOorexxArray
 270: return self~nodeList
 271: /**
 272:   Sets the xmlNodeList from a native ooRexx array.
 273:   @param nodeArray - the native ooRexx array to replace an existing xmlNodeList.
 274: */
 275: ::method fromOorexxArray
 276:   use strict arg nodeArray
 277:   do i=1 to nodeArray~items
 278:     if \nodeArray[i]~isA(.xmlNode)
 279:       then raise syntax 88.914 array (nodeArray[i], .xmlNode)
 280:   end
 281:   self~nodeList = nodeArray
 282: return
 283: /* :end */
 284: 
 285: /* CLASS: xmlNode */
 286: /**
 287:   The xmlNode class is the base class for real nodetypes such as elementNode and textNode. 
 288:   
 289:   Methods that make no sense or that are just plain impossible to implement in this base class, because the
 290:   implementation is only possible in a subclass will raise syntax error 93.963 - Unsupported or not implented method.
 291:   
 292:   Methods that have a default value (e.g. .nil) will be intialized to that default value and need to be overridden in
 293:   the appropiate subclass.
 294: */
 295: ::class xmlNode public
 296: /**
 297:   A convenience constant to implement null
 298: */
 299: ::constant null .nil
 300: /**
 301:   Constants that define the type of nodes that are possible.
 302: */
 303: ::constant elementNode 1 
 304: ::constant attributeNode 2
 305: ::constant textNode 3
 306: ::constant cdataSectionNode 4
 307: ::constant entityReferenceNode 5
 308: ::constant entityNode 6
 309: ::constant processingInstructionNode 7
 310: ::constant commentNode 8
 311: ::constant documentNode 9
 312: ::constant documentTypeNode 10
 313: ::constant documentFragmentNode 11
 314: ::constant notationNode 12
 315: /**
 316:   instances is a private class attribute (property) that is used to
 317:   keep track of the node instances being created and to provide a unique 
 318:   identifier for each node.
 319: */
 320: ::attribute instances class private
 321: /**
 322:   Gets a unique identifier for each (subclass) node being created.
 323:   @return number - unique identifier for the new xmlNode
 324:   
 325:   The use of use strict arg makes sure there are no parameters.
 326: */
 327: ::method getId class
 328:   use strict arg
 329:   if instances~dataType('U') then instances = 0
 330:   instances += 1
 331: return instances
 332: /**
 333:   The unique node identification
 334: */
 335: ::attribute id private
 336: /**
 337:   A NamedNodeMap representing the attributes in an elementNode.
 338: */  
 339: ::attribute attributes get
 340: ::attribute attributes set
 341: /**
 342:   The absolute base URI of this node or null if the implementation was not able to obtain an absolute URI. 
 343: */
 344: ::attribute baseURI get
 345: ::attribute baseURI set
 346: /**
 347:   A nodeList containing the childNodes of a node. If there are no children, this is a NodeList containing no
 348:   nodes.
 349: */
 350: ::attribute childNodes get
 351: ::attribute childNodes set
 352: /**
 353:   The local part of the qualified name of this node.
 354:   
355: For nodes of any type other than ELEMENT_NODE and ATTRIBUTE_NODE and nodes created with a DOM Level 1 method, such as 356: xmlDocument~createElement, this is always .nil. 357: */ 358: ::attribute localName get 359: ::attribute localName set 360: /** 361: The namespace URI of this node, or null if it is unspecified. This is not a computed value that is the result of a 362: namespace lookup based on an examination of the namespace declarations in scope. It is merely the namespace URI given 363: at creation time. 364:
365: For nodes of any type other than ELEMENT_NODE and ATTRIBUTE_NODE and nodes created with a DOM Level 1 method, such as 366: xmlDocument~createElement, this is always .nil. 367: */ 368: ::attribute namespaceURI get 369: ::attribute namespaceURI set 370: /** 371: 372: */ 373: ::attribute nextSibling 374: /** 375: The following nodeName values are valid for a particular type of node: 376: 390: */ 391: ::attribute nodeName get 392: ::attribute nodeName set 393: /** 394: An integer indicating which type of node this is. See above. 395: */ 396: ::attribute nodeType get 397: ::attribute nodeType set 398: /** 399: The following nodeName values are valid for a particular type of node: 400: 414: */ 415: ::attribute nodeValue get 416: ::attribute nodeValue set 417: /** 418: The xmlDocument object associated with this node. This is also the xmlDocument object used to create new nodes. When 419: this node is a xmlDocument or a xmlDocumentType which is not used with any xmlDocument yet, this is .nil. 420: */ 421: ::attribute ownerDocument get 422: ::attribute ownerDocument set 423: /** 424: The parent of this node. All nodes, except xmlAttr, xmlDocument, xmlDocumentFragment, xmlEntity, and xmlNotation may 425: have a parent. However, if a node has just been created and not yet added to the tree, or if it has been removed from 426: the tree, this is .nil. 427: */ 428: ::attribute parentNode get 429: ::attribute parentNode set 430: /** 431: The namespace prefix of this node, or null if it is unspecified. When it is defined to be .nil, setting it has 432: no effect, including if the node is read-only. 433: 434: Note that setting this attribute, when permitted, changes the nodeName attribute, which holds the qualified name, as 435: well as the tagName and name attributes of the xmlElement and xmlAttr interfaces, when applicable. 436: 437: Setting the prefix to null makes it unspecified, setting it to an empty string is implementation dependent. Note also 438: that changing the prefix of an attribute that is known to have a default value, does not make a new attribute with the 439: default value and the original prefix appear, since the namespaceURI and localName do not change. 440: 441: For nodes of any type other than ELEMENT_NODE and ATTRIBUTE_NODE and nodes created with a DOM Level 1 method, such as 442: createElement from the xmlDocument interface, this is always .nil. 443: */ 444: ::attribute prefix get 445: ::attribute prefix set 446: /** 447: 448: */ 449: ::attribute previousSibling 450: /** 451: This attribute returns the text content of this node and its descendants. When it is defined to be .nil, setting it 452: has no effect. On setting, any possible children this node may have are removed and, if it the new string is not empty 453: or null, replaced by a single xmlText node containing the string this attribute is set to. 454: */ 455: ::method textContent 456: raise syntax 93.960 457: exit 458: ::attribute textContent set 459: /** 460: Method to initially set read-only attributes 461: @param attrName - the name of the Attribute. 462: @param attrValue - the value of the attribute. 463: @raises syntax 93.900 - Attribute value cannot be set twice 464: 465: If the attribute has been set already a syntx error will be raised 466: */ 467: ::method setReadOnly 468: --trace i 469: use strict arg attrName,attrValue 470: if self~send(attrName)<>attrName~upper 471: then raise syntax 93.900 array ("Attribute:" attrName "is read only, once set") 472: else self~send(attrName'=',attrValue) 473: return 474: /** 475: The instance constructor 476: */ 477: ::method init 478: self~id = self~class~getId 479: self~attributes = .nil 480: self~baseURI = .nil 481: self~childNodes = .xmlNodeList~new(.array~new) 482: self~localName = .nil 483: self~namespaceURI = .nil 484: self~nodeName = '' 485: self~nodeValue = '' 486: self~nodeType = .nil 487: self~ownerDocument = .nil 488: self~parentNode = .nil 489: self~prefix = .nil 490: return 491: /** 492: Adds the node child to the end of the list of children of this node. If the child is already in the 493: tree, it is first removed. 494: @param child - the node to be appended. 495: @return node - the node appended 496: 497: If child is a xmlDocumentFragment object, the entire contents of the document fragment are moved into the child 498: list of this node. 499: */ 500: ::method appendChild 501: use strict arg child 502: appended = .nil 503: if (child<>.nil) then do 504: child~parentNode = self 505: self~childNodes~append(child) 506: appended = child 507: end 508: return appended 509: /** 510: @return nodes - A xmlNodeList that contains all the children of this node. 511: 512: If there are no children, then this is a xmlNodeList containing no nodes. 513: */ 514: ::method children 515: use strict arg 516: return self~childNodes 517: /** 518: Returns a duplicate of this node, i.e., serves as a generic copy constructor for nodes. The duplicate node has no 519: parent (parentNode is .nil) and no user data. User data associated to the imported node is not carried over. 520: However, if any UserDataHandlers has been specified along with the associated data these handlers will be called with 521: the appropriate parameters before this method returns. 522: @param deep=.false - optional .true or .false (= default) 523: @return node - the duplicated node 524: 525: If deep is .true, recursively clone the subtree under the specified node; if .false, clone only 526: the node itself (and its attributes, if it is an xmlElement). 527: Cloning an xmlElement copies all attributes and their values, including those generated by the XML processor to 528: represent defaulted attributes, but this method does not copy any children it contains unless it is a deep 529: clone. This includes text contained in the xmlElement since the text is contained in a child xmlText node. 530:
531: Cloning an xmlAttr directly, as opposed to be cloned as part of an xmlElement cloning operation, returns a specified 532: attribute (specified is true). Cloning an xmlAttr always clones its children, since they represent its value, no 533: matter whether this is a deep clone or not. 534:
535: Cloning an xmlEntityReference automatically constructs its subtree if a corresponding xmlEntity is available, no 536: matter whether this is a deep clone or not. 537:
538: Cloning any other type of node simply returns a copy of this node. 539:
540: Note that cloning an immutable subtree results in a mutable copy, but the children of an xmlEntityReference clone are 541: readonly. In addition, clones of unspecified xmlAttr nodes are specified. And, cloning xmlDocument, xmlDocumentType, 542: xmlEntity, and xmlNotation nodes is implementation dependent. 543: */ 544: ::method cloneNode 545: use strict arg deep=.false 546: clone = self~copy 547: clone~parentNode = .nil 548: if deep = .true then do 549: raise syntax 93.963 550: end 551: return clone 552: /** 553: Compares the reference node, i.e. the node on which this method is being called, with a node, i.e. the one passed as a 554: parameter, with regard to their position in the document and according to the document order. 555: @param other - The node to compare with 556: @return number - Position relatively to the reference node 557: */ 558: ::method compareDocumentPosition 559: use strict arg other 560: raise syntax 93.963 561: exit 562: /** 563: @return child - The first child of this node 564: 565: If there is no such node, this returns .nil 566: */ 567: ::method firstChild 568: use strict arg 569: child = .nil 570: if (self~childNodes~length>0) then child = self~Childnodes~item(0) 571: return child 572: /** 573: @param feature - The name of the feature requested 574: @param version - The version number of the feature to test 575: @return domObject - An object which implements the specialized APIs or .nil 576: 577: This method returns a specialized object which implements the specialized APIs of the specified feature and version, 578: as specified in DOM Features. The specialized object may also be obtained by using binding-specific casting methods 579: but is not necessarily expected to. 580:
581: This method also allows the implementation to provide specialized objects which do not support the xmlNode interface. 582: */ 583: ::method getFeature 584: use strict arg feature, version 585: raise syntax 93.963 586: exit 587: /** 588: Retrieves the object associated to a key on a this node. The object must first have been set to this node by calling 589: setUserData with the same key. 590: @param key - The key the object is associated to. 591: @return userdata - the DOMUserData associated, or .nil if there was none 592: */ 593: ::method getUserData 594: use strict arg key 595: raise syntax 93.963 596: exit 597: /** 598: @return boolean - .true if this node has any attributes, .false otherwise 599: */ 600: ::method hasAttributes 601: use strict arg 602: return .false 603: /** 604: @return boolean - .true if this node has any children, .false otherwise 605: */ 606: ::method hasChildNodes 607: use strict arg 608: hasChildren = .false 609: if (self~children~items>0) then hasChildren = .true 610: return hasChildren 611: /** 612: Inserts the node child before the existing child node where. 613: @param child - the node to be inserted 614: @param where - the node before which the new node needs to be inserted. 615: @return node - the node being inserted 616: 617: If where is .nil, insert child at the end of the list of children. 618:
619: If child is a xmlDocumentFragment object, all of its children are inserted, in the same order, before 620: where. 621:
622: If the child is already in the tree, it is first removed. 623:
624: Note: Inserting a node before itself is implementation dependent. 625: */ 626: ::method insertBefore 627: use strict arg child, where 628: if (where==.nil) then do 629: self~childNodes~append(child) 630: end 631: -- find the where node 632: else do 633: newList = .xmlNodeList~new 634: do i=0 to self~childNodes~length-1 635: if self~childNodes~item(i) == where then newList~append(child) 636: newList~append(self~childNodes~item(i)) 637: end 638: self~childNodes = newList 639: end 640: child~parentNode = self 641: return child 642: /** 643: This method checks if the specified namespaceURI is the default namespace or not. 644: @param uri - The namespaceURI to look for 645: @return boolean - .true if default, .false otherwise 646: */ 647: ::method isDefaultNamespace 648: use strict arg uri 649: raise syntax 93.963 650: exit 651: /** 652: Tests whether two nodes are equal. 653: @param other - The node to compare equality with 654: @return boolean - .true if equal, .false otherwise 655: 656: 657: This method tests for equality of nodes, not sameness (i.e., whether the two nodes are references to the same object) 658: which can be tested with xmlNode~isSameNode. All nodes that are the same will also be equal, though the reverse may 659: not be true. 660:
661: Two nodes are equal if and only if the following conditions are satisfied: 662: 673: For two xmlDocumentType nodes to be equal, the following conditions must also be satisfied: 674: 679: On the other hand, the following do not affect equality: the ownerDocument, baseURI, and parentNode attributes, the 680: specified attribute for xmlAttr nodes, the schemaTypeInfo attribute for xmlAttr and xmlElement nodes, the 681: xmlText~isElementContentWhitespace attribute for xmlText nodes, as well as any user data or event listeners registered 682: on the nodes. 683: */ 684: ::method isEqualNode 685: use strict arg other 686: raise syntax 93.963 687: exit 688: /** 689: Tests whether this node is the same node as the given one. 690: @param other - The node to test against. 691: @return boolean - .true if the nodes are the same, .false otherwise. 692: 693: This method provides a way to determine whether two xmlNode references returned by the implementation reference the 694: same object. When two xmlNode references are references to the same object, even if through a proxy, the references 695: may be used completely interchangeably, such that all attributes have the same values and calling the same DOM method 696: on either reference always has exactly the same effect. 697: */ 698: ::method isSameNode 699: use strict arg other 700: raise syntax 93.963 701: exit 702: /** 703: Tests whether the DOM implementation implements a specific feature and that feature is supported by this node, as 704: specified in DOM Features. 705: @param feature - The name of the feature to test. 706: @param version - This is the version number of the feature to test. 707: @return boolean - .true if supported on this node, .false otherwise. 708: */ 709: ::method isSupported 710: use strict arg feature, version 711: return .false 712: /** 713: @return aNode - The last child of this node. 714: 715: If there is no such node, this returns .nil. 716: */ 717: ::method lastChild 718: use strict arg 719: child = .nil 720: if (self~children~items>0) then child = self~children[self~children~items] 721: return child 722: /** 723: Look up the namespaceURI associated to the given prefix, starting from this node. 724:
725: See Namespace URI Lookup for details on the algorithm used by this method. 726: @param prefix - The prefix to look for. 727: @return aString - The associated namespaceURI or .nil if none is found. 728: 729: If prefix is null, the method will return the default namespaceURI if any. 730: */ 731: ::method lookupNamespaceURI 732: use strict arg prefix 733: raise syntax 93.963 734: exit 735: /** 736: Look up the prefix associated to the given namespaceURI, starting from this node. 737: @param uri - A string specifying the namespaceURI to look for 738: @return aString - An associated namespace prefix or .nil if none is found 739: 740: The default namespace declarations are ignored by this method. See Namespace Prefix Lookup for details on the 741: algorithm used by this method. 742:
743: If more than one prefix are associated to the namespace prefix, the returned namespace prefix is implementation 744: dependent. 745: */ 746: ::method lookupPrefix 747: use strict arg uri 748: raise syntax 93.963 749: exit 750: /** 751: Finds the next sibling. 752: @return aNode - The node immediately following this node. 753: 754: If there is no such node, this returns .nil. 755: */ 756: /*::method nextSibling 757: use strict arg 758: sibling = .nil 759: if (self~parentNode<>.nil) then do 760: siblings = self~parentNode~childNodes 761: do label next i=1 to siblings~items 762: if (siblings[i]==self) then do 763: if (i 779: If the parameter "normalize-characters" of the DOMConfiguration object attached to the xmlNode~ownerDocument is 780: .true, this method will also fully normalize the characters of the xmlText nodes. 781:
782: Note: In cases where the document contains CDATASections, the normalize operation alone may not be sufficient, since 783: XPointers do not differentiate between xmlText nodes and xmlCDATASection nodes. 784: */ 785: ::method normalize 786: use strict arg 787: raise syntax 93.963 788: exit 789: /** 790: Finds the preceding node. 791: @return aNode - The node immediately preceding this node. 792: 793: If there is no such node, this returns .nil 794: */ 795: /** 796: ::method previousSibling 797: use strict arg 798: sibling = .nil 799: if (self~parentNode<>.nil) then do 800: siblings = self~parentNode~childNodes 801: do labl prev i=1 to siblings~items 802: if (siblings[i]==self) then do 803: if (i>1) then do 804: sibling = siblings[i-1] 805: leave prev 806: end 807: end 808: end 809: end 810: return sibling 811: */ 812: /** 813: Removes the child node indicated by aNode from the list of children, and returns it. 814: @param child - The node being removed. 815: @return aNode - The node removed. 816: */ 817: ::method removeChild 818: use strict arg child 819: removed = .nil 820: if (child<>.nil) then do 821: -- find the reference node 822: do i=1 to self~children~items 823: if (children[i]==child) then leave 824: end 825: removed = self~children~remove(i) 826: removed~parentNode = .nil 827: end 828: return removed 829: /** 830: Replaces the child node old with new in the list of children, and returns the old child node. 831: @param new - The new node to put in the child list. 832: @param old - The node being replaced in the list. 833: @return aNode - The node replaced. 834: 835: If new is a xmlDocumentFragment object, old is replaced by all of the 836: xmlDocumentFragment children, which are inserted in the same order. If the new 837: is already in the tree, it is first removed. 838:
839: Note: Replacing a node with itself is implementation dependent. 840: */ 841: ::method replaceChild 842: use strict arg new, old 843: replaced = .nil 844: if (old<>.nil) then do 845: -- find the reference node 846: do i=1 to self~children~items 847: if (self~children[i]==old) then leave 848: end 849: replaced = self~children[i] 850: self~children[i] = new 851: self~children[i]~parentNode = self 852: replaced~parentNode = .nil 853: end 854: return replaced 855: /** 856: Associate an object to a key on this node. The object can later be retrieved from this node by invoking the 857: getUserData method with the same key. 858: @param key - The key to associate the object to. 859: @param data - A DOMUserData object to associate to the key, or null to remove any existing association to that key. 860: @param handler - An UserDataHandler, a handler to associate to that key, or null. 861: @return userData - The DOMUserData previously associated to the given key on this node, or null if there was none. 862: */ 863: ::method setUserData 864: use strict arg key, data, handler 865: raise syntax 93.963 866: exit 867: /** 868: Convenience method to walk thru a (sub)nodes tree 869: @param nodes - The sibling xmlNodeList to start the walk. 870: @param name - The name of the tag being searched for. 871: @param nl - The xmlNodeList containing the selected result nodes. 872: */ 873: ::method treeWalk private 874: use strict arg nodes, name, nl 875: do n=0 to nodes~length-1 876: if name<>'*' then do 877: if nodes~item(n)~nodeName==name then nl~append(nodes~item(n)) 878: end 879: else do 880: nl~append(nodes~item(n)) 881: end 882: if nodes~item(n)~childNodes~length>0 then do 883: self~treewalk(nodes~item(n)~childNodes, name, nl) 884: end 885: end 886: return 887: /* :end */ 888: 889: /* CLASS: xmlNamedNodeMap */ 890: /** 891: Objects implementing the xmlNamedNodeMap interface are used to represent collections of nodes that can be accessed by 892: name. Note that xmlNamedNodeMap does not inherit from NodeList; NamedNodeMaps are not maintained in any particular 893: order. Objects contained in an object implementing xmlNamedNodeMap may also be accessed by an ordinal index, but this 894: is simply to allow convenient enumeration of the contents of a xmlNamedNodeMap, and does not imply that the DOM 895: specifies an order to these xmlNodes. xmlNamedNodeMap objects in the DOM are live. 896: */ 897: ::class xmlNamedNodeMap public 898: /** 899: A private array with directory entries, that have a (possibly qualified) name as index and xmlNodes as items. 900: */ 901: ::attribute namedMap private 902: /** 903: xmlNamedNodeMap instance constructor. 904: */ 905: ::method init 906: self~namedMap = .directory~new 907: self~init:super 908: exit 909: /** 910: The number of xmlNodes in this map. 911: @return - The number of nodes in the xmlNamedNodeMap. 912: */ 913: ::method length 914: return self~namedMap~items 915: /** 916: Retrieves a node specified by name. 917: @param name - The nodeName of a node to retrieve. 918: @return node - The xmlNode with the specified name, or .nil. 919: */ 920: ::method getNamedItem 921: use strict arg name 922: node = .nil 923: if name~isA(.string) then do 924: node = self~namedMap[name] 925: end 926: return node 927: /** 928: Retrieves a node specified by local name and namespace URI. 929: @param namespaceURI - The namespace URI of the node to retrieve. 930: @param localName - The local name of the node to retrieve. 931: @return node - A xmlNode(of any type) with the specified local name and namespace URI, or null. 932: 933: Per [XML Namespaces], applications must use the value .nil, as the namespaceURI parameter for methods if they 934: wish to have no namespace. 935: */ 936: ::method getNamedItemNS 937: use strict arg namespaceURI, localName 938: node = .nil 939: if (localName)~isA(.string) then do 940: node = self~namedMap[localName] 941: if namespaceURI<>.nil then do 942: if node~namespaceURI<>namespaceURI then node = .nil 943: end 944: end 945: return node 946: /** 947: Returns the indexth item in the map. If index is greater than or equal to the number of nodes in this map, this 948: returns .nil. 949: @param index - Index into this map. 950: @return node - The node at the indexth position in the map, or .nil if not a valid index. 951: */ 952: ::method item 953: use strict arg index 954: node = .nil 955: if index>=0 then do 956: node = self~namedMap~allItems[index+1] 957: end 958: return node 959: /** 960: Removes a node specified by name. 961: @param name - The nodeName of the node to remove. 962: @return node - The node removed from this map if a node with such a name exists. 963: @raises user domException - NOT_FOUND_ERR 964: 965: When this map contains the attributes attached to an element, if the removed attribute is known to have a default 966: value, an attribute immediately appears containing the default value as well as the corresponding namespace URI, 967: local name, and prefix when applicable. 968: 969: This ooRexx implementation does not process a DTD, thus has no way to determine if a default value has to be provided. 970: The node is only removed, no additional checks for default value are made. 971: */ 972: ::method removeNamedItem 973: use strict arg name 974: node = .nil 975: if name~isA(.string) then do 976: node = self~namedMap~remove(name) 977: end 978: if node==.nil then raise user domException description(.domException~not_found_err) 979: return node 980: /** 981: Removes a node specified by local name and namespace URI. A removed attribute may be known to have a default value 982: when this map contains the attributes attached to an element, as returned by the attributes attribute of the xmlNode 983: interface. If so, an attribute immediately appears containing the default value as well as the corresponding 984: namespace URI, local name, and prefix when applicable. 985: @param namespaceURI=.nil - The namespace URI of the node to remove. 986: @param localName - The local name of the node to remove. 987: @return node - The node removed from this map if a node with such a name exists. 988: @raises user domException - NOT_FOUND_ERR 989: 990: Per [XML Namespaces], applications must use the value .nil as the namespaceURI parameter for methods if they 991: wish to have no namespace. 992: @see #removeNamedItem for behaviour concerning default values. 993: */ 994: ::method removeNamedItemNS 995: use strict arg namespaceURI=.nil, localName 996: node = .nil 997: if (localName)~isA(.string) then do 998: if node~namespaceURI==namespaceURI 999: then node = self~namedMap~remove(localName) 1000: else node = .nil 1001: end 1002: return node 1003: /** 1004: Adds a xmlNode using its nodeName attribute. If a node with that name is already present in this map, it is 1005: replaced by the new one. Replacing a node by itself has no effect. 1006: @param arg - A xmlNode to store in this map, accessible using its nodeName attribute. 1007: @return node - The replaced xmlNode or .nil if no replacement. 1008: @raises user domException - WRONG_DOCUMENT_ERR 1009: @raises user domException - INUSE_ATTRIBUTE_ERR 1010: */ 1011: ::method setNamedItem 1012: use strict arg arg 1013: --if arg~ownerDocument<>self~ownerDocument 1014: -- then raise user domException description (.domException~wrong_document_err) 1015: if arg~nodeType==.xmlNode~attributeNode then do 1016: if arg~ownerElement<>.nil 1017: then raise user domException description (.domException~inuse_attribute_err) 1018: end 1019: node = .nil 1020: if arg~isA(.xmlNode) then do 1021: name = arg~nodeName 1022: node = self~namedMap[name] 1023: self~namedMap[name] = arg 1024: end 1025: return node 1026: /** 1027: Adds a node using its namespaceURI and localName. If a node with that namespace URI and that local name is already 1028: present in this map, it is replaced by the new one. Replacing a node by itself has no effect. 1029: @param arg - A node to add to the map, subsequently accessible via namespaceURI and localName. 1030: @return node - The replaced xmlNode or .nil if no replacement. 1031: @raises user domException - WRONG_DOCUMENT_ERR 1032: @raises user domException - INUSE_ATTRIBUTE_ERR 1033: */ 1034: ::method setNamedItemNS 1035: use strict arg arg 1036: if arg~ownerDocument<>self~ownerDocument 1037: then raise user domException description (.domException~wrong_document_err) 1038: if arg~nodeType==.attributeElement then do 1039: if arg~ownerElement<>.nil 1040: then raise user domException description (.domException~inuse_attribute_err) 1041: end 1042: node = .nil 1043: if arg~isA(.xmlNode) then do 1044: name = arg~localName 1045: node = self~namedMap[name] 1046: -- the following replaces also a node from a different namespace 1047: -- probably need a directory with name indexes and items of a directory with namespace indexes and node items 1048: if node~namespaceURI<>arg~namespaceURI 1049: then node = .nil 1050: else self~namedMap[name] = arg 1051: end 1052: return node 1053: /** 1054: Provides a xmlNamedNodeMap as a native ooRexx directory 1055: @return directory - A native ooRexx directory representing the NamedNodeMap. 1056: */ 1057: ::method toOorexxDirectory 1058: return self~namedMap 1059: /** 1060: Sets a NamedNodeMap from a native ooRexx directory 1061: @param nodeDirectory - The native ooRexx directory to replace an existing xmlNamedNodeMap. 1062: @raises syntax 93.914 - Named item is not a proper xmlNode 1063: */ 1064: ::method fromOorexxDirectory 1065: use strict arg nodeDirectory 1066: s = nodeDirectory~supplier 1067: do while s~available 1068: if \s~item~isA(.xmlNode) then do 1069: raise syntax 93.914 array (nodeDirectory, .xmlNode) 1070: end 1071: s~next 1072: end 1073: self~namedMap = nodeDirectory 1074: return 1075: /* :end */ 1076: 1077: /* CLASS: xmlAttr */ 1078: /** 1079: The xmlAttr interface represents an attribute in an xmlElement object. Typically the allowable values for the 1080: attribute are defined in a schema associated with the document. 1081: 1082: xmlAttr objects inherit the xmlNode interface, but since they are not actually child nodes of the element they 1083: describe, the DOM does not consider them part of the document tree. Thus, the xmlNode attributes parentNode, 1084: previousSibling, and nextSibling have a .nil value for xmlAttr objects. The DOM takes the view 1085: that attributes are properties of elements rather than having a separate identity from the elements they are 1086: associated with; this should make it more efficient to implement such features as default attributes associated with 1087: all elements of a given type. Furthermore, xmlAttr nodes may not be immediate children of a xmlDocumentFragment. 1088: However, they can be associated with xmlElement nodes contained within a xmlDocumentFragment. In short, users and 1089: implementors of the DOM need to be aware that xmlAttr nodes have some things in common with other objects inheriting 1090: the Node interface, but they also are quite distinct. 1091: 1092: The attribute's effective value is determined as follows: if this attribute has been explicitly assigned any value, 1093: that value is the attribute's effective value; otherwise, if there is a declaration for this attribute, and that 1094: declaration includes a default value, then that default value is the attribute's effective value; otherwise, the 1095: attribute does not exist on this element in the structure model until it has been explicitly added. Note that the 1096: xmlNode nodeValue attribute on the xmlAttr instance can also be used to retrieve the string version of the 1097: attribute's value(s). 1098: 1099: If the attribute was not explicitly given a value in the instance document but has a default value provided by the 1100: schema associated with the document, an attribute node will be created with specified set to false. Removing attribute 1101: nodes for which a default value is defined in the schema generates a new attribute node with the default value and 1102: specified set to false. If validation occurred while invoking the xmlDocument normalizeDocument, attribute 1103: nodes with specified equals to false are recomputed according to the default attribute values provided by the schema. 1104: If no default value is associate with this attribute in the schema, the attribute node is discarded. 1105: 1106: In XML, where the value of an attribute can contain entity references, the child nodes of the xmlAttr node may be 1107: either xmlText or xmlEntityReference nodes (when these are in use; see the description ofxml EntityReference for 1108: discussion). 1109: */ 1110: 1111: ::class xmlAttr public subclass xmlNode 1112: /** 1113: Returns whether this attribute is known to be of type ID (i.e. to contain an identifier for its owner element) or not. 1114: When it is and its value is unique, the ownerElement of this attribute can be retrieved using the xmlDocument 1115: getElementById method. The implementation could use several ways to determine if an attribute node is known to 1116: contain an identifier: 1117:
    1118:
  • If validation occurred using an XML Schema [XML Schema Part 1] while loading the document or while invoking the 1119: xmlDocument normalizeDocument method, the post-schema-validation infoset contributions (PSVI contributions) 1120: values are used to determine if this attribute is a schema-determined ID attribute using the schema-determined ID 1121: definition in [XPointer].
  • 1122:
  • If validation occurred using a DTD while loading the document or while invoking the xmlDocument 1123: normalizeDocument method, the infoset [type definition] value is used to determine if this attribute is a 1124: DTD-determined ID attribute using the DTD-determined ID definition in [XPointer].
  • 1125:
  • From the use of the xmlElement setIdAttribute, setIdAttributeNS, or setIdAttributeNode, i.e. 1126: it is an user-determined ID attribute;
  • 1127:
  • Using mechanisms that are outside the scope of this specification, it is then an externally-determined ID 1128: attribute. This includes using schema languages different from XML schema and DTD.
  • 1129: 1130: If validation occurred while invoking the xmlDocument normalizeDocument method, all user-determined ID 1131: attributes are reset and all attribute nodes ID information are then reevaluated in accordance to the schema used. As 1132: a consequence, if the xmlAttr schemaTypeInfo attribute contains an ID type, isId will always return 1133: .true. 1134: */ 1135: ::attribute isId get 1136: ::attribute isId set 1137: /** 1138: Returns the name of this attribute. If the xmlNode localName is different from .nil, this attribute is a 1139: qualified name. 1140: */ 1141: ::method name 1142: return self~nodeName 1143: /** 1144: The xmlElement node this attribute is attached to or .nil if this attribute is not in use. 1145: */ 1146: ::attribute ownerElement get 1147: ::attribute ownerElement set 1148: /** 1149: The type information associated with this attribute. While the type information contained in this attribute is 1150: guarantee to be correct after loading the document or invoking the xmlDocument normalizeDocument method, 1151: schemaTypeInfo may not be reliable if the node was moved. 1152: */ 1153: ::attribute schemaTypeInfo get 1154: ::attribute schemaTypeInfo set 1155: /** 1156: .true if this attribute was explicitly given a value in the instance document, false otherwise. If the 1157: application changed the value of this attribute node (even if it ends up having the same value as the default value) 1158: then it is set to .true. The implementation may handle attributes with default values from other schemas 1159: similarly but applications should use the xmlDocument normalizeDocument method to guarantee this information is 1160: up-to-date. 1161: */ 1162: ::attribute specified get 1163: ::attribute specified set 1164: /** 1165: On retrieval, the value of the attribute is returned as a string. Character and general entity references are replaced 1166: with their values. See also the method getAttribute on the xmlElement interface. 1167: 1168: On setting, this creates a xmlText node with the unparsed contents of the string, i.e. any characters that an XML 1169: processor would recognize as markup are instead treated as literal text. See also the xmlElement setAttribute 1170: method. 1171: */ 1172: ::method value 1173: return self~nodeValue 1174: /** 1175: xmlAttr instance creation method 1176: */ 1177: ::method init 1178: self~isId = .false 1179: self~ownerElement = .nil 1180: self~schemaTypeInfo = .nil -- not supported/implemented 1181: self~specified = .false 1182: self~init:super 1183: return 1184: /* :end */ 1185: 1186: /* CLASS: xmlCharacterData */ 1187: /** 1188: The CharacterData interface extends xmlNode with a set of attributes and methods for accessing character data in the 1189: DOM. For clarity this set is defined here rather than on each object that uses these attributes and methods. No DOM 1190: objects correspond directly to CharacterData, though Text and others do inherit the interface from it. All offsets in 1191: this interface start from 0. 1192: 1193: The following DOES NOT APPLY FOR this ooRexx xmlDOM implementation. Characters are ASCII 8-bit. 1194: As explained in the DOMString interface, text strings in the DOM are represented in UTF-16, i.e. as a sequence of 1195: 16-bit units. In the following, the term 16-bit units is used whenever necessary to indicate that indexing on 1196: CharacterData is done in 16-bit units. 1197: */ 1198: ::class xmlCharacterData public mixinclass xmlNode 1199: /** 1200: The data contained in a xmlNode 1201: */ 1202: ::method data 1203: return self~nodeValue 1204: /** 1205: */ 1206: ::method length 1207: return self~data~length 1208: /** 1209: xmlCharacterData instance constructor 1210: @param data - The character data 1211: */ 1212: ::method init 1213: use strict arg data 1214: self~init:super 1215: if arg~isA(.string) 1216: then self~nodeValue = data 1217: else raise user domException description (.domException~invalid_modification_err) 1218: exit 1219: /** 1220: Append the string to the end of the character data. Upon success, data and length reflect the change. 1221: @param arg - The data to be appended 1222: */ 1223: ::method appendData 1224: use strict arg arg 1225: if arg~isA(.string) 1226: then self~data ||= arg 1227: else raise user domException description (.domException~invalid_modification_err) 1228: return 1229: /** 1230: Remove a range of characters from the node. Upon success, data and length reflect the change. 1231: @param offset - The index(base 0) where to start deleting data 1232: @param count - The number of characters to delete 1233: */ 1234: ::method deleteData 1235: use strict arg offset, count 1236: self~data = self~data~delStr(offset+1,count) 1237: return 1238: /** 1239: Insert a string at the specified offset. 1240: @param offset - The index where to start inserting data 1241: @param string - The character data to insert 1242: */ 1243: ::method insertData 1244: use strict arg offset, string 1245: if offset>self~data~length | count<0 1246: then raise user domException description (.domException~index_size_err) 1247: self~data = self~data~substr(1,offset) || string || self~data~substr(offset+1) 1248: return 1249: /** 1250: Replace the characters starting at the specified offset with the specified string. 1251: @param offset - The offset from which to start replacing. 1252: @param count - The number of characters to replace. 1253: @param string - The string with which the range must be replaced. 1254: 1255: If the sum of offset and count exceeds length, then all data to the end of the data are replaced; (i.e., the effect is 1256: the same as a remove method call with the same range, followed by an append method invocation). 1257: */ 1258: ::method replaceData 1259: use strict arg offset, count, string 1260: if offset<0 | offset>self~data~length | count<0 1261: then raise user domException description (.domException~index_size_err) 1262: self~data = self~data~overlay(string,offset+1,count) 1263: return 1264: /** 1265: Extracts a range of data from the node. 1266: @param offset - The index where to start retrieving data 1267: @param count - The number of characters to retrieve 1268: @return string - The specified substring. If the sum of offset and count exceeds the length, then all characters to 1269: the end of the data are returned. 1270: */ 1271: ::method substringData 1272: use strict arg offset, count 1273: if offset<0 | offset>self~data~length | count<0 1274: then raise user domException description (.domException~index_size_error) 1275: return self~data~substr(offset+1,count) 1276: /* :end */ 1277: 1278: /* CLASS: xmlComment */ 1279: /** 1280: This interface inherits from xmlCharacterData and represents the content of a comment, i.e., all the characters 1281: between the starting ''. Note that this is the definition of a comment in XML, and, in practice, 1282: HTML, although some HTML tools may implement the full SGML comment structure. 1283: 1284: No lexical check is done on the content of a comment and it is therefore possible to have the character sequence "--" 1285: (double-hyphen) in the content, which is illegal in a comment per section 2.5 of [XML 1.0]. The presence of this 1286: character sequence must generate a fatal error during serialization. 1287: */ 1288: ::class xmlComment public subclass xmlNode inherit xmlCharacterData 1289: /** 1290: commentNode instance constructor. 1291: @param data - The string representing the XML comment 1292: */ 1293: ::method init 1294: use strict arg data 1295: self~init:super(data) 1296: return 1297: /* :end */ 1298: 1299: /* CLASS: xmlText */ 1300: /** 1301: The XMLText interface inherits from XMLCharacterData and represents the textual content (termed character data in XML) 1302: of an xmlElement or xmlAttr. If there is no markup inside an element's content, the text is contained in a single 1303: object implementing the xmlText interface that is the only child of the element. If there is markup, it is parsed into 1304: the information items (elements, comments, etc.) and xmlText nodes that form the list of children of the element. 1305: 1306: When a document is first made available via the DOM, there is only one xmlText node for each block of text. Users may 1307: create adjacent xmlText nodes that represent the contents of a given element without any intervening markup, but 1308: should be aware that there is no way to represent the separations between these nodes in XML or HTML, so they will not 1309: (in general) persist between DOM editing sessions. The xmlNode normalize method merges any such adjacent 1310: xmlText objects into a single node for each block of text. 1311: 1312: No lexical check is done on the content of a xmlText node and, depending on its position in the document, some 1313: characters must be escaped during serialization using character references; e.g. the characters "<&" if the textual 1314: content is part of an element or of an attribute, the character sequence "]]>" when part of an element, the quotation 1315: mark character " or the apostrophe character ' when part of an attribute. 1316: */ 1317: ::class xmlText public subclass xmlNode inherit xmlCharacterData 1318: /** 1319: Returns whether this text node contains element content whitespace, often abusively called "ignorable whitespace". The 1320: text node is determined to contain whitespace in element content during the load of the document or if validation 1321: occurs while using the xmlDocument normalizeDocument method. 1322: */ 1323: ::attribute isElementContentWhitespace get 1324: ::attribute isElementContentWhitespace set private 1325: /** 1326: Returns all text of xmlText nodes logically-adjacent text nodes to this node, concatenated in document order. 1327: 1328: For instance, in the example below wholeText on the xmlText node that contains "bar" returns "barfoo", and also 1329: on the xmlText node that contains "foo" it returns "barfoo". 1330: */ 1331: ::method wholeText 1332: siblings = self~parentNode~childNodes 1333: wholeText = '' 1334: do s=0 to siblings~length-1 1335: wholeText = wholeText || s~data' ' 1336: end 1337: return wholeText~strip('T') 1338: /** 1339: xmlText instance constructor 1340: @param content - The text string representing the content 1341: */ 1342: ::method init 1343: use strict arg content 1344: self~init:super(content) 1345: if self~class==.xmlText 1346: then do 1347: self~nodeType = .xmlNode~textNode 1348: self~nodeName = "#text" 1349: end 1350: else do 1351: self~nodeType = .xmlNode~CDATASectionNode 1352: self~nodeName = "#cdata-section" 1353: end 1354: --self~nodeValue = content 1355: return 1356: 1357: /** 1358: Replaces the text of the current node and all logically-adjacent text nodes with the specified text. All 1359: logically-adjacent text nodes are removed including the current node unless it was the recipient of the replacement 1360: text. 1361: This method returns the node which received the replacement text. The returned node is: 1362:
      1363:
    • .nil, when the replacement text is the empty string;
    • 1364:
    • the current node, except when the current node is read-only;
    • 1365:
    • a new xmlText node of the same type (xmlText or xmlCDATASection) as the current node inserted at the location of 1366: the replacement.
    • 1367:
    1368: @param content - The content of the replacing xmlText node. 1369: @return text - The xmlText node created with the specified content. 1370: 1371: Assumption: Text and CDATASections are the only ones within Element nodes (and possibly within Attr nodes). 1372: */ 1373: ::method replaceWholeText 1374: use strict arg content 1375: text = .nil 1376: if content<>'' then do 1377: text = self~class~new(content) 1378: nodeList = .xmlNodeList~new(.array~of(text)) 1379: self~parentNode~childNodes = nodeList 1380: end 1381: return text 1382: /** 1383: Breaks this node into two nodes at the specified offset, keeping both in the tree as siblings. After being split, this 1384: node will contain all the content up to the offset point. A new node of the same type, which contains all the content 1385: at and after the offset point, is returned. If the original node had a parent node, the new node is inserted as the 1386: next sibling of the original node. When the offset is equal to the length of this node, the new node has no data. 1387: @param offset - The offset at which to split, starting from 0. 1388: @return text - The new node, of the same type as this node. 1389: @raises user domException - INDEX_SIZE_ERR 1390: */ 1391: ::method splitText 1392: use strict arg offset 1393: if offset+1>self~data~length then do 1394: raise user domException additional (.domException~index_size_err) description ("Offset" offset "is larger than length" self~data~length "of text") 1395: end 1396: text = self~class~new(self~data~substr(offset+1)) 1397: self~data = self~data~substr(1,offset) 1398: siblings = .array~new 1399: do c=0 to self~parentNode~childNodes-1 1400: child = self~parentNode~childNodes~item(c) 1401: siblings~append(child) 1402: if child==self then do 1403: siblings~append(text) 1404: end 1405: end 1406: children = .xmlNodelist~new(siblings) 1407: self~parentNode~childNodes = children 1408: return text 1409: /* :end */ 1410: 1411: /* CLASS: xmlCDATASection */ 1412: /** 1413: CDATA sections are used to escape blocks of text containing characters that would otherwise be regarded as markup. 1414: The only delimiter that is recognized in a CDATA section is the "]]>" string that ends the CDATA section. CDATA 1415: sections cannot be nested. Their primary purpose is for including material such as XML fragments, without needing to 1416: escape all the delimiters. 1417: 1418: The xmlCharacterData data attribute holds the text that is contained by the CDATA section. Note that this may 1419: contain characters that need to be escaped outside of CDATA sections and that, depending on the character encoding 1420: ("charset") chosen for serialization, it may be impossible to write out some characters as part of a CDATA section. 1421: 1422: The CDATASection interface inherits from the xmlCharacterData interface through the xmlText interface. Adjacent 1423: xmlCDATASection nodes are not merged by use of the normalize method of the xmlNode interface. 1424: 1425: No lexical check is done on the content of a CDATA section and it is therefore possible to have the character sequence 1426: "]]>" in the content, which is illegal in a CDATA section per section 2.7 of [XML 1.0]. The presence of this character 1427: sequence must generate a fatal error during serialization. 1428: 1429: Note: Because no markup is recognized within a xmlCDATASection, character numeric references cannot be used as an 1430: escape mechanism when serializing. Therefore, action needs to be taken when serializing a CDATASection with a 1431: character encoding where some of the contained characters cannot be represented. Failure to do so would not produce 1432: well-formed XML. 1433: 1434: One potential solution in the serialization process is to end the CDATA section before the character, output the 1435: character using a character reference or entity reference, and open a new CDATA section for any further characters in 1436: the text node. Note, however, that some code conversion libraries at the time of writing do not return an error or 1437: exception when a character is missing from the encoding, making the task of ensuring that data is not corrupted on 1438: serialization more difficult. 1439: */ 1440: ::class xmlCDATASection public subclass xmlText 1441: /** 1442: The CDATASection instance constructot 1443: @param content - The unparsed string representing the contents of the CDATASection. 1444: */ 1445: ::method init 1446: use strict arg content 1447: self~init:super(content) 1448: return 1449: /* :end */ 1450: 1451: /* CLASS: xmlPI */ 1452: /** 1453: The ProcessingInstruction interface represents a "processing instruction", used in XML as a way to keep 1454: processor-specific information in the text of the document. 1455: 1456: No lexical check is done on the content of a processing instruction and it is therefore possible to have the character 1457: sequence "?>" in the content, which is illegal a processing instruction per section 2.6 of [XML 1.0]. The presence of 1458: this character sequence must generate a fatal error during serialization. 1459: */ 1460: ::class xmlPI public subclass xmlNode 1461: /** 1462: The content of this processing instruction. This is from the first non white space character after the target to the 1463: character immediately preceding the ?>. 1464: */ 1465: ::method data 1466: return self~nodeValue 1467: /** 1468: The target of this processing instruction. XML defines this as being the first token following the markup that begins 1469: the processing instruction. 1470: */ 1471: ::method target 1472: return self~nodeName 1473: /** 1474: The xmlProcessingInstruction instance constructor 1475: @param target - The target for the processing instruction 1476: @param data - The unparsed string representing the content of the processing instruction. 1477: */ 1478: ::method init 1479: use strict arg target, data 1480: self~init:super 1481: self~nodeType = .xmlNode~processingInstructionNode 1482: self~nodeName = target 1483: self~nodeValue = data 1484: return 1485: /* :end */ 1486: 1487: /* CLASS: xmlDocumentType */ 1488: /** 1489: Information about the notations and entities declared by a document (including the external subset if the parser uses 1490: it and can provide the information) is available from a xmlDocumentType object. The xmlDocumentType for a document is 1491: available from the xmlDocument object’s doctype attribute; if there is no DOCTYPE declaration for the document, the 1492: document’s doctype attribute will be set to .nil instead of an instance of this interface. 1493: 1494: xmlDocumentType is a subclass (precisation) of xmlNode, and adds the following attributes: 1495:
      1496:
    • entities - This is a xmlNamedNodeMap giving the definitions of external and internal entities. For entity names 1497: defined more than once, only the first definition is provided (others are ignored as required by the XML 1498: recommendation). This may be .nil if the information is not provided by the parser, or if no entities are 1499: defined.
    • 1500:
    • internalSubset - A string giving the complete internal subset from the document. This does not include the 1501: brackets which enclose the subset. If the document has no internal subset, this is .nil.
    • 1502:
    • name - The name of the root element as given in the DOCTYPE declaration, if present.
    • 1503:
    • notations - This is a xmlNamedNodeMap giving the definitions of notations. For notation names defined more than 1504: once, only the first definition is provided (others are ignored as required by the XML recommendation). This may be 1505: .nil if the information is not provided by the parser, or if no notations are defined.
    • 1506:
    • publicId - The public identifier for the external subset of the document type definition. This will be a string 1507: or .nil.
    • 1508:
    • systemId - The system identifier for the external subset of the document type definition. This will be a URI as a 1509: string, or .nil.
    • 1510:
    1511: 1512: DOM Level 3 doesn't support editing DocumentType nodes. DocumentType nodes are read-only. 1513: */ 1514: ::class xmlDocumentType public subclass xmlNode 1515: /** 1516: Entities is a xmlNamedNodeMap containing the general entities, both external and internal, declared in the DTD. 1517: Parameter entities are not contained. Every node in this map also implements the Entity interface. 1518: The DOM Level 2 does not support editing entities, therefore entities cannot be altered in any way. 1519: */ 1520: ::attribute entities get 1521: ::attribute entities set 1522: /** 1523: The internal subset as a string, or .nil if there is none. This does not contain the delimiting square 1524: brackets. 1525: NOTE, - The actual content returned depends on how much information is available to the implementation. 1526: This may vary depending on various parameters, including the XML processor used to build the document. 1527: */ 1528: ::attribute internalSubset get 1529: ::attribute internalSubset set 1530: /** 1531: The name of DTD; i.e., the name immediately following the DOCTYPE keyword. 1532: */ 1533: ::attribute name get 1534: ::attribute name set 1535: /** 1536: Notations is xmlNamedNodeMap containing the notations declared in the DTD. Duplicates are discarded. Every node in 1537: this map also implements the xmlNotation interface. 1538: The DOM Level 2 does not support editing notations, therefore notations cannot be altered in any way. 1539: */ 1540: ::attribute notations get 1541: ::attribute notations set 1542: /** 1543: The public identifier of the external subset. 1544: */ 1545: ::attribute publicId get 1546: ::attribute publicId set 1547: /** 1548: The system identifier of the external subset. This may be an absolute URI or not. 1549: */ 1550: ::attribute systemId get 1551: ::attribute systemId set 1552: /** 1553: xmlDocumentType instance constructor. 1554: @param name - The qualified name of the document (e.g. 'gpx'), is equal to the root tagName. 1555: @param publicId - The public identifier of this document type (e.g. '-//W3C//DTD XHTML 1.0 Strict//EN'). 1556: @param systemId - The system identifier for the docType (e.g. 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'). 1557: */ 1558: ::method init 1559: use strict arg name, publicId, systemId 1560: self~nodeType = 10 1561: self~nodeName = name 1562: self~publicId = publicId 1563: self~systemId = systemId 1564: self~entities = .NamedNodeMap~new 1565: self~notations = .NamedNodeMap~new 1566: self~internalSubset = .nil 1567: return 1568: /* :end */ 1569: 1570: /* CLASS: xmlElement */ 1571: /** 1572: The Element interface represents an element in an HTML or XML document. Elements may have attributes associated with 1573: them; since the Element interface inherits from Node, the generic Node interface attribute attributes may be used to 1574: retrieve the set of all attributes for an element. There are methods on the Element interface to retrieve either an 1575: Attr object by name or an attribute value by name. In XML, where an attribute value may contain entity references, an 1576: Attr object should be retrieved to examine the possibly fairly complex sub-tree representing the attribute value. On 1577: the other hand, in HTML, where all attributes have simple string values, methods to directly access an attribute value 1578: can safely be used as a convenience. 1579: 1580: Note: In DOM Level 2, the method normalize is inherited from the Node interface where it was moved. 1581: */ 1582: ::class xmlElement public subclass xmlNode 1583: /** 1584: Private method to walk the xmlNode tree and retrieve all elements with the specified tagName. 1585: @param nodes - the xmlNodes to start with, i.e. the childNodes from the receiver node. 1586: @param tag - The name odf the tag for the elements to be selected,'*' means all tags. 1587: @param nodeList - A xmlNodeList with all the selected elements in the subtree with specified tagName. 1588: */ 1589: ::method selectElements private 1590: use strict arg nodes, tag, nodeList 1591: do n=0 to nodes~length-1 1592: node = nodes~item(n) 1593: if node~nodeType==.xmlNode~elementNode then do 1594: if tag<>'*' then do 1595: if node~tagName==tag then nodeList~append(node) 1596: end 1597: else do 1598: nodeList~append(node) 1599: end 1600: if node~childNodes~length>0 then do 1601: self~selectElements(node~childNodes, tag, nodeList) 1602: end 1603: end 1604: end 1605: return 1606: /** 1607: Private method to walk the xmlNode tree and retrieve all elements from a namespace with the specified local name. 1608: @param nodes - the xmlNodes to start with, i.e. the childNodes from the receiver node. 1609: @param namespaceURI - The namespace of the elements to be selected. 1610: @param localName - The local name for the element to be selected. 1611: @param nodeList - A xmlNodeList with all the elements in the subtree with specified tagName. 1612: */ 1613: ::method selectElementsNS private 1614: use strict arg nodes, namespaceURI, localName, nodeList 1615: do n=0 to nodes~items-1 1616: node = nodes[n] 1617: if node~nodeType==.xmlNode~elementNode then do 1618: if localName<>'*' then do 1619: if node~localName==localName then do 1620: if namespaceURI<>'*' then do 1621: if node~namespaceURI==namespacURI then nodeList~append(node) 1622: end 1623: else do 1624: nodeList~append(node) 1625: end 1626: end 1627: else do 1628: nop 1629: end 1630: end 1631: else do 1632: if namespaceURI<>'*' then do 1633: if node~namespaceURI==namespacURI then nodeList~append(node) 1634: end 1635: else do 1636: nodeList~append(node) 1637: end 1638: end 1639: end 1640: if node~childNodes~items>0 then do 1641: self~getElementNodesByTagNS(node~childNodes, namespaceURI, localName, nodeList) 1642: end 1643: end 1644: return 1645: /** 1646: The type information associated with this element. 1647: */ 1648: ::method schemaTypeInfo 1649: raise syntax 93.900 array (isUnderConstruction(.context~name)) 1650: return 1651: /** 1652: The name of the element. If Node localName is different from null, this attribute is a qualified name. 1653: */ 1654: ::method tagName 1655: return self~nodeName 1656: /** 1657: xmlElement instance constructor 1658: @param tagName - The name of the xmlElement to be created. 1659: 1660: nodeValue, localName, prefix, namespaceURI and childNodes are set by the superclass xmlNode 1661: */ 1662: ::method init 1663: use strict arg tagName 1664: self~init:super 1665: self~nodeName = tagname 1666: self~nodeType = .xmlNode~elementNode 1667: self~attributes = .xmlNamedNodeMap~new 1668: --self~nodeValue = .nil 1669: --self~localName = .nil 1670: --self~prefix = .nil 1671: --self~namespaceURI = .nil 1672: --self~childNodes = xmlNodeList~new 1673: return 1674: /** 1675: Retrieves an attribute value by name. 1676: @param name - The name of the attribute to retrieve. 1677: @return string - The xmlAttr value or .nil if that attribute does not have a specified or default value. 1678: */ 1679: ::method getAttribute 1680: use strict arg name 1681: nodeValue = .nil 1682: node = self~attributes~getNamedItem(name) 1683: if node<>.nil then nodeValue = node~nodeValue 1684: return nodeValue 1685: /** 1686: Retrieves an attribute value by local name and namespace URI. 1687: @param namespaceURI=.nil - The namespace URI of the attribute to retrieve. 1688: @param localName - The local name of the attribute to retrieve. 1689: @return string - The xmlAttr value, or the empty string if that attribute does not have a specified or default value. 1690: 1691: Per [XML Namespaces], applications must use the value null as the namespaceURI parameter for methods if they wish to 1692: have no namespace. 1693: 1694: Assumption: Attributes can not have a default namespace, thus need a prefix if they belong to a certain namespace. 1695: Assumption: A namespace can have multiple prefixes. 1696: */ 1697: ::method getAttributeNS 1698: use strict arg namespaceURI=.nil, localName 1699: nodeValue = .nil 1700: if namespaceURI==.nil then do 1701: node = self~attributes~getNamedItem(localName) 1702: if node<>.nil then nodeValue = node~nodeValue 1703: end 1704: else do 1705: prefixes = self~ownerdocument~nameSpaces[namespaceURI] 1706: found = .false 1707: if prefixes<>.nil then do i=1 to prefix~words until found 1708: prefix = prefixes~word(i) 1709: node = self~attributes~getNamedItem(prefix":"localName) 1710: if node<>.nil then do 1711: nodeValue = node~nodeValue 1712: found = .true 1713: end 1714: end 1715: end 1716: return nodeValue 1717: /** 1718: Retrieves an attribute node by name. 1719: @param name - The nodeName of the attribute to retrieve 1720: @return node - The xmlAttr node with the specified nodeName or .nil if there is no such attribute. 1721: 1722: To retrieve an attribute node by qualified name and namespace URI, use the getAttributeNodeNS method. 1723: */ 1724: ::method getAttributeNode 1725: use strict arg name 1726: attrNode = self~attributes~getNamedItem(name) 1727: return attrNode 1728: /** 1729: Retrieves an Attr node by local name and namespace URI. 1730: @param namespaceURI=.nil - The namespace URI of the attribute to retrieve. 1731: @param localName - The local name of the attribute to retrieve. 1732: @return node - The xmlAttr node with the specified attribute local name and namespace URI or null if there is no such 1733: attribute. 1734: 1735: Per [XML Namespaces], applications must use the value null as the namespaceURI parameter for methods if they wish to 1736: have no namespace. 1737: 1738: Assumption: Attributes can not have a default namespace, thus need a prefix if they belong to a certain namespace. 1739: Assumption: A namespace can have multiple prefixes. 1740: */ 1741: ::method getAttributeNodeNS 1742: use strict arg namespaceURI=.nil, localName 1743: if namespaceURI==.nil then do 1744: attrNode = self~attributes~getNamedItem(localName) 1745: end 1746: else do 1747: prefixes = self~ownerdocument~nameSpaces[namespaceURI] 1748: found = .false 1749: if prefixes<>.nil then do i=1 to prefix~words until found 1750: prefix = prefixes~word(i) 1751: attrNode = self~attributes~getNamedItem(prefix":"localName) 1752: if attrNode<>.nil then found = .true 1753: end 1754: end 1755: return attrNode 1756: /** 1757: Returns a xmlNodeList of all descendant xmlElements with a given tag name, in document order. 1758: @param tag - The name of the tag to match on. The special value "*" matches all tags. 1759: @return nodeList - A list of matching xmlElement nodes. 1760: */ 1761: ::method getElementsByTagName 1762: use strict arg tag 1763: nodeList = .xmlNodeList~new 1764: self~selectElements(self~childNodes, tag, nodeList) 1765: return nodeList 1766: /** 1767: Returns true when an attribute with a given name is specified on this element or has a default value, false otherwise. 1768: @param name - The name of the attribute to look for. 1769: @return boolean - .true if an attribute with the given name is specified on this element or has a default 1770: value, .false otherwise. 1771: */ 1772: ::method hasAttribute 1773: use strict arg name 1774: return self~attributes~getNamedItem(name)<>.nil 1775: /** 1776: Returns true when an attribute with a given local name and namespace URI is specified on this element or has a default 1777: value, false otherwise. 1778: @param namespaceURI=.nil - The namespace URI of the attribute to look for. 1779: @param localName - The local name of the attribute to look for. 1780: @return boolean - .true if an attribute with the given local name and namespace URI is specified or has a 1781: default value on this element, .false otherwise. 1782: 1783: Per [XML Namespaces], applications must use the value .nil as the namespaceURI parameter for methods if they 1784: wish to have no namespace. 1785: 1786: Assumption: Attributes can not have a default namespace, thus need a prefix if they belong to a certain namespace. 1787: Assumption: A namespace can have multiple prefixes. 1788: */ 1789: ::method hasAttributeNS 1790: use strict arg namespaceURI=.nil, localName 1791: boolean = .false 1792: if namespaceURI==.nil then do 1793: boolean = self~attributes~getNamedItem(name)<>.nil 1794: end 1795: prefixes = self~ownerDocument~nameSpaces[namespaceURI] 1796: if prefixes<>.nil then do 1797: do p=1 to prefixes~words until boolean==.true 1798: prefix = prefixes~word(p) 1799: boolean = self~attributes~getNamedItem(prefix':'localName)<>.nil 1800: end 1801: end 1802: return boolean 1803: /** 1804: Removes an attribute by name. 1805: NOT supported here: 1806: (If a default value for the removed attribute is defined in the DTD, a new attribute immediately appears with the 1807: default value as well as the corresponding namespace URI, local name, and prefix when applicable. The implementation 1808: may handle default values from other schemas similarly but applications should use Document.normalizeDocument() to 1809: guarantee this information is up-to-date.) 1810: @param name - The name of the attribute to remove. 1811: 1812: If no attribute with this name is found, this method has no effect. 1813: To remove an attribute by local name and namespace URI, use the removeAttributeNS method. 1814: */ 1815: ::method removeAttribute 1816: use strict arg name 1817: removed = self~attributes~removeNamedItem(name) 1818: return 1819: /** 1820: Removes an attribute by local name and namespace URI. 1821: NOT supported here: 1822: (If a default value for the removed attribute is defined in the DTD, a new attribute immediately appears with the 1823: default value as well as the corresponding namespace URI, local name, and prefix when applicable. The implementation 1824: may handle default values from other schemas similarly but applications should use Document.normalizeDocument() to 1825: guarantee this information is up-to-date.) 1826: @param nameSpaceURI=.nil - The namespace URI of the attribute to remove. 1827: @param localName - The local name of the attribute to remove. 1828: 1829: If no attribute with this local name and namespace URI is found, this method has no effect. 1830: 1831: Per [XML Namespaces], applications must use the value .nil as the namespaceURI parameter for methods if they 1832: wish to have no namespace. 1833: */ 1834: ::method removeAttributeNS 1835: use strict arg nameSpaceURI=.nil, localName 1836: removed = self~attributes~removeNamedItemNS(namespaceURI,localName) 1837: return 1838: /** 1839: Removes the specified attribute node. 1840: NOT supported here: 1841: (If a default value for the removed Attr node is defined in the DTD, a new node immediately appears with the default 1842: value as well as the corresponding namespace URI, local name, and prefix when applicable. The implementation may 1843: handle default values from other schemas similarly but applications should use Document.normalizeDocument() to 1844: guarantee this information is up-to-date.) 1845: @param oldAttr - The reference to the xmlAttr to be removed. 1846: @return attr - The removed attribute. 1847: @raises user domException - NOT_FOUND_ERR perhaps 1848: */ 1849: ::method removeAttributeNode 1850: use strict arg oldAttr 1851: removed = self~attributes~removeNamedItem(oldAttr~nodeName) 1852: return removed 1853: /** 1854: Adds a new attribute. If an attribute with that name is already present in the element, its value is changed to be 1855: that of the value parameter. This value is a simple string; it is not parsed as it is being set. So any markup (such 1856: as syntax to be recognized as an entity reference) is treated as literal text, and needs to be appropriately escaped 1857: by the implementation when it is written out. In order to assign an attribute value that contains entity references, 1858: the user must create an xmlAttr node plus any xmlText and xmlEntityReference nodes, build the appropriate subtree, and 1859: use setAttributeNode to assign it as the value of an attribute. 1860: @param name - The name of the attribute to create or alter. 1861: @param value - Value to set in string form. 1862: @raises user domException - INVALID_CHARACTER_ERR 1863: 1864: To set an attribute with a qualified name and namespace URI, use the setAttributeNS method. 1865: */ 1866: ::method setAttribute 1867: use strict arg name, value 1868: if name~verify(xmlValidName())>0 then do 1869: raise user domException description (.domException~invalid_character_err) 1870: end 1871: node = self~attributes~getNamedItem(name) 1872: if node<>.nil then do 1873: node~nodeValue = value 1874: end 1875: else do 1876: node = xmlAttr~new 1877: node~nodeName = name 1878: node~nodeValue = value 1879: self~attributes~setNamedItem(node) 1880: end 1881: return 1882: /** 1883: Adds a new attribute. If an attribute with the same local name and namespace URI is already present on the element, 1884: its prefix is changed to be the prefix part of the qualifiedName, and its value is changed to be the value parameter. 1885: This value is a simple string; it is not parsed as it is being set. So any markup (such as syntax to be recognized as 1886: an entity reference) is treated as literal text, and needs to be appropriately escaped by the implementation when it 1887: is written out. In order to assign an attribute value that contains entity references, the user must create an Attr 1888: node plus any Text and EntityReference nodes, build the appropriate subtree, and use setAttributeNodeNS or 1889: setAttributeNode to assign it as the value of an attribute. 1890: @param namespaceURI=.nil - The namespace URI of the attribute to create or alter. 1891: @param qualifiedName - The qualified name of the attribute to create or alter. 1892: @param value - The value to set in string form. 1893: @raises user domException - INVALID_CHARACTER_ERR 1894: @raises user domException - NAMESPACE_ERR 1895: 1896: Per [XML Namespaces], applications must use the value .nil as the namespaceURI parameter for methods if they 1897: wish to have no namespace. 1898: */ 1899: ::method setAttributeNS 1900: use strict arg namespaceURI=.nil, qualifiedName, value 1901: if qualifiedName~verify(xmlValidName())>0 then do 1902: raise user domException description (.domException~invalid_character_err) 1903: end 1904: if qualifiedName~pos(':')>0 & namespaceURI==.nil then do 1905: raise user domException description (.domException~namespace_err) 1906: end 1907: if qualifiedName~substr(1,3)~lower=="xml" & namespaceURI<>"http://www.w3.org/XML/1998/namespace" then do 1908: raise user domException description (.domException~namespace_err) 1909: end 1910: if qualifiedName~substr(1,5)~lower=="xmlns" & namespaceURI<>"http://www.w3.org/2000/xmlns/" then do 1911: raise user domException description (.domException~namespace_err) 1912: end 1913: if qualifiedName~substr(1,5)~lower<>"xmlns" & namespaceURI=="http://www.w3.org/2000/xmlns/" then do 1914: raise user domException description (.domException~namespace_err) 1915: end 1916: localName = qualifiedName 1917: if quailifedName~pos(':')>0 then parse var qualifiedName prefix ':'localName 1918: node = self~attributes~getNamedItemNS(namespaceURI,localName) 1919: if node<>.nil then do 1920: node~nodeValue = value 1921: end 1922: else do 1923: node = xmlAttr~new 1924: node~nodeName = name 1925: node~nodeValue = value 1926: node~namespaceURI = namespaceURI 1927: node~localName = localName 1928: node~prefix = prefix 1929: self~attributes~setNamedItemNS(node) 1930: end 1931: return 1932: /** 1933: Adds a new attribute node. If an attribute with that name (nodeName) is already present in the element, it is replaced 1934: by the new one. Replacing an attribute node by itself has no effect. 1935: @param newAttr - The xmlAttr node to add to the attribute list. 1936: @return attr - If the newAttr attribute replaces an existing attribute, the replaced Attr node is returned, otherwise 1937: .nil is returned. 1938: @raises user domExcep[tion - WRONG_DOCUMENT_ERR 1939: @raises user domException - INUSE_ATTRIBUTE_ERR 1940: 1941: To add a new attribute node with a qualified name and namespace URI, use the setAttributeNodeNS method. 1942: */ 1943: ::method setAttributeNode 1944: use strict arg newAttr 1945: if newAttr~ownerDocument<>self~ownerDocument then do 1946: raise user domException additional (.domException~wrong_document_err) description ("Attribute" newAttr~name "is owned by another document") 1947: end 1948: if newAttr~ownerElement<>self then do 1949: raise user domException additional (.domException~inuse_attribute_err) description (newAttr~ownerElement) 1950: end 1951: node = self~attributes~setNamedItem(newAttr) 1952: return node 1953: /** 1954: Adds a new attribute. If an attribute with that local name and that namespace URI is already present in the element, 1955: it is replaced by the new one. Replacing an attribute node by itself has no effect. 1956: @param newAttr - The xmlAttr node to add to the attribute list. 1957: @return attr - If the newAttr attribute replaces an existing attribute, the replaced Attr node is returned, otherwise 1958: .nil is returned. 1959: @raises user domExcep[tion - WRONG_DOCUMENT_ERR 1960: @raises user domException - INUSE_ATTRIBUTE_ERR 1961: 1962: Per [XML Namespaces], applications must use the value .nil as the namespaceURI parameter for methods if they 1963: wish to have no namespace. 1964: */ 1965: ::method setAttributeNodeNS 1966: use strict arg newAttr 1967: node = self~attributes~setNamedItemNS(newAttr) 1968: return node 1969: /** 1970: If the parameter isId is true, this method declares the specified attribute to be a user-determined ID attribute. This 1971: affects the value of the xmlAttr isId meyhod and the behavior of the xmlDocument getElementById method, 1972: but does not change any schema that may be in use, in particular this does not affect the the xmlAttr 1973: schemaTypeInfo property of the specified xmlAttr node. 1974: Use the value .false for the parameter isId to undeclare an attribute for being a user-determined ID attribute. 1975: @param name - The name of the attribute. 1976: @param isId - Whether the attribute is a of type ID. 1977: @raises user domException - NOT_FOUND_ERR 1978: 1979: To specify an attribute by local name and namespace URI, use the setIdAttributeNS method. 1980: */ 1981: ::method setIdAttribute 1982: use strict arg name, isId 1983: node = self~attributes~getNamedItem(name) 1984: if node==.nil then do 1985: raise user domException description (.domException~not_found_err) 1986: end 1987: node~isId = isId 1988: return 1989: /** 1990: If the parameter isId is true, this method declares the specified attribute to be a user-determined ID attribute. This 1991: affects the value of the xmlAttr isId meyhod and the behavior of the xmlDocument getElementById method, 1992: but does not change any schema that may be in use, in particular this does not affect the the xmlAttr 1993: schemaTypeInfo property of the specified xmlAttr node. 1994: Use the value .false for the parameter isId to undeclare an attribute for being a user-determined ID attribute. 1995: @param namespaceURI - The namespace URI of the attribute. 1996: @param localName - The local name of the attribute. 1997: @param isId - Whether the attribute is a of type ID. 1998: @raises user domException - NOT_FOUND_ERR 1999: */ 2000: ::method setIdAttributeNS 2001: use strict arg namespaceURI, localName, isId 2002: node = self~attributes~getNamedItemNS(namespaceURI, localName) 2003: if node==.nil then do 2004: raise user domException description (.domException~not_found_err) 2005: end 2006: node~isId = isId 2007: return 2008: /** 2009: If the parameter isId is true, this method declares the specified attribute to be a user-determined ID attribute. This 2010: affects the value of the xmlAttr isId meyhod and the behavior of the xmlDocument getElementById method, 2011: but does not change any schema that may be in use, in particular this does not affect the the xmlAttr 2012: schemaTypeInfo property of the specified xmlAttr node. 2013: Use the value .false for the parameter isId to undeclare an attribute for being a user-determined ID attribute. 2014: @param idAttr - 2015: @param isId - 2016: @raises user domException - NOT_FOUND_ERR 2017: */ 2018: ::method setIdAttributeNode 2019: use strict arg idAttr, isId 2020: if idAttr~ownerElement<>self then do 2021: raise user domException description(.domException~not_found_err) 2022: end 2023: idAttr~isId = isId 2024: return 2025: /* :end */ 2026: 2027: /* CLASS: xmlDocument */ 2028: /** 2029: The xmlDocument interface represents the entire HTML or XML document. Conceptually, it is the root of the document 2030: tree, and provides the primary access to the document's data. 2031: 2032: Since elements, text nodes, comments, processing instructions, etc. cannot exist outside the context of a Document, 2033: the xmlDocument interface also contains the factory methods needed to create these objects. The xmlNode objects 2034: created have a ownerDocument attribute which associates them with the Document within whose context they were created. 2035: */ 2036: ::class xmlDocument public subclass xmlNode 2037: /** 2038: A directory with elementIds as index and the associated xmlElement as item. 2039: */ 2040: ::attribute elementIds private 2041: /** 2042: A directory with tagNames as index and an array of xmlElement objects with the tagName as objects 2043: */ 2044: ::attribute elementTags private 2045: /** 2046: A directory with namespaceURIs as index and their prefix as item 2047: */ 2048: ::attribute nameSpaces private 2049: /** 2050: The Document Type Declaration (see DocumentType) associated with this document. For XML documents without a document 2051: type declaration this returns .nil. For HTML documents, a DocumentType object may be returned, independently of 2052: the presence or absence of document type declaration in the HTML document. 2053: 2054: This provides direct access to the xmlDocumentType node, child node of this xmlDocument. This node can be set a 2055: t document creation time and later changed through the use of child nodes manipulation methods, such as xmlNode's 2056: insertBefore, or xmlNode's replaceChild. 2057: 2058: Note, however, that while some implementations may instantiate different types of Document objects supporting 2059: additional features than the "Core", such as "HTML" [DOM Level 2 HTML], based on the xmlDocumentType specified at 2060: creation time, changing it afterwards is very unlikely to result in a change of the features supported. 2061: */ 2062: ::attribute docType get 2063: /** 2064: */ 2065: ::attribute docType set 2066: /** 2067: This is a convenience attribute that allows direct access to the child node that is the document element of 2068: the document. 2069: */ 2070: ::attribute documentElement get 2071: /** 2072: */ 2073: ::attribute documentElement set 2074: /** 2075: The location of the document or .nil if undefined or if the Document was created using xmlDOMImplementation 2076: createDocument. No lexical checking is performed when setting this attribute; this could result in a 2077: .nil value returned when using xmlNode baseURI. 2078: 2079: Beware that when the Document supports the feature "HTML" [DOM Level 2 HTML], the href attribute of the HTML BASE 2080: element takes precedence over this attribute when computing xmlNode baseURI. 2081: */ 2082: ::attribute documentURI 2083: /** 2084: The configuration used when xmlDocument normalizeDocument is invoked. 2085: */ 2086: ::attribute domConfig get 2087: /** 2088: */ 2089: ::attribute domConfig set 2090: /** 2091: The xmlDOMImplementation object that handles this document. A DOM application may use objects from multiple 2092: implementations. 2093: The attributes setter method ("IMPLEMENTATION=") starts out as public and is set to private once set 2094: turning the attribute into a read-only. 2095: */ 2096: ::attribute implementation get 2097: ::attribute implementation set 2098: /** 2099: An attribute specifying the encoding used for this document at the time of the parsing. This is null when it is not 2100: known, such as when the xmlDocument was created in memory. 2101: */ 2102: ::attribute inputEncoding get 2103: ::attribute inputEncoding set 2104: /** 2105: An attribute specifying whether error checking is enforced or not. When set to .false, the implementation is 2106: free to not test every possible error case normally defined on DOM operations, and not raise any xmlDOMException on 2107: DOM operations or report errors while using xmlDocument normalizeDocument. In case of error, the behavior is 2108: undefined. This attribute is true by default. 2109: */ 2110: ::attribute strictErrorChecking 2111: /** 2112: An attribute specifying, as part of the XML declaration, the encoding of this document. This is .nil when 2113: unspecified or when it is not known, such as when the Document was created in memory. 2114: */ 2115: ::attribute xmlEncoding 2116: /** 2117: An attribute specifying, as part of the XML declaration, whether this document is standalone. This is .false 2118: when unspecified. 2119: 2120: Note: No verification is done on the value when setting this attribute. Applications should use xmlDocument 2121: normalizeDocument with the "validate" parameter to verify if the value matches the validity constraint for 2122: standalone document declaration as defined in [XML 1.0]. 2123: */ 2124: ::attribute xmlStandalone 2125: /** 2126: An attribute specifying, as part of the XML declaration, the version number of this document. If there is no 2127: declaration and if this document supports the "XML" feature, the value is "1.0". If this document does not support the 2128: "XML" feature, the value is always null. Changing this attribute will affect methods that check for invalid characters 2129: in XML names. Application should invoke xmlDocument normalizeDocument in order to check for invalid characters 2130: in the Nodes that are already part of this Document. 2131: 2132: DOM applications may use the xmlDOMImplementation hasFeature(feature, version) method with parameter values 2133: "XMLVersion" and "1.0" (respectively) to determine if an implementation supports [XML 1.0]. DOM applications may use 2134: the same method with parameter values "XMLVersion" and "1.1" (respectively) to determine if an implementation supports 2135: [XML 1.1]. In both cases, in order to support XML, an implementation must also support the "XML" feature defined in 2136: this specification. Document objects supporting a version of the "XMLVersion" feature must not raise a 2137: NOT_SUPPORTED_ERR exception for the same version number when using xmlDocument xmlVersion. 2138: 2139: @raises user domException - NOT_SUPPORTED_ERR 2140: 2141: Raised if the version is set to a value that is not supported by this Document or if this document does not support 2142: the "XML" feature. 2143: */ 2144: ::attribute xmlVersion 2145: /** 2146: xmlDocument instance constructor 2147: */ 2148: ::method init 2149: -- public attributes 2150: self~init:super 2151: self~nodeType = .xmlNode~documentNode 2152: self~nodeName = "#document" 2153: self~nodeValue = .nil 2154: self~attributes = .nil 2155: self~parentNode = .nil 2156: self~previousSibling = .nil 2157: self~nextSibling = .nil 2158: self~ownerDocument = .nil 2159: --self~docType = .nil same as implementation 2160: --self~implementation = .xmlDomImplementation~new -- This one is set by .xmlDomImplementation createDocument method 2161: -- private attributes 2162: self~elementIds = .directory~new 2163: self~elementTags = .directory~new 2164: self~nameSpaces = .directory~new 2165: return 2166: /** 2167: Attempts to adopt a node from another document to this document. If supported, it changes the ownerDocument of the 2168: source node, its children, as well as the attached attribute nodes if there are any. If the source node has a parent 2169: it is first removed from the child list of its parent. This effectively allows moving a subtree from one document to 2170: another (unlike importNode which create a copy of the source node instead of moving it). When it fails, 2171: applications should use xmlDocument importNode instead. 2172: 2173: Note that if the adopted node is already part of this document (i.e. the source and target document are the same), 2174: this method still has the effect of removing the source node from the child list of its parent, if any. The following 2175: list describes the specifics for each type of node. 2176:
      2177:
    • ATTRIBUTE_NODE - The ownerElement attribute is set to null and the specified flag is set to true on the adopted 2178: xmlAttr. The descendants of the source xmlAttr are recursively adopted.
    • 2179:
    • DOCUMENT_FRAGMENT_NODE - The descendants of the source node are recursively adopted.
    • 2180:
    • DOCUMENT_NODE - Document nodes cannot be adopted.
    • 2181:
    • DOCUMENT_TYPE_NODE - DocumentType nodes cannot be adopted.
    • 2182:
    • ELEMENT_NODE - Specified attribute nodes of the source element are adopted. Default attributes are discarded, 2183: though if the document being adopted into defines default attributes for this element name, those are assigned. The 2184: descendants of the source element are recursively adopted.
    • 2185:
    • ENTITY_NODE - Entity nodes cannot be adopted.
    • 2186:
    • ENTITY_REFERENCE_NODE - Only the EntityReference node itself is adopted, the descendants are discarded, since the 2187: source and destination documents might have defined the entity differently. If the document being imported into 2188: provides a definition for this entity name, its value is assigned.
    • 2189:
    • NOTATION_NODE - Notation nodes cannot be adopted.
    • 2190:
    • PROCESSING_INSTRUCTION_NODE, TEXT_NODE, CDATA_SECTION_NODE, COMMENT_NODE - These nodes can all be adopted. No 2191: specifics.
    • 2192:
    2193: 2194: Note: Since it does not create new nodes unlike the xmlDocument importNode method, this method does not raise 2195: an INVALID_CHARACTER_ERR exception, and applications should use the xmlDocument normalizeDocument method to 2196: check if an imported name is not an XML name according to the XML version in use. 2197: @param source - The xmlNode to move into this document. 2198: @return node - The adopted node, or .nil if this operation fails, such as when the source node comes from a 2199: different implementation. 2200: */ 2201: ::method adoptNode 2202: use strict arg source 2203: raise syntax 93.900 array (isUnderConstruction(.context~name)) 2204: return 2205: /** 2206: Creates an xmlAttr of the given name. Note that the xmlAttr instance can then be set on an xmlElement using the 2207: setAttributeNode method. 2208: The new xmlAttr has the nodeName attribute set to name, and localName, prefix, and 2209: namespaceURI set to null. The value of the attribute is the empty string. 2210: @param name - The name of the attribute. 2211: @param value=.nil - The (optional) value of the attribute 2212: @return attr - A new Attr object 2213: @raises user domException - INVALID_CHARACTER_ERR 2214: 2215: Raised if the specified name is not an XML name according to the XML version in use specified in the xmlDocument 2216: xmlVersion attribute. 2217: To create an attribute with a qualified name and namespace URI, use the createAttributeNS method. 2218: */ 2219: ::method createAttribute 2220: use strict arg name, value=.nil 2221: if name~verify(xmlValidName())>0 2222: then raise user domException description (.domException~invalid_character_err) 2223: attr = .xmlAttr~new 2224: --attr~name = name 2225: attr~nodeName = name 2226: attr~localName = .nil 2227: attr~prefix = .nil 2228: attr~namespaceURI = .nil 2229: attr~nodeValue = value 2230: --attr~value = .nil 2231: attr~ownerDocument = self 2232: return attr 2233: /** 2234: Creates an attribute of the given qualified name and namespace URI. 2235: @param namespaceURI=.nil - The optional namespace URI of the attribute to create. 2236: @param qualifiedName - The qualified name of the attribute to instantiate. 2237: @return attr - A new xmlAttr object with the following attributes: 2238: 2239:
      2240:
    • nodeName - The specified qualifiedName.
    • 2241:
    • namespaceURI - The specified namespaceURI.
    • 2242:
    • prefix - prefix, extracted from qualifiedName, or null if there is no prefix.
    • 2243:
    • localName - name, extracted from the specified qualifiedName.
    • 2244:
    • name - The specified qualifiedName.
    • 2245:
    • nodeValue - An empty string (i.e. "").
    • 2246:
    2247: @raises user domException - INVALID_CHARACTER_ERR 2248: @raises user domException - NAMESPACE_ERR 2249: 2250: Per [XML Namespaces], applications must use the value null as the namespaceURI parameter for methods if they wish to 2251: have no namespace. 2252: */ 2253: ::method createAttributeNS 2254: use strict arg namespaceURI=.nil, qualifiedName 2255: if qualifiedName~verify(xmlValidName())>0 2256: then raise user domException description (.domException~invalid_character_err) 2257: exception = .false 2258: if qualifiedName~countStr(':')>1 then exception = .true 2259: prefix = '' 2260: localName = qualifiedName 2261: if qualifiedName~countStr(':')==1 then do 2262: parse var qualifiedName prefix ':' localName 2263: if prefix=='XML' & namesapceURI<>"http://www.w3.org/XML/1998/namespace" then exception = .true 2264: -- 2 more conditions to check, will be todo 2265: end 2266: if exception==.true then raise user domException description (.domException~namespace_err) 2267: attr = .xmlAttr~new 2268: attr~ nodeName = qualifiedName 2269: attr~namespaceURI = namespaceURI 2270: attr~prefix = prefix 2271: attr~localName = localName 2272: attr~name = qualifiedName 2273: attr~nodeValue = '' 2274: return attr 2275: /** 2276: Creates a xmlCDATASection node whose value is the specified string. 2277: @param data - The data for the node. 2278: @return cdata - The new xmlCDATASection object. 2279: */ 2280: ::method createCDATASection 2281: use strict arg data 2282: cdata = .xmlCDATASection~new(data) 2283: return cdata 2284: /** 2285: Creates a xmlComment node given the specified string. 2286: @param data - The data for the node 2287: @return comment - The new xmlComment object 2288: */ 2289: ::method createComment 2290: use strict arg data 2291: comment = .xmlComment~new(data) 2292: return comment 2293: /** 2294: Creates an empty DocumentFragment object. 2295: @return docFragment - The newly created empty xmlDocumentFragment 2296: */ 2297: ::method createDocumentFragment 2298: use strict arg 2299: docFragment = .xmlDocumentFragment~new 2300: return docFragment 2301: /** 2302: Creates an element of the type specified. Note that the instance returned implements the Element interface, so 2303: attributes can be specified directly on the returned object. The new xmlElement object will have the nodeName 2304: attribute set to tagName, and localName, prefix, and namespaceURI set to null. 2305: @param tagName - The name(case-sensitive for XML) of the element type to instantiate. 2306: 2307: NOT YET!!!!! 2308: In addition, if there are known attributes with default values, xmlAttr nodes representing them are automatically 2309: created and attached to the element. 2310: @return element - A new xmlElement as described above. 2311: @raises user domExceptuion - INVALID_CHARACTER_ERR 2312: 2313: To create an element with a qualified name and namespace URI, use the createElementNS method. 2314: */ 2315: ::method createElement 2316: use strict arg tagName 2317: if tagName~verify(xmlValidName())>0 2318: then raise user domException description (.domException~invalid_character_err) 2319: element = .xmlElement~new(tagName) 2320: element~ownerDocument = self 2321: --if self~elementTags[tagName]==.nil then self~elementTags[tagName] = .xmlNodelist~new 2322: --self~elementTags[tagName]~append(element) 2323: return element 2324: /** 2325: Creates an element of the given qualified name and namespace URI. 2326: @param namespaceURI=.nil - The optional namespace URI of the element to create. 2327: @param qualifiedName - The qualified name of the element type to instantiate. 2328: @return attr - A new xmlAttr object with the following attributes: 2329: 2330:
      2331:
    • nodeName - The specified qualifiedName.
    • 2332:
    • namespaceURI - The specified namespaceURI.
    • 2333:
    • prefix - prefix, extracted from qualifiedName, or null if there is no prefix.
    • 2334:
    • localName - name, extracted from the specified qualifiedName.
    • 2335:
    • tagName - The specified qualifiedName.
    • 2336:
    2337: @raises user domException - INVALID_CHARACTER_ERR 2338: @raises user domException - NAMESPACE_ERR 2339: 2340: 2341: Per [XML Namespaces], applications must use the value null as the namespaceURI parameter for methods if they wish to 2342: have no namespace. 2343: */ 2344: ::method createElementNS 2345: use strict arg namespaceURI=.nil, qualifiedName 2346: if qualifiedName~verify(xmlValidName())>0 2347: then raise user domException description (.domException~invalid_character_err) 2348: exception = .false 2349: if qualifiedName~countStr(':')>1 then exception = .true 2350: prefix = '' 2351: localName = qualifiedName 2352: if qualifiedName~countStr(':')==1 then do 2353: parse var qualifiedName prefix ':' localName 2354: if prefix=='XML' & namesapceURI<>"http://www.w3.org/XML/1998/namespace" then exception = .true 2355: -- more conditions to check, will be todo 2356: end 2357: if exception==.true then raise user domException description (.domException~namespace_err) 2358: element = .xmlElement~new 2359: element~nodeName = qualifiedName 2360: element~namespaceURI = namespaceURI 2361: element~prefix = prefix 2362: element~localName = localName 2363: element~tagName = qualifiedName 2364: return element 2365: /** 2366: Creates a xmlEntityReference object. In addition, if the referenced entity is known, the child list of the 2367: xmlEntityReference node is made the same as that of the corresponding xmlEntity node. 2368: @param name - The name of the reference 2369: 2370: Note: If any descendant of the Entity node has an unbound namespace prefix, the corresponding descendant of the 2371: created EntityReference node is also unbound; (its namespaceURI is null). The DOM Level 2 and 3 do not support any 2372: mechanism to resolve namespace prefixes in this case. 2373: */ 2374: ::method createEntityReference 2375: use strict arg name 2376: raise syntax 93.900 array (isUnderConstruction(.context~name)) 2377: return 2378: /** 2379: Creates a xmlProcessingInstruction node given the specified target and data strings. 2380: @param target - The target part of the processing instruction 2381: @param data - The data for the node 2382: @return pi - The new xmlProcessingInstruction object 2383: @raises user domException - INVALID_CHARACTER_ERR 2384: */ 2385: ::method createProcessingInstruction 2386: use strict arg target, data 2387: if target~verify(xmlValidName())>0 2388: then raise user domException description (.domException~invalid_character_err) 2389: pi = .xmlPI~new(target, data) 2390: return pi 2391: /** 2392: Creates a xmlText node given the specified string. 2393: @param data - The data for the node 2394: @return text - The new xmlText object 2395: */ 2396: ::method createTextNode 2397: use arg data 2398: text = .xmlText~new(data) 2399: return text 2400: /** 2401: Returns the xmlElement that has an ID attribute with the given value. If no such element exists, this returns null. If 2402: more than one element has an ID attribute with that value, what is returned is undefined. 2403: 2404: NOTE - Attributes with the name "ID" or "id" are not of type ID unless so defined. 2405: 2406: @param elementId - The unique id value for an element. 2407: @return element - The matching element or .nil if there is none. 2408: 2409: The DOM implementation is expected to use the attribute Attr~isId to determine if an attribute is of type ID. 2410: */ 2411: ::method getElementById 2412: use strict arg elementId 2413: element = self~elementIds[elementId] 2414: return element 2415: /** 2416: Returns a xmlNodeList of all the xmlElements in document order with a given tag name and are within in the document. 2417: @param tagName - The name of the tag to match on. The special value "*" matches all tags. 2418: @return nodeList - A new xmlNodeList object containing all the matched xmlElements. 2419: 2420: For XML, the tagname parameter is case-sensitive, otherwise it depends on the case-sensitivity of the markup language 2421: in use. 2422: */ 2423: ::method getElementsByTagName 2424: use strict arg tagName 2425: elements = .xmlNodeList~new 2426: self~selectElements(self~childNodes, tagName, elements) 2427: return elements 2428: /** 2429: Private method to walk the nodes tree and retrieve nodes by tagName 2430: @param nodes - The sibling nodes to walk thru. 2431: @param tag - The name of the tag to select on. 2432: @param nodelist - The xmlNodeList to append selected nodes to. 2433: */ 2434: ::method selectElements private 2435: use strict arg nodes, tag, nodelist 2436: do n=0 to nodes~length-1 2437: node = nodes~item(n) 2438: if (node~nodeType==.xmlNode~elementNode) then do 2439: if tag<>'*' then do 2440: if (node~tagName==tag) then nodelist~append(node) 2441: end 2442: else do 2443: nodelist~append(node) 2444: end 2445: if (node~childNodes~length>0) then do 2446: self~selectElements(node~childNodes, tag, nodelist) 2447: end 2448: end 2449: end 2450: return 2451: /** 2452: Returns a xmlNodeList of all the xmlElements with a given local name and namespace URI in document order. 2453: @param namespaceURI=.nil - The namespace URI of the elements to match on. The special value "*" matches all namespaces. 2454: @param localName - The local name of the elements to match on. The special value "*" matches all local names. 2455: @return nodeList - A new xmlNodeList containing all the matched xmlElements. 2456: */ 2457: ::method getElementsByTagNameNS 2458: use strict arg namespaceURI=.nil, localName 2459: raise syntax 93.900 array (isUnderConstruction(.context~name)) 2460: return 2461: /** 2462: Imports a node from another document to this document, without altering or removing the source node from the original 2463: document; this method creates a new copy of the source node. The returned node has no parent; (parentNode is null). 2464: 2465: For all nodes, importing a node creates a node object owned by the importing document, with attribute values identical 2466: to the source node's nodeName and nodeType, plus the attributes related to namespaces (prefix, localName, and 2467: namespaceURI). As in the cloneNode operation, the source node is not altered. User data associated to the imported 2468: node is not carried over. However, if any UserDataHandlers has been specified along with the associated data these 2469: handlers will be called with the appropriate parameters before this method returns. 2470: 2471: Additional information is copied as appropriate to the nodeType, attempting to mirror the behavior expected if a 2472: fragment of XML or HTML source was copied from one document to another, recognizing that the two documents may have 2473: different DTDs in the XML case. 2474: 2475: The following list describes the specifics for each type of node. 2476:
      2477:
    • ATTRIBUTE_NODE - The ownerElement attribute is set to null and the specified flag is set to true on the generated 2478: xmlAttr. The descendants of the source xmlAttr are recursively imported and the resulting nodes reassembled to form 2479: the corresponding subtree. 2480: NOTE - The deep parameter has no effect on xmlAttr nodes; they always carry their children with them 2481: when imported.
    • 2482:
    • DOCUMENT_FRAGMENT_NODE - If the deep option was set to true, the descendants of the source DocumentFragment are 2483: recursively imported and the resulting nodes reassembled under the imported DocumentFragment to form the corresponding 2484: subtree. Otherwise, this simply generates an empty DocumentFragment.
    • 2485:
    • DOCUMENT_NODE - Document nodes cannot be imported.
    • 2486:
    • DOCUMENT_TYPE_NODE - DocumentType nodes cannot be imported.
    • 2487:
    • ELEMENT_NODE - Specified attribute nodes of the source element are imported, and the generated xmlAttr nodes are 2488: attached to the generated xmlElement. Default attributes are not copied, though if the document being imported into 2489: defines default attributes for this element name, those are assigned. If the importNode deep parameter was set to 2490: true, the descendants of the source element are recursively imported and the resulting nodes reassembled to form the 2491: corresponding subtree.
    • 2492:
    • ENTITY_NODE - Entity nodes can be imported, however in the current release of the DOM the xmlDocumentType is 2493: readonly. Ability to add these imported nodes to a xmlDocumentType will be considered for addition to a future release 2494: of the DOM.
    • 2495:
    • ENTITY_REFERENCE_NODE - Only the EntityReference itself is copied, even if a deep import is requested, since the 2496: source and destination documents might have defined the entity differently. If the document being imported into 2497: provides a definition for this entity name, its value is assigned.
    • 2498:
    • NOTATION_NODE - Notation nodes can be imported, however they are read-only
    • 2499:
    • PROCESSING_INSTRUCTION_NODE - The imported node copies its target and data from those of the source node.
    • 2500:
    • TEXT_NODE, CDATA_SECTION_NODE, COMMENT_NODE - These three types of nodes inheriting from xmlCharacterData copy 2501: their data and length attributes from those of the source node.
    • 2502:
    2503: @param importNode - The node to import 2504: @param deep=.false - optional boolean to indicate a deep copy 2505: @return node - the imported node that belongs to this xmlDocument now. 2506: @raises user domException - INVALID_CHARACTER_ERR 2507: */ 2508: ::method importNode 2509: use strict arg importNode, deep=.false 2510: raise syntax 93.900 array (isUnderConstruction(.context~name)) 2511: return 2512: /** 2513: This method acts as if the document was going through a save and load cycle, putting the document in a "normal" form. 2514: As a consequence, this method updates the replacement tree of EntityReference nodes and normalizes Text nodes, as 2515: defined in the method xmlNode normalize. 2516: 2517: Otherwise, the actual result depends on the features being set on the Document.domConfig object and governing what 2518: operations actually take place. Noticeably this method could also make the document namespace well-formed according to 2519: the algorithm described in Namespace Normalization, check the character normalization, remove the CDATASection nodes, 2520: etc. See DOMConfiguration for details. 2521: 2522: Mutation events, when supported, are generated to reflect the changes occurring on the document. 2523: 2524: If errors occur during the invocation of this method, such as an attempt to update a read-only node or a Node.nodeName 2525: contains an invalid character according to the XML version in use, errors or warnings (DOMError.SEVERITY_ERROR or 2526: DOMError.SEVERITY_WARNING) will be reported using the DOMErrorHandler object associated with the "error-handler" 2527: parameter. Note this method might also report fatal errors (DOMError.SEVERITY_FATAL_ERROR) if an implementation cannot 2528: recover from an error. 2529: */ 2530: ::method normalizeDocument 2531: use strict arg 2532: raise syntax 93.900 array (isUnderConstruction(.context~name)) 2533: return 2534: /** 2535: Rename an existing node of type ELEMENT_NODE or ATTRIBUTE_NODE. 2536: 2537: When possible this simply changes the name of the given node, otherwise this creates a new node with the specified 2538: name and replaces the existing node with the new node as described below. 2539: 2540: If simply changing the name of the given node is not possible, the following operations are performed: a new node is 2541: created, any registered event listener is registered on the new node, any user data attached to the old node is 2542: removed from that node, the old node is removed from its parent if it has one, the children are moved to the new node, 2543: if the renamed node is an Element its attributes are moved to the new node, the new node is inserted at the position 2544: the old node used to have in its parent's child nodes list if it has one, the user data that was attached to the old 2545: node is attached to the new node. 2546: 2547: When the node being renamed is an Element only the specified attributes are moved, default attributes originated from 2548: the DTD are updated according to the new element name. In addition, the implementation may update default attributes 2549: from other schemas. Applications should use Document.normalizeDocument() to guarantee these attributes are up-to-date. 2550: 2551: When the node being renamed is an Attr that is attached to an Element, the node is first removed from the Element 2552: attributes map. Then, once renamed, either by modifying the existing node or creating a new one as described above, it 2553: is put back. 2554: In addition: 2555:
      2556:
    • a user data event NODE_RENAMED is fired
    • 2557:
    • when the implementation supports the feature "MutationNameEvents", each mutation operation involved in this method 2558: fires the appropriate event, and in the end the event {http://www.w3.org/2001/xml-events, DOMElementNameChanged} or 2559: {http://www.w3.org/2001/xml-events, DOMAttributeNameChanged} is fired.
    • 2560: <\ul> 2561: @param node - The node to rename 2562: @param namespaceURI=.nil - The new namespace URI. 2563: @param qualifiedName - The new qualified name. 2564: @return node - The renamed node. 2565: 2566: The renamed node is either the specified node or the new node that was created to replace the specified node. 2567: 2568: @raises user domException - NOT_SUPPORTED_ERR 2569: @raises user domException - INVALID_CHARACTER_ERR 2570: @raises user domException - WRONG_DOCUMENT_ERR 2571: @raises user domException - NAMESPACE_ERR 2572: */ 2573: ::method renameNode 2574: use strict arg node, namespaceURI=.nil, qualifiedName 2575: raise syntax 93.900 array (isUnderConstruction(.context~name)) 2576: return 2577: /* :end */ 2578: 2579: /* CLASS: xmlDomImplementation */ 2580: /** 2581: The xmlDomImplementation interface provides a number of methods for performing operations that are independent of any 2582: particular instance of the document object model. 2583: */ 2584: ::class xmlDomImplementation public 2585: ::attribute features private 2586: ::method init 2587: use strict arg 2588: self~init:super 2589: self~features = .directory~new 2590: self~features["core"] = .directory~new~~putall(.array~of("",1.0,2.0)) 2591: self~features["xml"] = .directory~new~~putall(.array~of("",1.0,2.0)) 2592: self~features["ls-load"] = .directory~new~~putall(.array~of("",3.0)) 2593: return 2594: /** 2595: Creates a DOM Document object of the specified type with its document element. 2596: 2597: Note that based on the DocumentType given to create the document, the implementation may instantiate specialized 2598: Document objects that support additional features than the "Core", such as "HTML" [DOM Level 2 HTML]. On the other 2599: hand, setting the DocumentType after the document was created makes this very unlikely to happen. Alternatively, 2600: specialized Document creation methods, such as createHTMLDocument [DOM Level 2 HTML], can be used to obtain specific 2601: types of Document objects. 2602: @param namespaceURI='' - The (optional) namespace URI of the document element to create or .nil. 2603: @param qualifiedName='' - The (optional) qualified name of the document element to be created or null. 2604: @param docType=.nil - The (optional) type of document to be created or . 2605: @return document - A new xmlDocument object with its document element. 2606: @raises user - domException.INVALID_CHARACTER_ERR 2607: @raises user - domException.NAMESPACE_ERR 2608: 2609: If the namespaceURI, qualifiedName, and docType are .nil, the returned xmlDocument is empty with no document 2610: element. 2611: When docType is not .nil, its ownerDocument attribute is set to the document being created. 2612: */ 2613: ::method createDocument 2614: use strict arg namespaceURI='', qualifiedName='', docType=.nil 2615: if qualifiedName~verify(xmlValidName())>0 2616: then raise user domException description (.domException~INVALID_CHARACTER_ERR) 2617: prefix = '' 2618: localName = qualifiedName 2619: if qualifiedName~countStr(':')>1 2620: then raise user domException additional (.domException~namespace_err) description ("Qualified name can contain only one ':' character.") 2621: if qualifiedName~countStr(':')==1 then parse var qualifiedName prefix':'localName 2622: if prefix<>'' & namespaceURI=='' 2623: then raise user domException additional (.domException~NAMESPACE_ERR) description ("Cannot have a prefix without namespaceURI.") 2624: if namespaceURI<>'' & qualifiedName=='' 2625: then raise user domException additional (.domException~NAMESPACE_ERR) description ("Cannot have namespaceURI without prefix.") 2626: if prefix~upper=='XML' & namespaceURI~lower<>'http://www.w3.org/XML/1998/namespace' 2627: then raise user domException additional (.domException~NAMESPACE_ERR) description ("Invalid namespaceURI for prefix" prefix".") 2628: if docType<>.nil then do 2629: if docType~isA(.xmlDocType) then do 2630: if docType~ownerDocument<>.nil then raise user domException additional (.domException~WRONG_DOCUMENT_ERR) description ("DOCTYTPE belongs to different document.") 2631: end 2632: else raise user domException additional (.domException~SYNTAX_ERR) description ("Argument is NOT a .xmlDocType.") 2633: end 2634: --trace i 2635: document = .xmlDocument~new 2636: document~implementation = self 2637: document~prefix = prefix 2638: document~localName = localName 2639: document~namespaceURI = namespaceURI 2640: if docType<>.nil then do 2641: document~appendChild(docType) 2642: docType~ownerDocument = document 2643: end 2644: document~docType = docType 2645: --if namespaceURI<>.nil | qualifiedName<>.nil | docType<>.nil then do 2646: -- documentElement = document~createElement(qualifiedName) 2647: -- document~appendChild(documentElement) 2648: -- document~documentElement = documentElement 2649: --end 2650: return document 2651: /** 2652: Creates an empty DocumentType node. Entity declarations and notations are not made available. Entity reference 2653: expansions and default attribute additions do not occur. 2654: @param qualifiedName - The qualified name for to new document (e.g. 'gpx') 2655: @param publicId - The public identifier of this document type (e.g. '-//W3C//DTD XHTML 1.0 Strict//EN') 2656: @param systemId - The system identifier for the document type (e.g. 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd') 2657: @return node - An empty xmlDocumentType node. 2658: */ 2659: ::method createDocumentType 2660: use strict arg qualifiedName, publicId, systemId 2661: raise syntax 93.900 array (isUnderConstruction(.context~name)) 2662: return 2663: /** 2664: This method returns a specialized object which implements the specialized APIs of the specified feature and version, 2665: as specified in DOM Features. The specialized object may also be obtained by using binding-specific casting methods 2666: but is not necessarily expected to, as discussed in Mixed DOM Implementations. This method also allow the 2667: implementation to provide specialized objects which do not support the DOMImplementation interface. 2668: @param feature - The name of the feature requested. 2669: @param version - This is the version number of the feature to test. 2670: @return object - Returns a xmlDomObject or .nil. 2671: 2672: The returned xmlDomObject which implements the specialized APIs of the specified feature and version, it is 2673: .nil if there is no object which implements interfaces associated with that feature. 2674: 2675: NOTE,/b> - The DOM Level 3 Feature handler support is not currently implemented, therefore getFeature 2676: will always return .nil. 2677: */ 2678: ::method getFeature 2679: use strict arg feature, version 2680: featureHandler = .nil 2681: versions = self~features[feature~lower] 2682: if versions<>.nil then do 2683: featureHandler = versions~index(feature) 2684: end 2685: return featureHandler 2686: /** 2687: Test if the DOM implementation implements a specific feature and version, as specified in DOM Features. 2688: @param feature - The name of the feature requested. 2689: @param version='' - This is the (optional) version number of the feature to test. 2690: @return boolean - Returns .true if the feature is implemented in the specified version, .false 2691: otherwise. 2692: */ 2693: ::method hasFeature 2694: use strict arg feature, version='' 2695: versions = self~features[feature~lower] 2696: if versions<>.nil then do 2697: featureSupported = versions~index[feature~lower] 2698: end 2699: return featureSupported<>.nil 2700: /* :end */ 2701: 2702: /* CLASS: domBuilder */ 2703: /** 2704: 2705: */ 2706: ::class dom1Builder public 2707: /** 2708: The DOM (Level 1) implementation for building a DOM (Level 1) 2709: 2710: NOTE - The domImplementation is currently only used for it's createDocument method. 2711: */ 2712: ::attribute dom private 2713: /** 2714: The DOM document resulting from the XML Parser and DOM (Level 1) builder. 2715: */ 2716: ::attribute doc get 2717: ::attribute doc set private 2718: /** 2719: The stack of nested elements with childnodes. 2720: 2721: NOTE - nodeStack[1] represents the current active Element node. 2722: */ 2723: ::attribute nodeStack private 2724: /** 2725: Represents the current active Attr node 2726: */ 2727: ::attribute attrNode private 2728: /** 2729: Flag to indicate if the convenience attribute documentElement must be set or not. 2730: */ 2731: ::attribute haveDocumentElement private 2732: /** 2733: DOM Builder instance constructor 2734: 2735: NOTE - domImplementation was introduced in DOM Level2, it is used here only to create a document with no 2736: namespace and doctype. 2737: */ 2738: ::method init 2739: self~dom = .xmlDomImplementation~new 2740: self~nodeStack = .queue~new 2741: self~haveDocumentElement = .false 2742: return 2743: /** 2744: The method invoker wants to start a new DOM document. A DOM Level1 document is created with the help of the DOM Level2 2745: DomImplemetation interface. 2746: @param content=.nil - Currently ignored, if present 2747: */ 2748: ::method startDocument 2749: use strict arg content=.nil 2750: self~doc = self~dom~createDocument() 2751: self~nodeStack~push(self~doc) 2752: return 2753: /** 2754: Signals the end of DOM building process. At this stage the stack with active nodes should only have the document node 2755: as content. 2756: */ 2757: ::method endDocument 2758: use strict arg 2759: -- stack should have just 1 item now 2760: if self~nodeStack~items<>1 then do 2761: raise syntax 93.900 array ("Error in XML input") 2762: end 2763: docNode = self~nodeStack~pull 2764: return 2765: /** 2766: Start a new element node. 2767: @param tagName - the name of the tag for this element node. 2768: 2769: If this is the first element created, the convenience attribute documentElement is set. The new element node is 2770: made the currently active one after being appended as a childnode of the parentnode. 2771: */ 2772: ::method startElement 2773: use strict arg tagName 2774: elementNode = self~doc~createElement(tagName) 2775: if (self~haveDocumentElement==.false) then do 2776: self~doc~documentElement = elementNode 2777: self~haveDocumentElement = .true 2778: end 2779: self~nodeStack[1]~appendChild(elementNode) 2780: self~nodeStack~push(elementNode) 2781: return 2782: /** 2783: Finish the currently active element node. 2784: @param tagName - the name of the tag of the element being ended. 2785: @raises syntax 93.900 - Mismatch in start and ending tag. 2786: 2787: The previous elemnt node is made the active node, by removing this active node from the stack. 2788: */ 2789: ::method endElement 2790: use strict arg tagName 2791: if self~nodeStack[1]~tagName<>tagName then do 2792: raise syntax 93.900 array ("Mismatch in start:" self~nodeStack[1]~tagName "and ending tag" tagName) 2793: end 2794: -- get rid of processed node 2795: processedNode = self~nodeStack~pull 2796: return 2797: /** 2798: Handle an attribute's name 2799: @param attrName - the name part of the current element's attribute. 2800: 2801: This will create the Attr node for the attribute, no name space checking is done. 2802: */ 2803: ::method nameAttr 2804: use strict arg attrName 2805: self~attrNode = self~doc~createAttribute(attrName) 2806: return 2807: /** 2808: Handle an attibute's value. 2809: @param attrValue - the value part of the current element's attribute. 2810: 2811: Appends this Attr node to the (perhaps empty) list of attributes. Also sets the Attr's node ownerelement. 2812: */ 2813: ::method valueAttr 2814: use strict arg attrValue 2815: self~attrNode~nodeValue = attrValue 2816: self~attrNode~ownerElement = self~nodeStack[1] 2817: self~nodeStack[1]~setAttributeNode(self~attrNode) 2818: return 2819: /** 2820: Handle a Processing Instruction (PI). 2821: @param target - The target for the PI (e.g. 'xml' in '<?xml version=.......?>'. 2822: @param data - The information following the target as a string. 2823: 2824: The PInode is appended as a childnode for the currently active element node. 2825: */ 2826: ::method havePI 2827: use strict arg target, data 2828: piNode = self~doc~createProcessingInstruction(target,data) 2829: self~nodeStack[1]~appendChild(piNode) 2830: return 2831: /** 2832: Handle a Comment. 2833: @param comment - The string representing the comment 2834: 2835: No validity checking is done on the comment's content. The comment node is appended as a childnode for the active 2836: element node. 2837: */ 2838: ::method haveComment 2839: use strict arg comment 2840: cmtNode = self~doc~createComment(comment) 2841: self~nodeStack[1]~appendChild(cmtNode) 2842: return 2843: /** 2844: Handle a Text node. 2845: @param text - the (inner) text of the node with entities resolved. 2846: 2847: The text node is appended as a childnode for the active element node. 2848: */ 2849: ::method haveText 2850: use strict arg text 2851: txtNode = self~doc~createTextNode(text) 2852: self~nodeStack[1]~appendChild(txtNode) 2853: return 2854: /** 2855: Handle CDATA. 2856: @param cdata - The raw (unparsed) text for the CDATASection node. 2857: 2858: The CDATA node is appended as a childnode for the currently active element node 2859: */ 2860: ::method haveCDATA 2861: use strict arg cdata 2862: cdataNode = self~doc~createCDATASection(cdata) 2863: self~nodeStack[1]~appendChild(cdataNode) 2864: return 2865: /* :end */ 2866: 2867: /* CLASS: xmlParser */ 2868: /** 2869: A non-validating simple XML parser. The parser recognizes the following: 2870:
        2871:
      • Document start, when a XML file has been stringified and when the parseSting method has accepted the 2872: string.
      • 2873:
      • XML Comments, no test for not allowed comment nesting.
      • 2874:
      • Removable White Space is removed when encountered.
      • 2875:
      • Processing Instructions (PI's), split into target (e.g. xml in <?xml version....?>) and data.
      • 2876:
      • CDATA with it's raw unparsed text.
      • 2877:
      • Attribute only tags, with their parsed, but without namespace checking, attributes.
      • 2878:
      • Tags with atributes as above and their parsed (i.e. resolved entities) text content.
      • 2879:
      • Document end, when the end of the XML string has been reached.
      • 2880:
      2881: */ 2882: ::class xmlParser public 2883: /** 2884: The DOM builder given as parameter at instance creation time 2885: */ 2886: ::attribute domBuilder private 2887: /** 2888: The xmlParser constructor. 2889: @param domBuilder - the DOM builder the parser should use 2890: */ 2891: ::method init 2892: use strict arg domBuilder 2893: self~domBuilder = domBuilder 2894: return 2895: /** 2896: Converts a XML file or stream into a string and passes the string on to parseString. 2897: @param xmlStream - An object with a supplier method 2898: @return domDocument - the DOM created from the input stream or .nil in case of errors 2899: */ 2900: ::method parseStream 2901: use strict arg xmlStream 2902: s = xmlStream~supplier 2903: xml = '' 2904: do while s~available 2905: xml ||= s~item || .endofline 2906: s~next 2907: end 2908: return self~parseString(xml) 2909: /** 2910: Analyzes the input string for situations the DOM builder wants to know about and invokes the appropiate methods for 2911: the builder to handle the situations. 2912: @param xml - the XML string to be parsed. 2913: @return domDocument - the DOM created by the builder or .nil in case of errors. 2914: */ 2915: ::method parseString 2916: use strict arg xml 2917: self~domBuilder~startDocument 2918: do while (xml~pos('>')>0) 2919: tagEnd = xml~pos('>') 2920: -- check comment first cause it can appear anywhere 2921: cmtStart = xml~pos("" +3 xml 2925: -- repair comment xml 2926: tag = "" 2927: end 2928: else do 2929: -- there could be (element) content in front of the tag(= '<') 2930: parse var xml text '<' tagContent '>' +1 xml 2931: -- repair tag xml 2932: tag = '<'tagContent'>' 2933: end 2934: -- if there is text it is the content for an element 2935: if (text<>'') then do 2936: -- if it is not ignorable whitespace 2937: if self~removeIgnorableWhiteSpace(text)<>'' 2938: then self~domBuilder~haveText(self~resolveEntities(text)) 2939: else text = '' 2940: end 2941: -- now handle the tag 2942: select 2943: when (tag~pos("" 2946: self~domBuilder~haveComment(comment) 2947: end 2948: when (tag~pos("0) then do 2949: -- this is a processing instruction (e.g. <?xml version=....?>) 2950: parse var tag "" 2951: self~domBuilder~havePI(target, data) 2952: end 2953: when (tag~pos("0) then do 2954: -- there is unparsed (raw) text 2955: parse var tag "" 2956: self~domBuilder~haveCDATA(rawText) 2957: end 2958: when (tag~pos("/>")>0) then do 2959: -- there is a complete element 2960: parse var tag '<' tagName attributes "/>" 2961: self~domBuilder~startElement(tagName) 2962: -- handle attributes if any 2963: self~parseAttributes(self~removeIgnorableWhiteSpace(attributes)) 2964: self~domBuilder~endElement(tagName) 2965: end 2966: when (tag~pos("0) then do 2967: -- this is an element ending tag 2968: parse var tag "' 2969: self~domBuilder~endElement(tagName) 2970: end 2971: otherwise do 2972: -- must be a element starting tag 2973: parse var tag '<' tagName attributes '>' 2974: self~domBuilder~startElement(tagName) 2975: -- handle attributes if any 2976: self~parseAttributes(self~removeIgnorableWhiteSpace(attributes)) 2977: end 2978: end 2979: end 2980: self~domBuilder~endDocument 2981: return self~domBuilder~doc 2982: /** 2983: Processes the attributes specified within an element tag and passes them on the the builder. 2984: @param attributes - the string containing all the attributes specifications within an element tag. 2985: */ 2986: ::method parseAttributes private 2987: use strict arg attributes 2988: attributes = attributes~strip 2989: do while (attributes<>'') 2990: parse var attributes attrName '=' rest 2991: aposPos = rest~pos("'") 2992: quotPos = rest~pos('"') 2993: select 2994: when (quotPos=0) then delimiter = "'" 2995: when (aposPos=0) then delimiter = '"' 2996: when (aposPosNOTE
      - As DOCTYPE is not supported (yet) no DOCTYPE defined entities are handled. 3019: */ 3020: ::method resolveEntities private 3021: use strict arg text 3022: text = text~changeStr("<",'<') 3023: text = text~changeStr(">",'>') 3024: text = text~changeStr("&",'&') 3025: text = text~changeStr("'","'") 3026: text = text~changeStr(""",'"') 3027: return text 3028: /* :end */ 3029: 3030: 3031: 3032: 3033:
All content © Ruurd Idenburg, 2007–2025, except where marked otherwise. All rights reserved. This page is primarily for non-commercial use only. The Idenburg website records no personal information and sets no ‘cookies’. This site is hosted on my on server at my home, falling under Dutch (privacy) laws.

This page updated on Wed, 28 May 2025 10:38:18 +0200.