xmlDOM.cls source

00001 /**
00002   **********************************************************************
00003  
00004   Copyright (c) 2011-2015 Ruurd J. Idenburg. All rights reserved.                                             
00005  
00006   This program and the accompanying materials are made available under
00007   the terms of the Common Public License v1.0 which accompanies this
00008   distribution. A copy is also available at the following address:
00009  
00010   http://www.opensource.org/licenses/cpl1.0.php                         
00011  
00012   Redistribution and use in source and binary forms, with or without
00013   modification, are permitted provided that the following conditions
00014   are met:                                                              
00015  
00016   Redistributions of source code must retain the above copyright
00017   notice, this list of conditions and the following disclaimer.         
00018  
00019   Redistributions in binary form must reproduce the above copyright
00020   notice, this list of conditions and the following disclaimer in the
00021   documentation and/or other materials provided with the distribution.  
00022  
00023   Neither the name or trademarks of Ruurd J. Idenburg nor the names
00024   of any  contributors may be used to endorse or promote products
00025   derived from this software without specific prior written permission. 
00026  
00027   DISCLAIMER                                                            
00028  
00029   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00030   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00031   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00032   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00033   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00034   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00035   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00036   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00037   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00038   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00039   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00040  
00041   ********************************************************************** 
00042 */
00043 /* CLASS: xmlUtil */
00044 /**
00045   xmlDom basic types and other useful things
00046 */
00047  
00048 /**
00049   XML name valid characters. For (oo)Rexx, which only supports ASCII at the moment the valid range is alpha (lower and
00050   upper) and digits, plus '.', '-', '_' and' :' (this last one for qualified names (i.e. namespace:tag)). 
00051   @return valid - A string containing the valid characters for a XML name
00052 */
00053 ::routine xmlValidName public
00054 valid = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-_:'
00055 return valid
00056 /**
00057   Generates a "under construction" message for things not yet operational.
00058   @param name - The name of the thing the message is about
00059   @return message - The message text
00060 */
00061 ::routine isUnderConstruction public
00062   use strict arg name
00063   message = name "is currently under construction!"
00064 return message 
00065 /**
00066   xmlDomString is a subclass of String, for the time being without any modifications.
00067 */  
00068 ::class xmlDomString public subclass string
00069 /**
00070   xmlDomTimeStamp represents a number of milliseconds
00071 */
00072 ::class xmlDomTimeStamp public subclass string
00073 /**
00074   xmlDomUserData represents a reference to application data.
00075 */
00076 ::class xmlDomUserData public
00077 /**
00078   xmlDomObject represents an object reference. 
00079 */
00080 ::class xmlDomObject public
00081  
00082 /**
00083   domExceptions and their codes.
00084  
00085   DOM operations only raise exceptions in "exceptional" circumstances, i.e., when an operation is impossible to perform
00086   (either for logical reasons, because data is lost, or because the implementation has become unstable). In general, DOM
00087   methods return specific error values in ordinary processing situations, such as out-of-bound errors when using 
00088   NodeList.
00089  
00090   Implementations should raise other exceptions under other circumstances. For example, implementations should raise an 
00091   implementation-dependent exception if a <b>.nil</b> argument is passed when null was not expected.
00092  
00093   Some languages and object systems do not support the concept of exceptions. For such systems, error conditions may be
00094   indicated using native error reporting mechanisms. For some bindings, for example, methods may return error codes 
00095   similar to those listed in the corresponding method descriptions. 
00096  
00097 */
00098 ::class domException public
00099 /**
00100   INDEX_SIZE_ERR - If index or size is negative, or greater than the allowed 
00101   value.
00102 */
00103 ::method index_size_err class
00104 return 1
00105 /**
00106   DOMSTRING_SIZE_ERR - If the specified range of text does not fit into a 
00107   DOMString.
00108 */
00109 ::method domstring_size_err class
00110 return 2
00111 /**
00112   HIERARCHY_REQUEST_ERR - If any Node is inserted somewhere it doesn't belong.
00113 */
00114 ::method hierarchy_request_err class
00115 return 3
00116 /**
00117   WRONG_DOCUMENT_ERR - If a Node is used in a different document than the one 
00118   that created it (that doesn't support it).
00119 */
00120 ::method wrong_document_err class
00121 return 4
00122 /**
00123   INVALID_CHARACTER_ERR - If an invalid or illegal character is specified, such 
00124   as in an XML name.
00125 */
00126 ::method invalid_character_err class
00127 return 5
00128 /**
00129   NO_DATA_ALLOWED_ERR - If data is specified for a Node which does not support 
00130   data
00131 */
00132 ::method no_data_allowed_err class
00133 return 6
00134 /**
00135  NO_MODIFICATION_ALLOWED_ERR - If an attempt is made to modify an object where 
00136  modifications are not allowed.
00137 */
00138 ::method no_modification_allowed_err class
00139 return 7
00140 /**
00141   NOT_FOUND_ERR - If an attempt is made to reference a Node in a context where 
00142   it does not exist.
00143 */
00144 ::method not_found_err class
00145 return 8
00146 /**
00147   NOT_SUPPORTED_ERR - If the implementation does not support the requested type of object or operation.
00148 */
00149 ::method not_supported_err class
00150 return 9
00151 /**
00152   INUSE_method_ERR - If an attempt is made to add an method that is already in use elsewhere.
00153 */
00154 ::method inuse_method_err class
00155 return 10
00156 /**
00157   INVALID_STATE_ERR - If an attempt is made to use an object that is not, or is no longer, usable.
00158 */
00159 ::method invalid_state_err class
00160 return 11
00161 /**
00162   SYNTAX_ERR - If an invalid or illegal string is specified.
00163 */
00164 ::method syntax_err class
00165 return 12
00166 /**
00167   INVALID_MODIFICATION_ERR - If an attempt is made to modify the type of the underlying object.
00168 */
00169 ::method invalid_modification_err class
00170 return 13
00171 /**
00172   NAMESPACE_ERR - If an attempt is made to create or change an object in a way which is incorrect with regard to
00173   namespaces.
00174 */
00175 ::method namespace_err class
00176 return 14
00177 /**
00178  INVALID_ACCESS_ERR - If a parameter or an operation is not supported by the underlying object.
00179 */
00180 ::method invalid_access_err class
00181 return 15
00182 /**
00183   VALIDATION_ERR - If a call to a method such as insertBefore or removeChild would make the Node invalid with respect to
00184   "partial validity", this exception would be raised and the operation would not be done. This code is used in [DOM 
00185   Level 3 Validation]. Refer to this specification for further information.
00186 */
00187 ::method validation_err class
00188 return 16
00189 /**
00190   TYPE_MISMATCH_ERR - If the type of an object is incompatible with the expected type of the parameter associated to the
00191   object. 
00192 */
00193 ::method type_mismatch_err class
00194 return 17
00195 /* :end */
00196  
00197 /* CLASS: xmlNodeList */ 
00198 /**
00199   The xmlNodeList interface provides the abstraction of an ordered collection of xmlNodes, without defining or 
00200   constraining how this collection is implemented. xmlNodeList objects in the DOM are live.
00201  
00202   For this ooRexx implementation a xmlNodeLIst is defined as a resticted array, whose members must be an instance of
00203   xmLNode.
00204  
00205   The items in the xmlNodeList are accessible via an integral index, starting from 0. 
00206 */
00207 ::class xmlNodeList public 
00208 /**
00209   Provide the number of xmlNodes in the xmlNodeList.
00210   @return count - The number of items (xmlNodes) in the xmlNodeList.
00211 */
00212 ::method length 
00213 return self~nodeList~items
00214 /**
00215   The nodeList array can only be set by the xmlNodeList self
00216 */
00217 ::attribute nodeList get
00218 ::attribute nodeList set
00219 /**
00220   xmlNodeList instance constructor.
00221  
00222   As the creation of the xmlNodeList is left to the implementer, for ooRexx the constructor expects to get the
00223   representation of the complete xmlNodeList as an ooRexx array.
00224   @param nodeList=(.array~new) - an ooRexx array of xmlNodes.
00225 */
00226 ::method init
00227   use strict arg nodeList=(.array~new)
00228   if \nodeList~isA(.array) 
00229     then raise syntax 93.914 array (nodeList, .Array)
00230   self~nodeList = nodeList
00231 exit
00232 /**
00233   Retrieve the xmlNode at index position.
00234   @param index - The index (base 0) of the wanted Node. 
00235   @return node - The xmlNode at the index in the xmlNodeList, or <b>.nil</b> if not a valid index.
00236 */
00237 ::method item 
00238   use strict arg index
00239   node = .nil
00240   if index>=0 
00241     then node = self~nodeList[index+1]
00242 return node
00243 /**
00244   Add a xmlNode to the xmlNodeList.
00245   @param node - The xmlNode to be added to the xmlNodeList.
00246   @raises user domException - HIERARCHY_REQUEST_ERR
00247  
00248 */
00249 ::method append
00250   use strict arg node
00251   if \node~isA(.xmlNode)
00252     then raise syntax 88.914 array (node, .xmlNode)
00253   self~nodeList~append(node)
00254 return
00255 /**
00256   Removes a xmlNode from the xmlNodeList.
00257   @param node - The xmlNode to be removed.
00258   @return node - The removed xmlNode or <b>.nil</b>, if not present.
00259  
00260   Note: On hold for possible future use
00261 */
00262 ::method remove private protected
00263   use strict arg node
00264   node = self~nodelist~remove(node)
00265 return node
00266 /**
00267   @return array - A native ooRexx array representing the xmlNodeList.
00268 */
00269 ::method toOorexxArray
00270 return self~nodeList
00271 /**
00272   Sets the xmlNodeList from a native ooRexx array.
00273   @param nodeArray - the native ooRexx array to replace an existing xmlNodeList.
00274 */
00275 ::method fromOorexxArray
00276   use strict arg nodeArray
00277   do i=1 to nodeArray~items
00278     if \nodeArray[i]~isA(.xmlNode)
00279       then raise syntax 88.914 array (nodeArray[i], .xmlNode)
00280   end
00281   self~nodeList = nodeArray
00282 return
00283 /* :end */
00284  
00285 /* CLASS: xmlNode */
00286 /**
00287   The <b>xmlNode</b> class is the base class for real nodetypes such as <i>elementNode</i> and <i>textNode</i>. 
00288  
00289   Methods that make no sense or that are just plain impossible to implement in this base class, because the
00290   implementation is only possible in a subclass will raise syntax error 93.963 - Unsupported or not implented method.
00291  
00292   Methods that have a default value (e.g. .nil) will be intialized to that default value and need to be overridden in
00293   the appropiate subclass.
00294 */
00295 ::class xmlNode public
00296 /**
00297   A convenience constant to implement <i>null</i>
00298 */
00299 ::constant null .nil
00300 /**
00301   Constants that define the type of nodes that are possible.
00302 */
00303 ::constant elementNode 1 
00304 ::constant attributeNode 2
00305 ::constant textNode 3
00306 ::constant cdataSectionNode 4
00307 ::constant entityReferenceNode 5
00308 ::constant entityNode 6
00309 ::constant processingInstructionNode 7
00310 ::constant commentNode 8
00311 ::constant documentNode 9
00312 ::constant documentTypeNode 10
00313 ::constant documentFragmentNode 11
00314 ::constant notationNode 12
00315 /**
00316   <b>instances</b> is a private class attribute (property) that is used to
00317   keep track of the node instances being created and to provide a unique 
00318   identifier for each node.
00319 */
00320 ::attribute instances class private
00321 /**
00322   Gets a unique identifier for each (subclass) node being created.
00323   @return number - unique identifier for the new xmlNode
00324  
00325   The use of <u>use strict arg</u> makes sure there are no parameters.
00326 */
00327 ::method getId class
00328   use strict arg
00329   if instances~dataType('U') then instances = 0
00330   instances += 1
00331 return instances
00332 /**
00333   The unique node identification
00334 */
00335 ::attribute id private
00336 /**
00337   A <b>NamedNodeMap</b> representing the attributes in an <b>elementNode</b>.
00338 */  
00339 ::attribute attributes get
00340 ::attribute attributes set
00341 /**
00342   The absolute base URI of this node or null if the implementation was not able to obtain an absolute URI. 
00343 */
00344 ::attribute baseURI get
00345 ::attribute baseURI set
00346 /**
00347   A <b>nodeList</b> containing the childNodes of a node. If there are no children, this is a NodeList containing no
00348   nodes.
00349 */
00350 ::attribute childNodes get
00351 ::attribute childNodes set
00352 /**
00353   The local part of the qualified name of this node.
00354   <br>
00355   For nodes of any type other than ELEMENT_NODE and ATTRIBUTE_NODE and nodes created with a DOM Level 1 method, such as
00356   xmlDocument~createElement, this is always <b>.nil</b>.
00357 */
00358 ::attribute localName get
00359 ::attribute localName set
00360 /**
00361   The namespace URI of this node, or null if it is unspecified. This is not a computed value that is the result of a
00362   namespace lookup based on an examination of the namespace declarations in scope. It is merely the namespace URI given
00363   at creation time.
00364   <br>
00365   For nodes of any type other than ELEMENT_NODE and ATTRIBUTE_NODE and nodes created with a DOM Level 1 method, such as
00366   xmlDocument~createElement, this is always <b>.nil</b>.
00367 */
00368 ::attribute namespaceURI get
00369 ::attribute namespaceURI set
00370 /**
00371  
00372 */
00373 ::attribute nextSibling 
00374 /**
00375   The following nodeName values are valid for a particular type of node:
00376   <ul>
00377   <li><b>Attr</b> - xmlAttr~name (i.e. the name part of the name-value attribute pair).</li>
00378   <li><b>CDATASection</b> - literal "#cdata-section".</li>
00379   <li><b>Comment</b> - literal "#comment".</li>
00380   <li><b>Document</b> - literal "#document".</li>
00381   <li><b>DocumentFragment</b> - literal "#document-fragment".</li>
00382   <li><b>DocumentType</b> - xmlDocumentType~name.</li>
00383   <li><b>Element</b> - xmlElement~tagName.</li>
00384   <li><b>Entity</b> - xmlEntity name (e.g. ?????).</li>
00385   <li><b>EntityReference</b> - name of entity referenced (e.g. ?????).</li>
00386   <li><b>Notation</b> - notation name (e.g. ?????).</li>
00387   <li><b>ProcessingInstruction</b> - xmlProcessingInstruction~target.</li>
00388   <li><b>Text</b> - literal "#text".</li>
00389   </ul>
00390 */
00391 ::attribute nodeName get 
00392 ::attribute nodeName set
00393 /**
00394   An integer indicating which type of node this is. See above.
00395 */
00396 ::attribute nodeType get
00397 ::attribute nodeType set 
00398 /**
00399   The following nodeName values are valid for a particular type of node:
00400   <ul>
00401   <li><b>Attr</b> - xmlAttr~value (i.e. the value part of the name-value attribute pair).</li>
00402   <li><b>CDATASection</b> -  xmlCharacterData~data (i.e. the content of the CDATA Section).</li>
00403   <li><b>Comment</b> - xmlCharacterData.data (i.e. the content of the comment).</li>
00404   <li><b>Document</b> - <b>.nil</b></li>
00405   <li><b>DocumentFragment</b> - <b>.nil</b></li>
00406   <li><b>DocumentType</b> - <b>.nil</b></li>
00407   <li><b>Element</b> - <b>.nil</b></li>
00408   <li><b>Entity</b> - <b>.nil</b></li> 
00409   <li><b>EntityReference</b> - <b>.nil</b></li>
00410   <li><b>Notation</b> - <b>.nil</b></li>
00411   <li><b>ProcessingInstruction</b> - xmlProcessingInstruction~data</li>
00412   <li><b>Text</b> - xmlCharacter~data (i.e. the content of the text node).</li>
00413   </ul>
00414 */
00415 ::attribute nodeValue get 
00416 ::attribute nodeValue set
00417 /**
00418   The xmlDocument object associated with this node. This is also the xmlDocument object used to create new nodes. When
00419   this node is a xmlDocument or a xmlDocumentType which is not used with any xmlDocument yet, this is <b>.nil</b>.
00420 */
00421 ::attribute ownerDocument get
00422 ::attribute ownerDocument set
00423 /**
00424   The parent of this node. All nodes, except xmlAttr, xmlDocument, xmlDocumentFragment, xmlEntity, and xmlNotation may
00425   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
00426   the tree, this is <b>.nil</b>. 
00427 */
00428 ::attribute parentNode get 
00429 ::attribute parentNode set
00430 /**
00431   The namespace prefix of this node, or null if it is unspecified. When it is defined to be <b>.nil</b>, setting it has
00432   no effect, including if the node is read-only. 
00433  
00434   Note that setting this attribute, when permitted, changes the nodeName attribute, which holds the qualified name, as
00435   well as the tagName and name attributes of the xmlElement and xmlAttr interfaces, when applicable.
00436  
00437   Setting the prefix to null makes it unspecified, setting it to an empty string is implementation dependent. Note also
00438   that changing the prefix of an attribute that is known to have a default value, does not make a new attribute with the
00439   default value and the original prefix appear, since the namespaceURI and localName do not change.
00440  
00441   For nodes of any type other than ELEMENT_NODE and ATTRIBUTE_NODE and nodes created with a DOM Level 1 method, such as
00442   createElement from the xmlDocument interface, this is always <b>.nil</b>.
00443 */
00444 ::attribute prefix get 
00445 ::attribute prefix set 
00446 /**
00447  
00448 */
00449 ::attribute previousSibling
00450 /**
00451   This attribute returns the text content of this node and its descendants. When it is defined to be .nil, setting it
00452   has no effect. On setting, any possible children this node may have are removed and, if it the new string is not empty
00453   or null, replaced by a single xmlText node containing the string this attribute is set to. 
00454 */
00455 ::method textContent
00456   raise syntax 93.960
00457 exit
00458 ::attribute textContent set
00459 /**
00460   Method to initially set read-only attributes
00461   @param attrName - the name of the Attribute.
00462   @param attrValue - the value of the attribute.
00463   @raises syntax 93.900 - Attribute value cannot be set twice
00464  
00465   If the attribute has been set already a syntx error will be raised
00466 */
00467 ::method setReadOnly
00468 --trace i
00469   use strict arg attrName,attrValue
00470   if self~send(attrName)<>attrName~upper
00471     then raise syntax 93.900 array ("Attribute:" attrName "is read only, once set")
00472     else self~send(attrName'=',attrValue)
00473 return
00474 /**
00475   The instance constructor
00476 */
00477 ::method init
00478   self~id = self~class~getId
00479   self~attributes = .nil
00480   self~baseURI = .nil
00481   self~childNodes = .xmlNodeList~new(.array~new)
00482   self~localName = .nil
00483   self~namespaceURI = .nil
00484   self~nodeName = ''
00485   self~nodeValue = ''
00486   self~nodeType = .nil
00487   self~ownerDocument = .nil
00488   self~parentNode = .nil
00489   self~prefix = .nil
00490 return
00491 /**
00492   Adds the node <b>child</b> to the end of the list of children of this node. If the <b>child</b> is already in the
00493   tree, it is first removed.
00494   @param child - the node to be appended. 
00495   @return node - the node appended
00496  
00497   If <b>child</b> is a xmlDocumentFragment object, the entire contents of the document fragment are moved into the child
00498   list of this node.
00499 */
00500 ::method appendChild
00501   use strict arg child
00502   appended = .nil
00503   if (child<>.nil) then do
00504     child~parentNode = self
00505     self~childNodes~append(child)
00506     appended = child
00507   end
00508 return appended
00509 /**
00510   @return nodes - A xmlNodeList that contains all the children of this node. 
00511  
00512   If there are no children, then this is a xmlNodeList containing no nodes.
00513 */
00514 ::method children
00515   use strict arg 
00516 return self~childNodes
00517 /**
00518   Returns a duplicate of this node, i.e., serves as a generic copy constructor for nodes. The duplicate node has no
00519   parent (parentNode is <b>.nil</b>) and no user data. User data associated to the imported node is not carried over.
00520   However, if any UserDataHandlers has been specified along with the associated data these handlers will be called with
00521   the appropriate parameters before this method returns.
00522   @param deep=.false - optional <b>.true</b> or <b>.false</b> (= default)
00523   @return node - the duplicated node
00524  
00525   If <i> deep</i> is <b>.true</b>, recursively clone the subtree under the specified node; if <b>.false</b>, clone only
00526   the node itself (and its attributes, if it is an xmlElement).
00527   Cloning an xmlElement copies all attributes and their values, including those generated by the XML processor to
00528   represent defaulted attributes, but this method does not copy any children it contains unless it is a <i>deep</i>
00529   clone. This includes text contained in the xmlElement since the text is contained in a child xmlText node. 
00530   <br>
00531   Cloning an xmlAttr directly, as opposed to be cloned as part of an xmlElement cloning operation, returns a specified
00532   attribute (specified is true). Cloning an xmlAttr always clones its children, since they represent its value, no
00533   matter whether this is a <i>deep</i> clone or not. 
00534   <br>
00535   Cloning an xmlEntityReference automatically constructs its subtree if a corresponding xmlEntity is available, no
00536   matter whether this is a <i>deep</i> clone or not.
00537   <br>
00538   Cloning any other type of node simply returns a copy of this node.
00539   <br>
00540   Note that cloning an immutable subtree results in a mutable copy, but the children of an xmlEntityReference clone are
00541   readonly. In addition, clones of unspecified xmlAttr nodes are specified. And, cloning xmlDocument, xmlDocumentType,
00542   xmlEntity, and xmlNotation nodes is implementation dependent.
00543 */
00544 ::method cloneNode
00545   use strict arg deep=.false
00546   clone = self~copy
00547   clone~parentNode = .nil
00548   if deep = .true then do
00549      raise syntax 93.963
00550   end
00551 return clone
00552 /**
00553   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
00554   parameter, with regard to their position in the document and according to the document order.
00555   @param other - The node to compare with 
00556   @return number - Position relatively to the reference node 
00557 */
00558 ::method compareDocumentPosition
00559   use strict arg other
00560   raise syntax 93.963
00561 exit
00562 /**
00563   @return child - The first child of this node
00564  
00565   If there is no such node, this returns <b>.nil</b>
00566 */
00567 ::method firstChild
00568   use strict arg
00569   child = .nil
00570   if (self~childNodes~length>0) then child = self~Childnodes~item(0)
00571 return child
00572 /**
00573   @param feature - The name of the feature requested 
00574   @param version - The version number of the feature to test 
00575   @return domObject - An object which implements the specialized APIs or <b>.nil</b>
00576  
00577   This method returns a specialized object which implements the specialized APIs of the specified feature and version,
00578   as specified in DOM Features. The specialized object may also be obtained by using binding-specific casting methods
00579   but is not necessarily expected to. 
00580   <br>
00581   This method also allows the implementation to provide specialized objects which do not support the xmlNode interface. 
00582 */
00583 ::method getFeature
00584   use strict arg feature, version
00585   raise syntax 93.963
00586 exit
00587 /**
00588   Retrieves the object associated to a key on a this node. The object must first have been set to this node by calling
00589   <b>setUserData</b> with the same key.
00590   @param key - The key the object is associated to.
00591   @return userdata - the DOMUserData associated, or <b>.nil</b> if there was none
00592 */
00593 ::method getUserData
00594   use strict arg key
00595   raise syntax 93.963 
00596 exit
00597 /**
00598   @return boolean - <b>.true</b> if this node has any attributes, <b>.false</b> otherwise
00599 */
00600 ::method hasAttributes
00601   use strict arg
00602 return .false
00603 /**
00604   @return boolean - <b>.true</b> if this node has any children, <b>.false</b> otherwise
00605 */
00606 ::method hasChildNodes
00607   use strict arg
00608   hasChildren = .false
00609   if (self~children~items>0) then hasChildren = .true
00610 return hasChildren
00611 /**
00612   Inserts the node <i>child</i> before the existing child node <i>where</i>.
00613   @param child - the node to be inserted
00614   @param where - the node before which the new node needs to be inserted.
00615   @return node - the node being inserted
00616  
00617   If <i>where</i> is .nil, insert <i>child</i> at the end of the list of children.
00618   <br>
00619   If <i>child</i> is a xmlDocumentFragment object, all of its children are inserted, in the same order, before
00620   <i>where</i>. 
00621   <br>
00622   If the <i>child</i> is already in the tree, it is first removed.
00623   <br>
00624   Note: Inserting a node before itself is implementation dependent. 
00625 */
00626 ::method insertBefore
00627   use strict arg child, where
00628   if (where==.nil) then do
00629      self~childNodes~append(child)
00630   end
00631   -- find the where node
00632   else do
00633     newList = .xmlNodeList~new
00634     do i=0 to self~childNodes~length-1
00635      if self~childNodes~item(i) == where then newList~append(child)
00636      newList~append(self~childNodes~item(i))
00637     end
00638     self~childNodes = newList
00639   end
00640   child~parentNode = self
00641 return child
00642 /**
00643   This method checks if the specified <i>namespaceURI</i> is the default namespace or not.
00644   @param uri - The <i>namespaceURI</i> to look for
00645   @return boolean - <b>.true</b> if default, <b>.false</b> otherwise
00646 */
00647 ::method isDefaultNamespace
00648   use strict arg uri
00649   raise syntax 93.963
00650 exit  
00651 /**
00652   Tests whether two nodes are equal.
00653   @param other - The node to compare equality with
00654   @return boolean - <b>.true</b> if equal, <b>.false</b> otherwise
00655  
00656  
00657   This method tests for equality of nodes, not sameness (i.e., whether the two nodes are references to the same object)
00658   which can be tested with xmlNode~isSameNode. All nodes that are the same will also be equal, though the reverse may
00659   not be true.
00660   <br>
00661   Two nodes are equal if and only if the following conditions are satisfied: 
00662   <ul>
00663   <li>The two nodes are of the same type.</li>
00664   <li>The following string attributes are equal: nodeName, localName, namespaceURI, prefix, nodeValue. This is: they are
00665   both null, or they have the same length and are character for character identical.</li>
00666   <li>The attributes xmlNamedNodeMaps are equal. This is: they are both null, or they have the same length and for each
00667   node that exists in one map there is a node that exists in the other map and is equal, although not necessarily at the
00668   same index.<li>
00669   <li>The childNodes xmlNodeLists are equal. This is: they are both null, or they have the same length and contain equal
00670   nodes at the same index. 
00671   <br>Note that normalization can affect equality; to avoid this, nodes should be normalized before being compared.</li>
00672   </ul>
00673   For two xmlDocumentType nodes to be equal, the following conditions must also be satisfied: 
00674   <ul>
00675   <li>The following string attributes are equal: publicId, systemId, internalSubset.</li>
00676   <li>The entities xmlNamedNodeMaps are equal.</li>
00677   <li>The notations NamedNodeMaps are equal.</li>
00678   </ul>
00679   On the other hand, the following do not affect equality: the ownerDocument, baseURI, and parentNode attributes, the
00680   specified attribute for xmlAttr nodes, the schemaTypeInfo attribute for xmlAttr and xmlElement nodes, the
00681   xmlText~isElementContentWhitespace attribute for xmlText nodes, as well as any user data or event listeners registered
00682   on the nodes. 
00683 */
00684 ::method isEqualNode
00685   use strict arg other
00686   raise syntax 93.963
00687 exit
00688 /**
00689   Tests whether this node is the same node as the given one.
00690   @param other - The node to test against.
00691   @return boolean - <b>.true</b> if the nodes are the same, <b>.false</b> otherwise. 
00692  
00693   This method provides a way to determine whether two xmlNode references returned by the implementation reference the
00694   same object. When two xmlNode references are references to the same object, even if through a proxy, the references
00695   may be used completely interchangeably, such that all attributes have the same values and calling the same DOM method
00696   on either reference always has exactly the same effect.
00697 */
00698 ::method isSameNode
00699   use strict arg other
00700   raise syntax 93.963
00701 exit
00702 /**
00703   Tests whether the DOM implementation implements a specific feature and that feature is supported by this node, as
00704   specified in DOM Features. 
00705   @param feature - The name of the feature to test. 
00706   @param version - This is the version number of the feature to test. 
00707   @return boolean - <b>.true</b> if supported on this node, <b>.false</b> otherwise.
00708 */  
00709 ::method isSupported
00710   use strict arg feature, version
00711 return .false
00712 /**
00713   @return aNode - The last child of this node. 
00714  
00715   If there is no such node, this returns <b>.nil</b>.
00716 */
00717 ::method lastChild
00718   use strict arg
00719   child = .nil
00720   if (self~children~items>0) then child = self~children[self~children~items]
00721 return child
00722 /**
00723   Look up the <i>namespaceURI</i> associated to the given prefix, starting from this node.
00724   <br>
00725   See Namespace URI Lookup for details on the algorithm used by this method.
00726   @param prefix - The prefix to look for. 
00727   @return aString - The associated <i>namespaceURI</i> or <b>.nil</b> if none is found.
00728  
00729   If <i>prefix</i> is null, the method will return the default <i>namespaceURI</i> if any.
00730 */
00731 ::method lookupNamespaceURI
00732   use strict arg prefix
00733   raise syntax 93.963
00734 exit
00735 /**
00736   Look up the prefix associated to the given <i>namespaceURI</i>, starting from this node. 
00737   @param uri - A string specifying the <i>namespaceURI</i> to look for
00738   @return aString - An associated namespace prefix or <b>.nil</b> if none is found
00739  
00740   The default namespace declarations are ignored by this method. See Namespace Prefix Lookup for details on the
00741   algorithm used by this method. 
00742   <br>
00743   If more than one prefix are associated to the namespace prefix, the returned namespace prefix is implementation
00744   dependent.
00745 */
00746 ::method lookupPrefix
00747   use strict arg uri
00748   raise syntax 93.963 
00749 exit
00750 /**
00751   Finds the next sibling.
00752   @return aNode - The node immediately following this node. 
00753  
00754   If there is no such node, this returns <b>.nil</b>.
00755 */
00756 /*::method nextSibling
00757   use strict arg
00758   sibling = .nil
00759   if (self~parentNode<>.nil) then do
00760     siblings = self~parentNode~childNodes
00761     do label next i=1 to siblings~items
00762       if (siblings[i]==self) then do
00763         if (i<siblings~items) then do
00764           sibling = siblings[i-1]
00765           leave next 
00766         end
00767       end
00768     end
00769   end
00770 return sibling
00771 */
00772 /**
00773   Puts all xmlText nodes in the full depth of the sub-tree underneath this xmlNode, including attribute nodes, into a
00774   "normal" form where only structure (e.g., elements, comments, processing instructions, CDATA sections, and entity
00775   references) separates xmlText nodes, i.e., there are neither adjacent xmlText nodes nor empty xmlText nodes. This can
00776   be used to ensure that the DOM view of a document is the same as if it were saved and re-loaded, and is useful when 
00777   operations (such as XPointer [XPointer] lookups) that depend on a particular document tree structure are to be used. 
00778   <br>
00779   If the parameter "normalize-characters" of the DOMConfiguration object attached to the xmlNode~ownerDocument is
00780   <b>.true</b>, this method will also fully normalize the characters of the xmlText nodes.
00781   <br>
00782   Note: In cases where the document contains CDATASections, the normalize operation alone may not be sufficient, since
00783   XPointers do not differentiate between xmlText nodes and xmlCDATASection nodes.
00784 */
00785 ::method normalize
00786   use strict arg
00787   raise syntax 93.963
00788 exit
00789 /**
00790   Finds the preceding node.
00791   @return aNode - The node immediately preceding this node. 
00792  
00793   If there is no such node, this returns <b>.nil</b>
00794 */
00795 /**
00796 ::method previousSibling
00797   use strict arg
00798   sibling = .nil
00799   if (self~parentNode<>.nil) then do
00800     siblings = self~parentNode~childNodes
00801     do labl prev i=1 to siblings~items
00802       if (siblings[i]==self) then do
00803         if (i>1) then do
00804           sibling = siblings[i-1]
00805           leave prev
00806         end
00807       end
00808     end
00809   end
00810 return sibling
00811 */
00812 /**
00813   Removes the child node indicated by <i>aNode</i> from the list of children, and returns it.
00814   @param child - The node being removed.
00815   @return aNode - The node removed.
00816 */
00817 ::method removeChild
00818   use strict arg child
00819   removed = .nil
00820   if (child<>.nil) then do
00821     -- find the reference node
00822     do i=1 to self~children~items
00823       if (children[i]==child) then leave
00824     end
00825     removed = self~children~remove(i)
00826     removed~parentNode = .nil
00827   end
00828 return removed
00829 /**
00830   Replaces the child node <i>old</i> with <i>new</i> in the list of children, and returns the <i>old</i> child node.
00831   @param new - The new node to put in the child list.
00832   @param old - The node being replaced in the list.
00833   @return aNode - The node replaced.
00834  
00835   If <i>new</i> is a xmlDocumentFragment object, <i>old</i> is replaced by all of the
00836   xmlDocumentFragment children, which are inserted in the same order. If the <i>new</i> 
00837   is already in the tree, it is first removed.
00838   <br>
00839   Note: Replacing a node with itself is implementation dependent. 
00840 */
00841 ::method replaceChild
00842   use strict arg new, old
00843   replaced = .nil
00844   if (old<>.nil) then do
00845   -- find the reference node
00846     do i=1 to self~children~items
00847        if (self~children[i]==old) then leave
00848     end
00849     replaced = self~children[i]
00850     self~children[i] = new
00851     self~children[i]~parentNode = self
00852     replaced~parentNode = .nil
00853   end
00854 return replaced
00855 /**
00856   Associate an object to a key on this node. The object can later be retrieved from this node by invoking the
00857   getUserData method with the same key.
00858   @param key - The key to associate the object to.
00859   @param data - A DOMUserData object to associate to the key, or null to remove any existing association to that key.
00860   @param handler - An UserDataHandler, a handler to associate to that key, or null.
00861   @return userData - The DOMUserData previously associated to the given key on this node, or null if there was none.
00862 */
00863 ::method setUserData
00864   use strict arg key, data, handler
00865   raise syntax 93.963 
00866 exit
00867 /**
00868   Convenience method to walk thru a (sub)nodes tree
00869   @param nodes - The sibling xmlNodeList to start the walk.
00870   @param name - The name of the tag being searched for.
00871   @param nl - The xmlNodeList containing the selected result nodes.
00872 */
00873 ::method treeWalk private
00874   use strict arg nodes, name, nl
00875   do n=0 to nodes~length-1
00876     if name<>'*' then do
00877       if nodes~item(n)~nodeName==name then nl~append(nodes~item(n))
00878     end
00879     else do
00880       nl~append(nodes~item(n))
00881     end
00882     if nodes~item(n)~childNodes~length>0 then do
00883       self~treewalk(nodes~item(n)~childNodes, name, nl)
00884     end
00885   end
00886 return
00887 /* :end */
00888  
00889 /* CLASS: xmlNamedNodeMap */
00890 /**
00891   Objects implementing the xmlNamedNodeMap interface are used to represent collections of nodes that can be accessed by
00892   name. Note that xmlNamedNodeMap does not inherit from NodeList; NamedNodeMaps are not maintained in any particular
00893   order. Objects contained in an object implementing xmlNamedNodeMap may also be accessed by an ordinal index, but this
00894   is simply to allow convenient enumeration of the contents of a xmlNamedNodeMap, and does not imply that the DOM
00895   specifies an order to these xmlNodes. xmlNamedNodeMap objects in the DOM are live. 
00896 */
00897 ::class xmlNamedNodeMap public 
00898 /**
00899   A private array with directory entries, that have a (possibly qualified) name as index and xmlNodes as items.
00900 */
00901 ::attribute namedMap private
00902 /**
00903   xmlNamedNodeMap instance constructor.
00904 */
00905 ::method init
00906   self~namedMap = .directory~new
00907   self~init:super
00908 exit
00909 /**
00910   The number of xmlNodes in this map. 
00911   @return - The number of nodes in the xmlNamedNodeMap.
00912 */
00913 ::method length 
00914 return self~namedMap~items
00915 /**
00916   Retrieves a node specified by name.
00917   @param name - The nodeName of a node to retrieve.
00918   @return node - The xmlNode with the specified name, or <b>.nil</b>.
00919 */ 
00920 ::method getNamedItem
00921   use strict arg name
00922   node = .nil
00923   if name~isA(.string) then do
00924     node = self~namedMap[name]
00925   end
00926 return node
00927 /**
00928   Retrieves a node specified by local name and namespace URI.
00929   @param namespaceURI - The namespace URI of the node to retrieve.
00930   @param localName - The local name of the node to retrieve.
00931   @return node - A xmlNode(of any type) with the specified local name and namespace URI, or null.
00932  
00933   Per [XML Namespaces], applications must use the value <b>.nil,</b> as the namespaceURI parameter for methods if they
00934   wish to have no namespace.
00935 */
00936 ::method getNamedItemNS
00937   use strict arg namespaceURI, localName
00938   node = .nil
00939   if (localName)~isA(.string) then do 
00940     node = self~namedMap[localName]
00941     if namespaceURI<>.nil then do
00942       if node~namespaceURI<>namespaceURI then node = .nil
00943     end
00944   end
00945 return node
00946 /**
00947   Returns the indexth item in the map. If index is greater than or equal to the number of nodes in this map, this
00948   returns <b>.nil</b>.
00949   @param index - Index into this map.
00950   @return node - The node at the indexth position in the map, or <B>.nil</b> if not a valid index.
00951 */
00952 ::method item
00953   use strict arg index
00954   node = .nil 
00955   if index>=0 then do  
00956     node = self~namedMap~allItems[index+1]
00957   end  
00958 return node
00959 /**
00960   Removes a node specified by name. 
00961   @param name - The nodeName of the node to remove.
00962   @return node - The node removed from this map if a node with such a name exists.
00963   @raises user domException - NOT_FOUND_ERR 
00964  
00965   When this map contains the attributes attached to an element, if the removed attribute is known to have a default
00966   value, an attribute immediately appears containing the default value as well as the corresponding namespace URI,
00967   local name, and prefix when applicable.
00968  
00969   This ooRexx implementation does not process a DTD, thus has no way to determine if a default value has to be provided.
00970   The node is only removed, no additional checks for default value are made.
00971 */
00972 ::method removeNamedItem
00973   use strict arg name
00974   node = .nil
00975   if name~isA(.string) then do
00976     node = self~namedMap~remove(name)
00977   end
00978   if node==.nil then raise user domException description(.domException~not_found_err)
00979 return node
00980 /**
00981   Removes a node specified by local name and namespace URI. A removed attribute may be known to have a default value
00982   when this map contains the attributes attached to an element, as returned by the attributes attribute of the xmlNode
00983   interface. If so, an attribute immediately appears containing the default value as well as the corresponding
00984   namespace URI, local name, and prefix when applicable.
00985   @param namespaceURI=.nil - The namespace URI of the node to remove.
00986   @param localName - The local name of the node to remove.
00987   @return node - The node removed from this map if a node with such a name exists.
00988   @raises user domException - NOT_FOUND_ERR 
00989  
00990   Per [XML Namespaces], applications must use the value <b>.nil</b> as the namespaceURI parameter for methods if they
00991   wish to have no namespace.
00992   @see #removeNamedItem for behaviour concerning default values. 
00993 */
00994 ::method removeNamedItemNS
00995   use strict arg namespaceURI=.nil, localName
00996   node = .nil
00997   if (localName)~isA(.string) then do
00998     if node~namespaceURI==namespaceURI 
00999       then node = self~namedMap~remove(localName)
01000       else node = .nil
01001   end
01002 return node
01003 /**
01004   Adds a xmlNode using its <i>nodeName</i> attribute. If a node with that name is already present in this map, it is
01005   replaced by the new one. Replacing a node by itself has no effect.
01006   @param arg - A xmlNode to store in this map, accessible using its <i>nodeName</i> attribute.
01007   @return node - The replaced xmlNode or <b>.nil</b> if no replacement.
01008   @raises user domException - WRONG_DOCUMENT_ERR
01009   @raises user domException - INUSE_ATTRIBUTE_ERR
01010 */  
01011 ::method setNamedItem
01012   use strict arg arg
01013   --if arg~ownerDocument<>self~ownerDocument
01014   --  then raise user domException description (.domException~wrong_document_err)
01015   if arg~nodeType==.xmlNode~attributeNode then do
01016     if arg~ownerElement<>.nil 
01017       then raise user domException description (.domException~inuse_attribute_err)
01018   end
01019   node = .nil
01020   if arg~isA(.xmlNode) then do
01021     name = arg~nodeName
01022     node = self~namedMap[name]
01023     self~namedMap[name] = arg
01024   end
01025 return node
01026 /**
01027   Adds a node using its namespaceURI and localName. If a node with that namespace URI and that local name is already
01028   present in this map, it is replaced by the new one. Replacing a node by itself has no effect.
01029   @param arg - A node to add to the map, subsequently accessible via <i>namespaceURI</i> and <i>localName</i>. 
01030   @return node - The replaced xmlNode or <b>.nil</b> if no replacement.
01031   @raises user domException - WRONG_DOCUMENT_ERR
01032   @raises user domException - INUSE_ATTRIBUTE_ERR
01033 */
01034 ::method setNamedItemNS
01035   use strict arg arg
01036   if arg~ownerDocument<>self~ownerDocument
01037     then raise user domException description (.domException~wrong_document_err)
01038   if arg~nodeType==.attributeElement then do
01039     if arg~ownerElement<>.nil 
01040       then raise user domException description (.domException~inuse_attribute_err)
01041   end
01042   node = .nil
01043   if arg~isA(.xmlNode) then do
01044     name = arg~localName 
01045     node = self~namedMap[name]
01046     -- the following replaces also a node from a different namespace
01047     -- probably need a directory with name indexes and items of a directory with namespace indexes and node items
01048     if node~namespaceURI<>arg~namespaceURI
01049       then node = .nil
01050       else self~namedMap[name] = arg
01051   end
01052 return node
01053 /**
01054   Provides a xmlNamedNodeMap as a native ooRexx directory
01055   @return directory - A native ooRexx directory representing the NamedNodeMap.
01056 */
01057 ::method toOorexxDirectory
01058 return self~namedMap
01059 /**
01060   Sets a NamedNodeMap from a native ooRexx directory
01061   @param nodeDirectory - The native ooRexx directory to replace an existing xmlNamedNodeMap.
01062   @raises syntax 93.914 - Named item is not a proper xmlNode 
01063 */
01064 ::method fromOorexxDirectory
01065   use strict arg nodeDirectory
01066   s = nodeDirectory~supplier
01067   do while s~available
01068     if \s~item~isA(.xmlNode) then do
01069       raise syntax 93.914 array (nodeDirectory, .xmlNode)
01070     end
01071     s~next
01072   end
01073   self~namedMap = nodeDirectory
01074 return
01075 /* :end */
01076  
01077 /* CLASS: xmlAttr */
01078 /**
01079   The xmlAttr interface represents an attribute in an xmlElement object. Typically the allowable values for the
01080   attribute are defined in a schema associated with the document.
01081  
01082   xmlAttr objects inherit the xmlNode interface, but since they are not actually child nodes of the element they
01083   describe, the DOM does not consider them part of the document tree. Thus, the xmlNode attributes <i>parentNode</i>,
01084   <i>previousSibling</i>, and <i>nextSibling</i> have a <b>.nil</b> value for xmlAttr objects. The DOM takes the view
01085   that attributes are properties of elements rather than having a separate identity from the elements they are
01086   associated with; this should make it more efficient to implement such features as default attributes associated with
01087   all elements of a given type. Furthermore, xmlAttr nodes may not be immediate children of a xmlDocumentFragment.
01088   However, they can be associated with xmlElement nodes contained within a xmlDocumentFragment. In short, users and
01089   implementors of the DOM need to be aware that xmlAttr nodes have some things in common with other objects inheriting
01090   the Node interface, but they also are quite distinct.
01091  
01092   The attribute's effective value is determined as follows: if this attribute has been explicitly assigned any value,
01093   that value is the attribute's effective value; otherwise, if there is a declaration for this attribute, and that
01094   declaration includes a default value, then that default value is the attribute's effective value; otherwise, the
01095   attribute does not exist on this element in the structure model until it has been explicitly added. Note that the
01096   xmlNode <i>nodeValue</i> attribute on the xmlAttr instance can also be used to retrieve the string version of the
01097   attribute's value(s).
01098  
01099   If the attribute was not explicitly given a value in the instance document but has a default value provided by the
01100   schema associated with the document, an attribute node will be created with specified set to false. Removing attribute
01101   nodes for which a default value is defined in the schema generates a new attribute node with the default value and
01102   specified set to false. If validation occurred while invoking the xmlDocument <i>normalizeDocument</i>, attribute
01103   nodes with specified equals to false are recomputed according to the default attribute values provided by the schema.
01104   If no default value is associate with this attribute in the schema, the attribute node is discarded. 
01105  
01106   In XML, where the value of an attribute can contain entity references, the child nodes of the xmlAttr node may be
01107   either xmlText or xmlEntityReference nodes (when these are in use; see the description ofxml EntityReference for
01108   discussion). 
01109 */
01110  
01111 ::class xmlAttr public subclass xmlNode
01112 /**
01113   Returns whether this attribute is known to be of type ID (i.e. to contain an identifier for its owner element) or not.
01114   When it is and its value is unique, the ownerElement of this attribute can be retrieved using the  xmlDocument
01115   <i>getElementById</i> method. The implementation could use several ways to determine if an attribute node is known to
01116   contain an identifier:
01117   <ul>
01118   <li>If validation occurred using an XML Schema [XML Schema Part 1] while loading the document or while invoking the
01119   xmlDocument <i>normalizeDocument</i> method, the post-schema-validation infoset contributions (PSVI contributions)
01120   values are used to determine if this attribute is a schema-determined ID attribute using the schema-determined ID 
01121   definition in [XPointer].</li>
01122   <li>If validation occurred using a DTD while loading the document or while invoking  the xmlDocument
01123   <i>normalizeDocument</i> method, the infoset [type definition] value is used to determine if this attribute is a
01124   DTD-determined ID attribute using the DTD-determined ID definition in [XPointer].</li>
01125   <li>From the use of the xmlElement <i>setIdAttribute</i>, <i>setIdAttributeNS</i>, or <i>setIdAttributeNode</i>, i.e.
01126   it is an user-determined ID attribute;</li>
01127   <li>Using mechanisms that are outside the scope of this specification, it is then an externally-determined ID
01128   attribute. This includes using schema languages different from XML schema and DTD.</li> 
01129  
01130   If validation occurred while invoking the xmlDocument <i>normalizeDocument</i> method, all user-determined ID
01131   attributes are reset and all attribute nodes ID information are then reevaluated in accordance to the schema used. As
01132   a consequence, if the xmlAttr <i>schemaTypeInfo</i> attribute contains an ID type, <i>isId</i> will always return
01133   <b>.true</b>. 
01134 */
01135 ::attribute isId get
01136 ::attribute isId set
01137 /**
01138   Returns the name of this attribute. If the xmlNode <i>localName</i> is different from <b>.nil</b>, this attribute is a
01139   qualified name.
01140 */
01141 ::method name
01142 return self~nodeName
01143 /**
01144   The xmlElement node this attribute is attached to or <b>.nil</b> if this attribute is not in use.
01145 */
01146 ::attribute ownerElement get
01147 ::attribute ownerElement set
01148 /**
01149   The type information associated with this attribute. While the type information contained in this attribute is
01150   guarantee to be correct after loading the document or invoking the xmlDocument <i>normalizeDocument</i> method,
01151   <i>schemaTypeInfo</i> may not be reliable if the node was moved. 
01152 */
01153 ::attribute schemaTypeInfo get
01154 ::attribute schemaTypeInfo set
01155 /**
01156   <b>.true</b> if this attribute was explicitly given a value in the instance document, false otherwise. If the
01157   application changed the value of this attribute node (even if it ends up having the same value as the default value)
01158   then it is set to <b>.true</b>. The implementation may handle attributes with default values from other schemas
01159   similarly but applications should use the xmlDocument <i>normalizeDocument</i> method to guarantee this information is
01160   up-to-date. 
01161 */
01162 ::attribute specified get
01163 ::attribute specified set
01164 /**
01165   On retrieval, the value of the attribute is returned as a string. Character and general entity references are replaced
01166   with their values. See also the method <i>getAttribute</i> on the xmlElement interface.
01167  
01168    On setting, this creates a xmlText node with the unparsed contents of the string, i.e. any characters that an XML
01169    processor would recognize as markup are instead treated as literal text. See also the xmlElement <i>setAttribute</i>
01170    method.
01171 */
01172 ::method value
01173 return self~nodeValue
01174 /**
01175   xmlAttr instance creation method
01176 */
01177 ::method init
01178   self~isId = .false
01179   self~ownerElement = .nil
01180   self~schemaTypeInfo = .nil  -- not supported/implemented
01181   self~specified = .false
01182   self~init:super
01183 return
01184 /* :end */
01185  
01186 /* CLASS: xmlCharacterData */
01187 /**
01188   The CharacterData interface extends xmlNode with a set of attributes and methods for accessing character data in the
01189   DOM. For clarity this set is defined here rather than on each object that uses these attributes and methods. No DOM
01190   objects correspond directly to CharacterData, though Text and others do inherit the interface from it. All offsets in
01191   this interface start from 0.
01192  
01193   The following DOES NOT APPLY FOR this ooRexx xmlDOM implementation. Characters are ASCII 8-bit.
01194   As explained in the DOMString interface, text strings in the DOM are represented in UTF-16, i.e. as a sequence of
01195   16-bit units. In the following, the term 16-bit units is used whenever necessary to indicate that indexing on
01196   CharacterData is done in 16-bit units. 
01197 */
01198 ::class xmlCharacterData public mixinclass xmlNode
01199 /**
01200   The data contained in a xmlNode
01201 */
01202 ::method data 
01203 return self~nodeValue
01204 /**
01205 */
01206 ::method length 
01207 return self~data~length
01208 /**
01209   xmlCharacterData instance constructor
01210   @param data - The character data
01211 */
01212 ::method init
01213   use strict arg data
01214   self~init:super
01215   if arg~isA(.string) 
01216     then self~nodeValue = data
01217     else raise user domException description (.domException~invalid_modification_err)
01218 exit
01219 /**
01220   Append the string to the end of the character data. Upon success, <i>data</i> and <i>length</i> reflect the change.   
01221   @param arg - The data to be appended
01222 */
01223 ::method appendData
01224   use strict arg arg
01225   if arg~isA(.string) 
01226     then self~data ||= arg
01227     else raise user domException description (.domException~invalid_modification_err)
01228 return
01229 /**
01230   Remove a range of characters from the node. Upon success, <i>data</i> and <i>length</i> reflect the change.
01231   @param offset - The index(base 0) where to start deleting data
01232   @param count - The number of characters to delete
01233 */
01234 ::method deleteData
01235   use strict arg offset, count
01236   self~data = self~data~delStr(offset+1,count)
01237 return
01238 /**
01239   Insert a string at the specified offset.
01240   @param offset - The index where to start inserting data
01241   @param string - The character data to insert
01242 */
01243 ::method insertData
01244   use strict arg offset, string
01245   if offset>self~data~length | count<0 
01246     then raise user domException description (.domException~index_size_err)   
01247   self~data = self~data~substr(1,offset) || string || self~data~substr(offset+1)
01248 return
01249 /**
01250   Replace the characters starting at the specified offset with the specified string.
01251   @param offset - The offset from which to start replacing.
01252   @param count - The number of characters to replace. 
01253   @param string - The string with which the range must be replaced.
01254  
01255   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
01256   the same as a remove method call with the same range, followed by an append method invocation).
01257   */
01258 ::method replaceData
01259   use strict arg offset, count, string
01260   if offset<0 | offset>self~data~length | count<0 
01261     then raise user domException description (.domException~index_size_err)
01262   self~data = self~data~overlay(string,offset+1,count)
01263 return
01264 /**
01265   Extracts a range of data from the node.
01266   @param offset - The index where to start retrieving data
01267   @param count - The number of characters to retrieve
01268   @return string - The specified substring. If the sum of offset and count exceeds the length, then all characters to
01269   the end of the data are returned.
01270 */
01271 ::method substringData
01272   use strict arg offset, count
01273   if offset<0 | offset>self~data~length | count<0
01274     then raise user domException description (.domException~index_size_error)
01275 return self~data~substr(offset+1,count)
01276 /* :end */
01277  
01278 /* CLASS: xmlComment */
01279 /**
01280   This interface inherits from xmlCharacterData and represents the content of a comment, i.e., all the characters
01281   between the starting '<!--' and ending '-->'. Note that this is the definition of a comment in XML, and, in practice,
01282   HTML, although some HTML tools may implement the full SGML comment structure. 
01283  
01284   No lexical check is done on the content of a comment and it is therefore possible to have the character sequence "--"
01285   (double-hyphen) in the content, which is illegal in a comment per section 2.5 of [XML 1.0]. The presence of this
01286   character sequence must generate a fatal error during serialization. 
01287 */
01288 ::class xmlComment public subclass xmlNode inherit xmlCharacterData
01289 /**
01290   commentNode instance constructor.
01291   @param data - The string representing the XML comment
01292 */
01293 ::method init
01294   use strict arg data
01295   self~init:super(data)
01296 return
01297 /* :end */
01298  
01299 /* CLASS: xmlText */
01300 /**
01301   The XMLText interface inherits from XMLCharacterData and represents the textual content (termed character data in XML)
01302   of an xmlElement or xmlAttr. If there is no markup inside an element's content, the text is contained in a single
01303   object implementing the xmlText interface that is the only child of the element. If there is markup, it is parsed into
01304   the information items (elements, comments, etc.) and xmlText nodes that form the list of children of the element.
01305  
01306   When a document is first made available via the DOM, there is only one xmlText node for each block of text. Users may
01307   create adjacent xmlText nodes that represent the contents of a given element without any intervening markup, but
01308   should be aware that there is no way to represent the separations between these nodes in XML or HTML, so they will not
01309   (in general) persist between DOM editing sessions. The xmlNode <i>normalize</i> method merges any such adjacent
01310   xmlText objects into a single node for each block of text.
01311  
01312   No lexical check is done on the content of a xmlText node and, depending on its position in the document, some
01313   characters must be escaped during serialization using character references; e.g. the characters "<&" if the textual
01314   content is part of an element or of an attribute, the character sequence "]]>" when part of an element, the quotation
01315   mark character " or the apostrophe character ' when part of an attribute. 
01316 */
01317 ::class xmlText public subclass xmlNode inherit xmlCharacterData
01318 /**
01319   Returns whether this text node contains element content whitespace, often abusively called "ignorable whitespace". The
01320   text node is determined to contain whitespace in element content during the load of the document or if validation
01321   occurs while using the xmlDocument <i>normalizeDocument</i> method.
01322 */
01323 ::attribute isElementContentWhitespace get
01324 ::attribute isElementContentWhitespace set private
01325 /**
01326   Returns all text of xmlText nodes logically-adjacent text nodes to this node, concatenated in document order.
01327  
01328   For instance, in the example below <i>wholeText</i> on the xmlText node that contains "bar" returns "barfoo", and also
01329   on the xmlText node that contains "foo" it returns "barfoo". 
01330 */
01331 ::method wholeText
01332   siblings = self~parentNode~childNodes
01333   wholeText = ''
01334   do s=0 to siblings~length-1
01335     wholeText = wholeText || s~data' '
01336   end
01337 return wholeText~strip('T')
01338 /**
01339   xmlText instance constructor
01340   @param content - The text string representing the content
01341 */
01342 ::method init
01343   use strict arg content
01344   self~init:super(content)
01345   if self~class==.xmlText
01346     then do
01347       self~nodeType = .xmlNode~textNode
01348       self~nodeName = "#text"
01349     end
01350     else do
01351       self~nodeType = .xmlNode~CDATASectionNode
01352       self~nodeName = "#cdata-section"
01353     end
01354   --self~nodeValue = content
01355 return
01356  
01357 /**
01358   Replaces the text of the current node and all logically-adjacent text nodes with the specified text. All
01359   logically-adjacent text nodes are removed including the current node unless it was the recipient of the replacement
01360   text.
01361   This method returns the node which received the replacement text. The returned node is: 
01362   <ul>
01363   <li><b>.nil</b>, when the replacement text is the empty string;</li>
01364   <li>the current node, except when the current node is read-only;</li>
01365   <li>a new xmlText node of the same type (xmlText or xmlCDATASection) as the current node inserted at the location of
01366   the replacement.</li>
01367   </ul>
01368   @param content - The content of the replacing xmlText node.
01369   @return text - The xmlText node created with the specified content.
01370  
01371   Assumption: Text and CDATASections are the only ones within Element nodes (and possibly within Attr nodes).
01372 */
01373 ::method replaceWholeText
01374   use strict arg content
01375   text = .nil
01376   if content<>'' then do
01377     text = self~class~new(content)
01378     nodeList = .xmlNodeList~new(.array~of(text))
01379     self~parentNode~childNodes = nodeList
01380   end
01381 return text
01382 /**
01383   Breaks this node into two nodes at the specified offset, keeping both in the tree as siblings. After being split, this
01384   node will contain all the content up to the offset point. A new node of the same type, which contains all the content
01385   at and after the offset point, is returned. If the original node had a parent node, the new node is inserted as the
01386   next sibling of the original node. When the offset is equal to the length of this node, the new node has no data.
01387   @param offset - The offset at which to split, starting from 0.
01388   @return text - The new node, of the same type as this node.
01389   @raises user domException - INDEX_SIZE_ERR
01390 */    
01391  ::method splitText
01392   use strict arg offset
01393   if offset+1>self~data~length then do
01394     raise user domException additional (.domException~index_size_err) description ("Offset" offset "is larger than length" self~data~length "of text")
01395   end
01396   text = self~class~new(self~data~substr(offset+1))
01397   self~data = self~data~substr(1,offset)
01398   siblings = .array~new
01399   do c=0 to self~parentNode~childNodes-1
01400     child = self~parentNode~childNodes~item(c)
01401     siblings~append(child)
01402     if child==self then do
01403       siblings~append(text)
01404     end
01405   end
01406   children = .xmlNodelist~new(siblings)
01407   self~parentNode~childNodes = children
01408 return text
01409 /* :end */
01410  
01411 /* CLASS: xmlCDATASection */
01412 /**
01413   CDATA sections are used to escape blocks of text containing characters that would otherwise be regarded as markup.
01414   The only delimiter that is recognized in a CDATA section is the "]]>" string that ends the CDATA section. CDATA
01415   sections cannot be nested. Their primary purpose is for including material such as XML fragments, without needing to
01416   escape all the delimiters.
01417  
01418   The xmlCharacterData <i>data</i> attribute holds the text that is contained by the CDATA section. Note that this may
01419   contain characters that need to be escaped outside of CDATA sections and that, depending on the character encoding
01420   ("charset") chosen for serialization, it may be impossible to write out some characters as part of a CDATA section.
01421  
01422   The CDATASection interface inherits from the xmlCharacterData interface through the xmlText interface. Adjacent
01423   xmlCDATASection nodes are not merged by use of the <i>normalize</i> method of the xmlNode interface.
01424  
01425   No lexical check is done on the content of a CDATA section and it is therefore possible to have the character sequence
01426   "]]>" in the content, which is illegal in a CDATA section per section 2.7 of [XML 1.0]. The presence of this character
01427   sequence must generate a fatal error during serialization.
01428  
01429   Note: Because no markup is recognized within a xmlCDATASection, character numeric references cannot be used as an
01430   escape mechanism when serializing. Therefore, action needs to be taken when serializing a CDATASection with a
01431   character encoding where some of the contained characters cannot be represented. Failure to do so would not produce
01432   well-formed XML.
01433  
01434   One potential solution in the serialization process is to end the CDATA section before the character, output the
01435   character using a character reference or entity reference, and open a new CDATA section for any further characters in
01436   the text node. Note, however, that some code conversion libraries at the time of writing do not return an error or
01437   exception when a character is missing from the encoding, making the task of ensuring that data is not corrupted on
01438   serialization more difficult.
01439 */  
01440 ::class xmlCDATASection public subclass xmlText
01441 /**
01442   The CDATASection instance constructot
01443   @param content - The unparsed string representing the contents of the CDATASection.
01444 */
01445 ::method init
01446   use strict arg content
01447   self~init:super(content)
01448 return
01449 /* :end */
01450  
01451 /* CLASS: xmlPI */
01452 /**
01453   The ProcessingInstruction interface represents a "processing instruction", used in XML as a way to keep
01454   processor-specific information in the text of the document.
01455  
01456   No lexical check is done on the content of a processing instruction and it is therefore possible to have the character
01457   sequence "?>" in the content, which is illegal a processing instruction per section 2.6 of [XML 1.0]. The presence of
01458   this character sequence must generate a fatal error during serialization. 
01459 */
01460 ::class xmlPI public subclass xmlNode
01461 /**
01462   The content of this processing instruction. This is from the first non white space character after the target to the
01463   character immediately preceding the ?>.
01464 */
01465 ::method data 
01466 return self~nodeValue
01467 /**
01468   The target of this processing instruction. XML defines this as being the first token following the markup that begins
01469   the processing instruction. 
01470 */
01471 ::method target 
01472 return self~nodeName
01473 /**
01474   The xmlProcessingInstruction instance constructor
01475   @param target - The target for the processing instruction
01476   @param data - The unparsed string representing the content of the processing instruction.
01477 */
01478 ::method init
01479   use strict arg target, data
01480   self~init:super
01481   self~nodeType = .xmlNode~processingInstructionNode
01482   self~nodeName = target
01483   self~nodeValue = data
01484 return
01485 /* :end */
01486  
01487 /* CLASS: xmlDocumentType */
01488 /**
01489   Information about the notations and entities declared by a document (including the external subset if the parser uses
01490   it and can provide the information) is available from a xmlDocumentType object. The xmlDocumentType for a document is
01491   available from the xmlDocument object’s doctype attribute; if there is no DOCTYPE declaration for the document, the
01492   document’s doctype attribute will be set to <b>.nil</b> instead of an instance of this interface.
01493  
01494   xmlDocumentType is a subclass (precisation) of xmlNode, and adds the following attributes:
01495   <ul>
01496   <li>entities - This is a xmlNamedNodeMap giving the definitions of external and internal entities. For entity names
01497   defined more than once, only the first definition is provided (others are ignored as required by the XML
01498   recommendation). This may be <b>.nil</b> if the information is not provided by the parser, or if no entities are
01499   defined.</li>
01500   <li>internalSubset - A string giving the complete internal subset from the document. This does not include the
01501   brackets which enclose the subset. If the document has no internal subset, this is <b>.nil</b>.</li>
01502   <li>name - The name of the root element as given in the DOCTYPE declaration, if present.</li>
01503   <li>notations - This is a xmlNamedNodeMap giving the definitions of notations. For notation names defined more than
01504   once, only the first definition is provided (others are ignored as required by the XML recommendation). This may be
01505   <b>.nil</b> if the information is not provided by the parser, or if no notations are defined.</li>
01506   <li>publicId - The public identifier for the external subset of the document type definition. This will be a string
01507   or <b>.nil</b>.</li>
01508   <li>systemId - The system identifier for the external subset of the document type definition. This will be a URI as a
01509   string, or <b>.nil</b>.</li>
01510   </ul>
01511  
01512   DOM Level 3 doesn't support editing DocumentType nodes. DocumentType nodes are read-only. 
01513 */
01514 ::class xmlDocumentType public subclass xmlNode
01515 /**
01516   Entities is a xmlNamedNodeMap containing the general entities, both external and internal, declared in the DTD.
01517   Parameter entities are not contained. Every node in this map also implements the Entity interface.
01518   The DOM Level 2 does not support editing entities, therefore entities cannot be altered in any way.
01519 */
01520 ::attribute entities get
01521 ::attribute entities set
01522 /**
01523   The internal subset as a string, or <b>.nil</b> if there is none. This does not contain the delimiting square
01524   brackets.
01525   <b><u>NOTE</u>,</b> - The actual content returned depends on how much information is available to the implementation.
01526   This may vary depending on various parameters, including the XML processor used to build the document.
01527 */
01528 ::attribute internalSubset get
01529 ::attribute internalSubset set
01530 /**
01531   The name of DTD; i.e., the name immediately following the DOCTYPE keyword.
01532 */
01533 ::attribute name get
01534 ::attribute name set
01535 /**
01536   Notations is xmlNamedNodeMap containing the notations declared in the DTD. Duplicates are discarded. Every node in
01537   this map also implements the xmlNotation interface.
01538   The DOM Level 2 does not support editing notations, therefore notations cannot be altered in any way.
01539 */
01540 ::attribute notations get
01541 ::attribute notations set
01542 /**
01543   The public identifier of the external subset.
01544 */
01545 ::attribute publicId get
01546 ::attribute publicId set
01547 /**
01548   The system identifier of the external subset. This may be an absolute URI or not.
01549 */
01550 ::attribute systemId get
01551 ::attribute systemId set
01552 /**
01553   xmlDocumentType instance constructor.
01554   @param name - The qualified name of the document (e.g. 'gpx'), is equal to the root tagName.
01555   @param publicId - The public identifier of this document type (e.g. '-//W3C//DTD XHTML 1.0 Strict//EN').
01556   @param systemId - The system identifier for the docType (e.g. 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd').
01557 */
01558 ::method init
01559   use strict arg name, publicId, systemId
01560   self~nodeType = 10
01561   self~nodeName = name
01562   self~publicId = publicId
01563   self~systemId = systemId
01564   self~entities = .NamedNodeMap~new
01565   self~notations = .NamedNodeMap~new
01566   self~internalSubset = .nil
01567 return
01568 /* :end */
01569  
01570 /* CLASS: xmlElement */
01571 /**
01572   The Element interface represents an element in an HTML or XML document. Elements may have attributes associated with
01573   them; since the Element interface inherits from Node, the generic Node interface attribute attributes may be used to
01574   retrieve the set of all attributes for an element. There are methods on the Element interface to retrieve either an
01575   Attr object by name or an attribute value by name. In XML, where an attribute value may contain entity references, an
01576   Attr object should be retrieved to examine the possibly fairly complex sub-tree representing the attribute value. On
01577   the other hand, in HTML, where all attributes have simple string values, methods to directly access an attribute value
01578   can safely be used as a convenience.
01579  
01580   Note: In DOM Level 2, the method normalize is inherited from the Node interface where it was moved.
01581 */
01582 ::class xmlElement public subclass xmlNode
01583 /**
01584   Private method to walk the xmlNode tree and retrieve all elements with the specified tagName.
01585   @param nodes - the xmlNodes to start with, i.e. the childNodes from the receiver node.
01586   @param tag - The name odf the tag for the elements to be selected,'*' means all tags.
01587   @param nodeList - A xmlNodeList with all the selected elements in the subtree with specified tagName. 
01588 */
01589 ::method selectElements private
01590   use strict arg nodes, tag, nodeList
01591   do n=0 to nodes~length-1
01592     node = nodes~item(n)
01593     if node~nodeType==.xmlNode~elementNode then do
01594       if tag<>'*' then do
01595         if node~tagName==tag then nodeList~append(node)
01596       end
01597       else do
01598         nodeList~append(node)
01599       end
01600       if node~childNodes~length>0 then do
01601         self~selectElements(node~childNodes, tag, nodeList)
01602       end
01603     end
01604   end
01605 return
01606 /**
01607   Private method to walk the xmlNode tree and retrieve all elements from a namespace with the specified local name.
01608   @param nodes - the xmlNodes to start with, i.e. the childNodes from the receiver node.
01609   @param namespaceURI - The namespace of the elements to be selected.
01610   @param localName - The local name for the element to be selected.
01611   @param nodeList - A xmlNodeList with all the elements in the subtree with specified tagName. 
01612 */
01613 ::method selectElementsNS private
01614   use strict arg nodes, namespaceURI, localName, nodeList
01615   do n=0 to nodes~items-1
01616     node = nodes[n]
01617     if node~nodeType==.xmlNode~elementNode then do
01618       if localName<>'*' then do
01619         if node~localName==localName then do
01620           if namespaceURI<>'*' then do
01621             if node~namespaceURI==namespacURI then nodeList~append(node)
01622           end
01623           else do
01624             nodeList~append(node)
01625           end
01626         end
01627         else do
01628           nop
01629         end
01630       end
01631       else do
01632         if namespaceURI<>'*' then do
01633           if node~namespaceURI==namespacURI then nodeList~append(node)
01634         end
01635         else do
01636           nodeList~append(node)
01637         end
01638       end
01639     end
01640     if node~childNodes~items>0 then do
01641       self~getElementNodesByTagNS(node~childNodes, namespaceURI, localName, nodeList)
01642     end
01643   end
01644 return
01645 /**
01646   The type information associated with this element. 
01647 */
01648 ::method schemaTypeInfo
01649   raise syntax 93.900 array (isUnderConstruction(.context~name))
01650 return
01651 /**
01652   The name of the element. If Node <i>localName</i> is different from null, this attribute is a qualified name.
01653 */
01654 ::method tagName
01655 return self~nodeName
01656 /**
01657   xmlElement instance constructor
01658   @param tagName - The name of the xmlElement to be created.
01659  
01660   nodeValue, localName, prefix, namespaceURI and childNodes are set by the superclass xmlNode
01661 */
01662 ::method init
01663   use strict arg tagName
01664   self~init:super
01665   self~nodeName = tagname
01666   self~nodeType = .xmlNode~elementNode
01667   self~attributes = .xmlNamedNodeMap~new
01668   --self~nodeValue = .nil
01669   --self~localName = .nil
01670   --self~prefix = .nil
01671   --self~namespaceURI = .nil
01672   --self~childNodes = xmlNodeList~new
01673 return
01674 /**
01675   Retrieves an attribute value by name.
01676   @param name - The name of the attribute to retrieve.
01677   @return string - The xmlAttr value or <b>.nil</b> if that attribute does not have a specified or default value.
01678 */
01679 ::method getAttribute
01680 use strict arg name
01681 nodeValue = .nil
01682 node = self~attributes~getNamedItem(name)
01683 if node<>.nil then nodeValue = node~nodeValue
01684 return nodeValue 
01685 /**
01686   Retrieves an attribute value by local name and namespace URI.
01687   @param namespaceURI=.nil - The namespace URI of the attribute to retrieve.
01688   @param localName - The local name of the attribute to retrieve.
01689   @return string - The xmlAttr value, or the empty string if that attribute does not have a specified or default value.
01690  
01691   Per [XML Namespaces], applications must use the value null as the namespaceURI parameter for methods if they wish to
01692   have no namespace.
01693  
01694   Assumption: Attributes can not have a default namespace, thus need a prefix if they belong to a certain namespace.
01695   Assumption: A namespace can have multiple prefixes.
01696 */
01697 ::method getAttributeNS
01698   use strict arg namespaceURI=.nil, localName
01699   nodeValue = .nil
01700   if namespaceURI==.nil then do 
01701     node = self~attributes~getNamedItem(localName)
01702     if node<>.nil then nodeValue = node~nodeValue
01703   end
01704   else do
01705     prefixes = self~ownerdocument~nameSpaces[namespaceURI]
01706     found = .false
01707     if prefixes<>.nil then do i=1 to prefix~words until found
01708       prefix = prefixes~word(i)
01709       node = self~attributes~getNamedItem(prefix":"localName)
01710         if node<>.nil then do
01711           nodeValue = node~nodeValue
01712           found = .true
01713       end
01714     end
01715   end
01716 return nodeValue
01717 /**
01718   Retrieves an attribute node by name.
01719   @param name - The nodeName of the attribute to retrieve
01720   @return node - The xmlAttr node with the specified nodeName or <b>.nil</b> if there is no such attribute.
01721  
01722   To retrieve an attribute node by qualified name and namespace URI, use the getAttributeNodeNS method.
01723 */
01724 ::method getAttributeNode
01725 use strict arg name
01726 attrNode = self~attributes~getNamedItem(name)
01727 return attrNode
01728 /**
01729   Retrieves an Attr node by local name and namespace URI.
01730   @param namespaceURI=.nil - The namespace URI of the attribute to retrieve.
01731   @param localName - The local name of the attribute to retrieve.
01732   @return node - The xmlAttr node with the specified attribute local name and namespace URI or null if there is no such
01733   attribute.
01734  
01735   Per [XML Namespaces], applications must use the value null as the namespaceURI parameter for methods if they wish to 
01736   have no namespace.
01737  
01738   Assumption: Attributes can not have a default namespace, thus need a prefix if they belong to a certain namespace.
01739   Assumption: A namespace can have multiple prefixes.
01740 */
01741 ::method getAttributeNodeNS
01742   use strict arg namespaceURI=.nil, localName
01743   if namespaceURI==.nil then do 
01744     attrNode = self~attributes~getNamedItem(localName)
01745   end
01746   else do
01747     prefixes = self~ownerdocument~nameSpaces[namespaceURI]
01748     found = .false
01749     if prefixes<>.nil then do i=1 to prefix~words until found
01750       prefix = prefixes~word(i)
01751       attrNode = self~attributes~getNamedItem(prefix":"localName)
01752       if attrNode<>.nil then found = .true
01753     end
01754   end
01755 return attrNode
01756 /**
01757   Returns a xmlNodeList of all descendant xmlElements with a given tag name, in document order.
01758   @param tag - The name of the tag to match on. The special value "*" matches all tags.
01759   @return nodeList - A list of matching xmlElement nodes.
01760 */
01761 ::method getElementsByTagName
01762   use strict arg tag
01763   nodeList = .xmlNodeList~new
01764   self~selectElements(self~childNodes, tag, nodeList)
01765 return nodeList
01766 /**
01767   Returns true when an attribute with a given name is specified on this element or has a default value, false otherwise.
01768   @param name - The name of the attribute to look for.
01769   @return boolean - <b>.true</b> if an attribute with the given name is specified on this element or has a default
01770   value, <b>.false</b> otherwise.
01771 */  
01772 ::method hasAttribute
01773   use strict arg name
01774 return self~attributes~getNamedItem(name)<>.nil
01775 /**
01776   Returns true when an attribute with a given local name and namespace URI is specified on this element or has a default
01777   value, false otherwise.
01778   @param namespaceURI=.nil - The namespace URI of the attribute to look for.
01779   @param localName - The local name of the attribute to look for.
01780   @return boolean - <b>.true</b> if an attribute with the given local name and namespace URI is specified or has a
01781   default value on this element, <b>.false</b> otherwise.
01782  
01783   Per [XML Namespaces], applications must use the value <b>.nil</b> as the namespaceURI parameter for methods if they
01784   wish to have no namespace.
01785  
01786   Assumption: Attributes can not have a default namespace, thus need a prefix if they belong to a certain namespace.
01787   Assumption: A namespace can have multiple prefixes.
01788   */
01789 ::method hasAttributeNS
01790   use strict arg namespaceURI=.nil, localName
01791   boolean = .false
01792   if namespaceURI==.nil then do
01793     boolean = self~attributes~getNamedItem(name)<>.nil
01794   end
01795   prefixes = self~ownerDocument~nameSpaces[namespaceURI]
01796   if prefixes<>.nil then do
01797     do p=1 to prefixes~words until boolean==.true
01798       prefix = prefixes~word(p)
01799       boolean = self~attributes~getNamedItem(prefix':'localName)<>.nil
01800     end
01801   end
01802 return boolean
01803 /**
01804   Removes an attribute by name. 
01805   NOT supported here:
01806   (If a default value for the removed attribute is defined in the DTD, a new attribute immediately appears with the
01807   default value as well as the corresponding namespace URI, local name, and prefix when applicable. The implementation
01808   may handle default values from other schemas similarly but applications should use Document.normalizeDocument() to
01809   guarantee this information is up-to-date.)
01810   @param name - The name of the attribute to remove.
01811  
01812   If no attribute with this name is found, this method has no effect.
01813   To remove an attribute by local name and namespace URI, use the removeAttributeNS method.
01814 */
01815 ::method removeAttribute
01816 use strict arg name
01817 removed = self~attributes~removeNamedItem(name)
01818 return
01819 /**
01820   Removes an attribute by local name and namespace URI.
01821   NOT supported here:
01822   (If a default value for the removed attribute is defined in the DTD, a new attribute immediately appears with the
01823   default value as well as the corresponding namespace URI, local name, and prefix when applicable. The implementation
01824   may handle default values from other schemas similarly but applications should use Document.normalizeDocument() to
01825   guarantee this information is up-to-date.)
01826   @param nameSpaceURI=.nil - The namespace URI of the attribute to remove.
01827   @param localName - The local name of the attribute to remove.
01828  
01829   If no attribute with this local name and namespace URI is found, this method has no effect.
01830  
01831   Per [XML Namespaces], applications must use the value <b>.nil</b> as the namespaceURI parameter for methods if they
01832   wish to have no namespace.
01833 */
01834 ::method removeAttributeNS
01835   use strict arg nameSpaceURI=.nil, localName
01836   removed = self~attributes~removeNamedItemNS(namespaceURI,localName)
01837 return 
01838 /**
01839   Removes the specified attribute node. 
01840   NOT supported here:
01841   (If a default value for the removed Attr node is defined in the DTD, a new node immediately appears with the default
01842   value as well as the corresponding namespace URI, local name, and prefix when applicable. The implementation may
01843   handle default values from other schemas similarly but applications should use Document.normalizeDocument() to
01844   guarantee this information is up-to-date.)
01845   @param oldAttr - The reference to the xmlAttr to be removed.
01846   @return attr - The removed attribute.
01847   @raises user domException - NOT_FOUND_ERR perhaps
01848 */
01849 ::method removeAttributeNode
01850   use strict arg oldAttr
01851   removed = self~attributes~removeNamedItem(oldAttr~nodeName)
01852 return removed
01853 /**
01854   Adds a new attribute. If an attribute with that name is already present in the element, its value is changed to be
01855   that of the value parameter. This value is a simple string; it is not parsed as it is being set. So any markup (such
01856   as syntax to be recognized as an entity reference) is treated as literal text, and needs to be appropriately escaped
01857   by the implementation when it is written out. In order to assign an attribute value that contains entity references,
01858   the user must create an xmlAttr node plus any xmlText and xmlEntityReference nodes, build the appropriate subtree, and
01859   use <i>setAttributeNode</i> to assign it as the value of an attribute.
01860   @param name - The name of the attribute to create or alter.
01861   @param value - Value to set in string form.
01862   @raises user domException - INVALID_CHARACTER_ERR
01863  
01864   To set an attribute with a qualified name and namespace URI, use the setAttributeNS method.
01865 */
01866 ::method setAttribute
01867   use strict arg name, value
01868   if name~verify(xmlValidName())>0 then do
01869     raise user domException description (.domException~invalid_character_err)
01870   end
01871   node = self~attributes~getNamedItem(name)
01872   if node<>.nil then do
01873     node~nodeValue = value
01874   end
01875   else do
01876     node = xmlAttr~new
01877     node~nodeName = name
01878     node~nodeValue = value
01879     self~attributes~setNamedItem(node)
01880   end
01881 return 
01882 /**
01883   Adds a new attribute. If an attribute with the same local name and namespace URI is already present on the element,
01884   its prefix is changed to be the prefix part of the qualifiedName, and its value is changed to be the value parameter.
01885   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
01886   an entity reference) is treated as literal text, and needs to be appropriately escaped by the implementation when it
01887   is written out. In order to assign an attribute value that contains entity references, the user must create an Attr 
01888   node plus any Text and EntityReference nodes, build the appropriate subtree, and use <i>setAttributeNodeNS</i> or
01889   <i>setAttributeNode</i> to assign it as the value of an attribute.
01890   @param namespaceURI=.nil - The namespace URI of the attribute to create or alter.
01891   @param qualifiedName - The qualified name of the attribute to create or alter.
01892   @param value - The value to set in string form.
01893   @raises user domException - INVALID_CHARACTER_ERR
01894   @raises user domException - NAMESPACE_ERR
01895  
01896   Per [XML Namespaces], applications must use the value <b>.nil</b> as the namespaceURI parameter for methods if they
01897   wish to have no namespace.
01898 */
01899 ::method setAttributeNS
01900   use strict arg namespaceURI=.nil, qualifiedName, value
01901   if qualifiedName~verify(xmlValidName())>0 then do
01902     raise user domException description (.domException~invalid_character_err)
01903   end
01904   if qualifiedName~pos(':')>0 & namespaceURI==.nil then do
01905     raise user domException description (.domException~namespace_err)
01906   end
01907   if qualifiedName~substr(1,3)~lower=="xml" & namespaceURI<>"http://www.w3.org/XML/1998/namespace" then do
01908     raise user domException description (.domException~namespace_err)
01909   end
01910   if qualifiedName~substr(1,5)~lower=="xmlns" & namespaceURI<>"http://www.w3.org/2000/xmlns/" then do
01911     raise user domException description (.domException~namespace_err)
01912   end
01913   if qualifiedName~substr(1,5)~lower<>"xmlns" & namespaceURI=="http://www.w3.org/2000/xmlns/" then do
01914     raise user domException description (.domException~namespace_err)
01915   end
01916   localName = qualifiedName
01917   if quailifedName~pos(':')>0 then parse var qualifiedName prefix ':'localName
01918   node = self~attributes~getNamedItemNS(namespaceURI,localName)
01919   if node<>.nil then do
01920     node~nodeValue = value
01921   end
01922   else do
01923     node = xmlAttr~new
01924     node~nodeName = name
01925     node~nodeValue = value
01926     node~namespaceURI = namespaceURI
01927     node~localName = localName
01928     node~prefix = prefix
01929     self~attributes~setNamedItemNS(node)
01930   end
01931 return
01932 /**
01933   Adds a new attribute node. If an attribute with that name (nodeName) is already present in the element, it is replaced
01934   by the new one. Replacing an attribute node by itself has no effect.
01935   @param newAttr - The xmlAttr node to add to the attribute list.
01936   @return attr - If the newAttr attribute replaces an existing attribute, the replaced Attr node is returned, otherwise
01937   <b>.nil</b> is returned.
01938   @raises user domExcep[tion - WRONG_DOCUMENT_ERR
01939   @raises user domException - INUSE_ATTRIBUTE_ERR
01940  
01941   To add a new attribute node with a qualified name and namespace URI, use the setAttributeNodeNS method.
01942 */
01943 ::method setAttributeNode
01944   use strict arg newAttr
01945   if newAttr~ownerDocument<>self~ownerDocument then do
01946     raise user domException additional (.domException~wrong_document_err) description ("Attribute" newAttr~name "is owned by another document") 
01947   end
01948   if newAttr~ownerElement<>self then do 
01949     raise user domException additional (.domException~inuse_attribute_err) description (newAttr~ownerElement)
01950   end
01951   node = self~attributes~setNamedItem(newAttr)
01952 return node
01953 /**
01954   Adds a new attribute. If an attribute with that local name and that namespace URI is already present in the element,
01955   it is replaced by the new one. Replacing an attribute node by itself has no effect.
01956   @param newAttr - The xmlAttr node to add to the attribute list.
01957   @return attr - If the newAttr attribute replaces an existing attribute, the replaced Attr node is returned, otherwise
01958   <b>.nil</b> is returned.
01959   @raises user domExcep[tion - WRONG_DOCUMENT_ERR
01960   @raises user domException - INUSE_ATTRIBUTE_ERR
01961  
01962   Per [XML Namespaces], applications must use the value <b>.nil</b> as the namespaceURI parameter for methods if they
01963   wish to have no namespace.
01964 */
01965 ::method setAttributeNodeNS
01966   use strict arg newAttr
01967   node = self~attributes~setNamedItemNS(newAttr)
01968 return node
01969 /**
01970   If the parameter isId is true, this method declares the specified attribute to be a user-determined ID attribute. This
01971   affects the value of the xmlAttr <i>isId</i> meyhod and the behavior of the xmlDocument <i>getElementById</i> method,
01972   but does not change any schema that may be in use, in particular this does not affect the the xmlAttr
01973   <i>schemaTypeInfo</i> property of the specified xmlAttr node. 
01974   Use the value <b>.false</b> for the parameter isId to undeclare an attribute for being a user-determined ID attribute.
01975   @param name - The name of the attribute.
01976   @param isId - Whether the attribute is a of type ID.
01977   @raises user domException - NOT_FOUND_ERR
01978  
01979   To specify an attribute by local name and namespace URI, use the setIdAttributeNS method. 
01980 */
01981 ::method setIdAttribute
01982   use strict arg name, isId
01983   node = self~attributes~getNamedItem(name)
01984   if node==.nil then do 
01985     raise user domException description (.domException~not_found_err)
01986   end
01987   node~isId = isId
01988 return
01989 /**
01990   If the parameter isId is true, this method declares the specified attribute to be a user-determined ID attribute. This
01991   affects the value of the xmlAttr <i>isId</i> meyhod and the behavior of the xmlDocument <i>getElementById</i> method,
01992   but does not change any schema that may be in use, in particular this does not affect the the xmlAttr
01993   <i>schemaTypeInfo</i> property of the specified xmlAttr node. 
01994   Use the value <b>.false</b> for the parameter isId to undeclare an attribute for being a user-determined ID attribute.
01995   @param namespaceURI - The namespace URI of the attribute.
01996   @param localName - The local name of the attribute.
01997   @param isId - Whether the attribute is a of type ID.
01998   @raises user domException - NOT_FOUND_ERR
01999 */
02000 ::method setIdAttributeNS
02001   use strict arg namespaceURI, localName, isId
02002   node = self~attributes~getNamedItemNS(namespaceURI, localName)
02003   if node==.nil then do
02004     raise user domException description (.domException~not_found_err)
02005   end
02006   node~isId = isId
02007 return
02008 /**
02009   If the parameter isId is true, this method declares the specified attribute to be a user-determined ID attribute. This
02010   affects the value of the xmlAttr <i>isId</i> meyhod and the behavior of the xmlDocument <i>getElementById</i> method,
02011   but does not change any schema that may be in use, in particular this does not affect the the xmlAttr
02012   <i>schemaTypeInfo</i> property of the specified xmlAttr node. 
02013   Use the value <b>.false</b> for the parameter isId to undeclare an attribute for being a user-determined ID attribute.
02014   @param idAttr -
02015   @param isId - 
02016   @raises user domException - NOT_FOUND_ERR
02017 */
02018 ::method setIdAttributeNode
02019   use strict arg idAttr, isId
02020   if idAttr~ownerElement<>self then do
02021     raise user domException description(.domException~not_found_err)
02022   end
02023   idAttr~isId = isId
02024 return
02025 /* :end */
02026  
02027 /* CLASS: xmlDocument */
02028 /**
02029   The xmlDocument interface represents the entire HTML or XML document. Conceptually, it is the root of the document
02030   tree, and provides the primary access to the document's data.
02031  
02032   Since elements, text nodes, comments, processing instructions, etc. cannot exist outside the context of a Document,
02033   the xmlDocument interface also contains the factory methods needed to create these objects. The xmlNode objects
02034   created have a ownerDocument attribute which associates them with the Document within whose context they were created.
02035 */
02036 ::class xmlDocument public subclass xmlNode
02037 /**
02038   A directory with elementIds as index and the associated xmlElement as item.
02039 */
02040 ::attribute elementIds private
02041 /**
02042   A directory with tagNames as index and an array of xmlElement objects with the tagName as objects
02043 */
02044 ::attribute elementTags private
02045 /**
02046   A directory with namespaceURIs as index and their prefix as item
02047 */
02048 ::attribute nameSpaces private
02049 /**
02050   The Document Type Declaration (see DocumentType) associated with this document. For XML documents without a document
02051   type declaration this returns <b>.nil</b>. For HTML documents, a DocumentType object may be returned, independently of
02052   the presence or absence of document type declaration in the HTML document.
02053  
02054   This provides direct access to the xmlDocumentType node, child node of this xmlDocument. This node can be set a
02055   t document creation time and later changed through the use of child nodes manipulation methods, such as xmlNode's 
02056   <i>insertBefore</i>, or xmlNode's <i>replaceChild</i>. 
02057  
02058   Note, however, that while some implementations may instantiate different types of Document objects supporting
02059   additional features than the "Core", such as "HTML" [DOM Level 2 HTML], based on the xmlDocumentType specified at
02060   creation time, changing it afterwards is very unlikely to result in a change of the features supported.
02061 */ 
02062 ::attribute docType get
02063 /**
02064 */
02065 ::attribute docType set
02066 /**
02067   This is a convenience attribute that allows direct access to the child node that is the document element of 
02068   the document.
02069 */
02070 ::attribute documentElement get
02071 /**
02072 */
02073 ::attribute documentElement set
02074 /**
02075   The location of the document or <b>.nil</b> if undefined or if the Document was created using xmlDOMImplementation
02076   <i>createDocument</i>. No lexical checking is performed when setting this attribute; this could result in a
02077   <b>.nil</b> value returned when using xmlNode <i>baseURI</i>. 
02078  
02079   Beware that when the Document supports the feature "HTML" [DOM Level 2 HTML], the href attribute of the HTML BASE 
02080   element takes precedence over this attribute when computing xmlNode <i>baseURI</i>. 
02081 */
02082 ::attribute documentURI
02083 /**
02084   The configuration used when xmlDocument <i>normalizeDocument</i> is invoked. 
02085 */ 
02086 ::attribute domConfig get
02087 /**
02088 */
02089 ::attribute domConfig set
02090 /**
02091   The xmlDOMImplementation object that handles this document. A DOM application may use objects from multiple
02092   implementations.
02093   The attributes setter method ("IMPLEMENTATION=") starts out as <i>public</i> and is set to <i>private</i> once set
02094   turning the attribute into a <i>read-only</i>.
02095 */
02096 ::attribute implementation get
02097 ::attribute implementation set 
02098 /**
02099   An attribute specifying the encoding used for this document at the time of the parsing. This is null when it is not
02100   known, such as when the xmlDocument was created in memory.
02101 */
02102 ::attribute inputEncoding get
02103 ::attribute inputEncoding set
02104 /**
02105   An attribute specifying whether error checking is enforced or not. When set to <b>.false</b>, the implementation is 
02106   free to not test every possible error case normally defined on DOM operations, and not raise any xmlDOMException on
02107   DOM operations or report errors while using xmlDocument <i>normalizeDocument</i>. In case of error, the behavior is
02108   undefined. This attribute is true by default.
02109 */
02110 ::attribute strictErrorChecking 
02111 /**
02112   An attribute specifying, as part of the XML declaration, the encoding of this document. This is <b>.nil</b> when
02113   unspecified or when it is not known, such as when the Document was created in memory.
02114 */
02115 ::attribute xmlEncoding
02116 /**
02117   An attribute specifying, as part of the XML declaration, whether this document is standalone. This is <b>.false</b>
02118   when unspecified.
02119  
02120   Note: No verification is done on the value when setting this attribute. Applications should use xmlDocument
02121   <i>normalizeDocument</i> with the "validate" parameter to verify if the value matches the validity constraint for
02122   standalone document declaration as defined in [XML 1.0]. 
02123 */
02124 ::attribute xmlStandalone
02125 /**
02126   An attribute specifying, as part of the XML declaration, the version number of this document. If there is no
02127   declaration and if this document supports the "XML" feature, the value is "1.0". If this document does not support the
02128   "XML" feature, the value is always null. Changing this attribute will affect methods that check for invalid characters
02129   in XML names. Application should invoke xmlDocument <i>normalizeDocument</i> in order to check for invalid characters
02130   in the Nodes that are already part of this Document.
02131  
02132   DOM applications may use the xmlDOMImplementation <i>hasFeature(feature, version)</i> method with parameter values
02133   "XMLVersion" and "1.0" (respectively) to determine if an implementation supports [XML 1.0]. DOM applications may use
02134   the same method with parameter values "XMLVersion" and "1.1" (respectively) to determine if an implementation supports
02135   [XML 1.1]. In both cases, in order to support XML, an implementation must also support the "XML" feature defined in
02136   this specification. Document objects supporting a version of the "XMLVersion" feature must not raise a
02137   NOT_SUPPORTED_ERR exception for the same version number when using xmlDocument <i>xmlVersion</i>. 
02138  
02139   @raises user domException - NOT_SUPPORTED_ERR
02140  
02141   Raised if the version is set to a value that is not supported by this Document or if this document does not support
02142   the "XML" feature.  
02143 */
02144 ::attribute xmlVersion
02145 /**
02146   xmlDocument instance constructor
02147 */
02148 ::method init
02149   -- public attributes
02150   self~init:super
02151   self~nodeType = .xmlNode~documentNode
02152   self~nodeName = "#document"
02153   self~nodeValue = .nil
02154   self~attributes = .nil
02155   self~parentNode = .nil
02156   self~previousSibling = .nil
02157   self~nextSibling = .nil
02158   self~ownerDocument = .nil
02159   --self~docType = .nil same as implementation
02160   --self~implementation = .xmlDomImplementation~new -- This one is set by .xmlDomImplementation <i>createDocument</i> method
02161   -- private attributes
02162   self~elementIds = .directory~new
02163   self~elementTags = .directory~new
02164   self~nameSpaces = .directory~new
02165 return
02166 /**
02167   Attempts to adopt a node from another document to this document. If supported, it changes the ownerDocument of the
02168   source node, its children, as well as the attached attribute nodes if there are any. If the source node has a parent
02169   it is first removed from the child list of its parent. This effectively allows moving a subtree from one document to
02170   another (unlike <i>importNode</i> which create a copy of the source node instead of moving it). When it fails,
02171   applications should use xmlDocument <i>importNode</i> instead. 
02172  
02173   Note that if the adopted node is already part of this document (i.e. the source and target document are the same),
02174   this method still has the effect of removing the source node from the child list of its parent, if any. The following
02175   list describes the specifics for each type of node. 
02176   <ul>
02177   <li>ATTRIBUTE_NODE - The ownerElement attribute is set to null and the specified flag is set to true on the adopted
02178   xmlAttr. The descendants of the source xmlAttr are recursively adopted.</li>
02179   <li>DOCUMENT_FRAGMENT_NODE - The descendants of the source node are recursively adopted.</li>
02180   <li>DOCUMENT_NODE - Document nodes cannot be adopted.</li>
02181   <li>DOCUMENT_TYPE_NODE - DocumentType nodes cannot be adopted.</li>
02182   <li>ELEMENT_NODE - Specified attribute nodes of the source element are adopted. Default attributes are discarded,
02183   though if the document being adopted into defines default attributes for this element name, those are assigned. The
02184   descendants of the source element are recursively adopted.</li>
02185   <li>ENTITY_NODE - Entity nodes cannot be adopted.</li>
02186   <li>ENTITY_REFERENCE_NODE - Only the EntityReference node itself is adopted, the descendants are discarded, since the
02187   source and destination documents might have defined the entity differently. If the document being imported into
02188   provides a definition for this entity name, its value is assigned.</li>
02189   <li>NOTATION_NODE - Notation nodes cannot be adopted.</li>
02190   <li>PROCESSING_INSTRUCTION_NODE, TEXT_NODE, CDATA_SECTION_NODE, COMMENT_NODE - These nodes can all be adopted. No
02191   specifics.</li>
02192   </ul>
02193  
02194   Note: Since it does not create new nodes unlike the xmlDocument <i>importNode</i> method, this method does not raise
02195   an INVALID_CHARACTER_ERR exception, and applications should use the xmlDocument <i>normalizeDocument</i> method to
02196   check if an imported name is not an XML name according to the XML version in use.
02197   @param source - The xmlNode to move into this document.
02198   @return node - The adopted node, or <b>.nil</b> if this operation fails, such as when the source node comes from a 
02199   different implementation.
02200 */
02201 ::method adoptNode 
02202   use strict arg source
02203   raise syntax 93.900 array (isUnderConstruction(.context~name))
02204 return
02205 /**
02206   Creates an xmlAttr of the given name. Note that the xmlAttr instance can then be set on an xmlElement using the
02207   <i>setAttributeNode</i> method. 
02208   The new xmlAttr has the <i>nodeName</i> attribute set to <i>name</i>, and <i>localName</i>, <i>prefix</i>, and
02209   <i>namespaceURI</i> set to null. The value of the attribute is the empty string.
02210   @param name - The name of the attribute.
02211   @param value=.nil - The (optional) value of the attribute
02212   @return attr - A new Attr object
02213   @raises user domException - INVALID_CHARACTER_ERR
02214  
02215   Raised if the specified name is not an XML name according to the XML version in use specified in the xmlDocument
02216   <i>xmlVersion</i> attribute.
02217   To create an attribute with a qualified name and namespace URI, use the <i>createAttributeNS</i> method.
02218 */
02219 ::method createAttribute
02220   use strict arg name, value=.nil
02221   if name~verify(xmlValidName())>0 
02222     then raise user domException description (.domException~invalid_character_err)
02223   attr = .xmlAttr~new
02224   --attr~name = name
02225   attr~nodeName = name
02226   attr~localName = .nil
02227   attr~prefix = .nil
02228   attr~namespaceURI = .nil
02229   attr~nodeValue = value
02230   --attr~value = .nil
02231   attr~ownerDocument = self
02232 return attr
02233 /**
02234   Creates an attribute of the given qualified name and namespace URI.
02235   @param namespaceURI=.nil - The optional namespace URI of the attribute to create.
02236   @param qualifiedName - The qualified name of the attribute to instantiate.
02237   @return attr - A new xmlAttr object with the following attributes:
02238  
02239   <ul>
02240   <li>nodeName - The specified qualifiedName.</li>
02241   <li>namespaceURI - The specified namespaceURI.</li>
02242   <li>prefix - prefix, extracted from qualifiedName, or null if there is no prefix.</li>
02243   <li>localName - name, extracted from the specified qualifiedName.</li>
02244   <li>name - The specified qualifiedName.</li>
02245   <li>nodeValue - An empty string (i.e. "").</li>
02246   </ul>
02247   @raises user domException - INVALID_CHARACTER_ERR
02248   @raises user domException - NAMESPACE_ERR
02249  
02250   Per [XML Namespaces], applications must use the value null as the namespaceURI parameter for methods if they wish to
02251   have no namespace.
02252 */
02253 ::method createAttributeNS
02254   use strict arg namespaceURI=.nil, qualifiedName
02255   if qualifiedName~verify(xmlValidName())>0 
02256     then raise user domException description (.domException~invalid_character_err)
02257   exception = .false
02258   if qualifiedName~countStr(':')>1 then exception = .true
02259   prefix = ''
02260   localName = qualifiedName
02261   if qualifiedName~countStr(':')==1 then do
02262     parse var qualifiedName prefix ':' localName
02263     if prefix=='XML' & namesapceURI<>"http://www.w3.org/XML/1998/namespace" then exception = .true 
02264     -- 2 more conditions to check, will be todo
02265   end
02266   if exception==.true then raise user domException description (.domException~namespace_err)
02267   attr = .xmlAttr~new
02268   attr~ nodeName = qualifiedName
02269   attr~namespaceURI = namespaceURI
02270   attr~prefix = prefix
02271   attr~localName = localName
02272   attr~name = qualifiedName
02273   attr~nodeValue = ''
02274 return attr
02275 /**
02276   Creates a xmlCDATASection node whose value is the specified string.
02277   @param data - The data for the node.
02278   @return cdata - The new xmlCDATASection object.
02279 */
02280 ::method createCDATASection 
02281   use strict arg data
02282   cdata = .xmlCDATASection~new(data)
02283 return cdata
02284 /**
02285   Creates a xmlComment node given the specified string.
02286   @param data - The data for the node
02287   @return comment - The new xmlComment object
02288 */
02289 ::method createComment
02290   use strict arg data
02291   comment = .xmlComment~new(data)
02292 return comment
02293 /**
02294   Creates an empty DocumentFragment object.
02295   @return docFragment - The newly created empty xmlDocumentFragment
02296 */
02297 ::method createDocumentFragment
02298   use strict arg
02299   docFragment = .xmlDocumentFragment~new
02300 return docFragment
02301 /**
02302   Creates an element of the type specified. Note that the instance returned implements the Element interface, so
02303   attributes can be specified directly on the returned object. The new xmlElement object will have the nodeName
02304   attribute set to <i>tagName</i>, and localName, prefix, and namespaceURI set to null. 
02305   @param tagName - The name(case-sensitive for XML) of the element type to instantiate. 
02306  
02307   NOT YET!!!!!
02308   In addition, if there are known attributes with default values, xmlAttr nodes representing them are automatically 
02309   created and attached to the element.
02310   @return element - A new xmlElement as described above.
02311   @raises user domExceptuion - INVALID_CHARACTER_ERR
02312  
02313   To create an element with a qualified name and namespace URI, use the createElementNS method.
02314 */
02315 ::method createElement
02316   use strict arg tagName
02317   if tagName~verify(xmlValidName())>0
02318     then raise user domException description (.domException~invalid_character_err)
02319   element = .xmlElement~new(tagName)
02320   element~ownerDocument = self
02321   --if self~elementTags[tagName]==.nil then self~elementTags[tagName] = .xmlNodelist~new
02322   --self~elementTags[tagName]~append(element)
02323 return element
02324 /**
02325   Creates an element of the given qualified name and namespace URI.
02326   @param namespaceURI=.nil - The optional namespace URI of the element to create.
02327   @param qualifiedName - The qualified name of the element type to instantiate.
02328   @return attr - A new xmlAttr object with the following attributes:
02329  
02330   <ul>
02331   <li>nodeName - The specified qualifiedName.</li>
02332   <li>namespaceURI - The specified namespaceURI.</li>
02333   <li>prefix - prefix, extracted from qualifiedName, or null if there is no prefix.</li>
02334   <li>localName - name, extracted from the specified qualifiedName.</li>
02335   <li>tagName - The specified qualifiedName.</li>
02336   </ul>
02337   @raises user domException - INVALID_CHARACTER_ERR
02338   @raises user domException - NAMESPACE_ERR
02339  
02340  
02341   Per [XML Namespaces], applications must use the value null as the namespaceURI parameter for methods if they wish to
02342   have no namespace.
02343 */
02344 ::method createElementNS
02345   use strict arg namespaceURI=.nil, qualifiedName
02346   if qualifiedName~verify(xmlValidName())>0
02347     then raise user domException description (.domException~invalid_character_err)
02348   exception = .false
02349   if qualifiedName~countStr(':')>1 then exception = .true
02350   prefix = ''
02351   localName = qualifiedName
02352   if qualifiedName~countStr(':')==1 then do
02353     parse var qualifiedName prefix ':' localName
02354     if prefix=='XML' & namesapceURI<>"http://www.w3.org/XML/1998/namespace" then exception = .true 
02355     -- more conditions to check, will be todo
02356   end
02357   if exception==.true then raise user domException description (.domException~namespace_err)
02358   element = .xmlElement~new
02359   element~nodeName = qualifiedName
02360   element~namespaceURI = namespaceURI
02361   element~prefix = prefix
02362   element~localName = localName
02363   element~tagName = qualifiedName
02364 return element
02365 /**
02366   Creates a xmlEntityReference object. In addition, if the referenced entity is known, the child list of the
02367   xmlEntityReference node is made the same as that of the corresponding xmlEntity node.
02368   @param name - The name of the reference
02369  
02370   Note: If any descendant of the Entity node has an unbound namespace prefix, the corresponding descendant of the
02371   created EntityReference node is also unbound; (its namespaceURI is null). The DOM Level 2 and 3 do not support any
02372   mechanism to resolve namespace prefixes in this case.
02373 */
02374 ::method createEntityReference
02375   use strict arg name
02376   raise syntax 93.900 array (isUnderConstruction(.context~name))
02377 return
02378 /**
02379   Creates a xmlProcessingInstruction node given the specified target and data strings.
02380   @param target - The target part of the processing instruction
02381   @param data - The data for the node
02382   @return pi - The new xmlProcessingInstruction object
02383   @raises user domException - INVALID_CHARACTER_ERR
02384 */
02385 ::method createProcessingInstruction
02386   use strict arg target, data
02387   if target~verify(xmlValidName())>0 
02388     then raise user domException description (.domException~invalid_character_err)
02389   pi = .xmlPI~new(target, data)
02390 return pi
02391 /**
02392   Creates a xmlText node given the specified string.
02393   @param data - The data for the node
02394   @return text - The new xmlText object
02395 */
02396 ::method createTextNode
02397   use arg data
02398   text = .xmlText~new(data)
02399 return text
02400 /**
02401   Returns the xmlElement that has an ID attribute with the given value. If no such element exists, this returns null. If
02402   more than one element has an ID attribute with that value, what is returned is undefined. 
02403  
02404   <b.<u>NOTE</u></b> - Attributes with the name "ID" or "id" are not of type ID unless so defined.
02405  
02406   @param elementId - The unique id value for an element.
02407   @return element - The matching element or <b>.nil</b> if there is none.
02408  
02409   The DOM implementation is expected to use the attribute Attr~isId to determine if an attribute is of type ID. 
02410 */
02411 ::method getElementById
02412   use strict arg elementId
02413   element = self~elementIds[elementId]
02414 return element
02415 /**
02416   Returns a xmlNodeList of all the xmlElements in document order with a given tag name and are within in the document.
02417   @param tagName - The name of the tag to match on. The special value "*" matches all tags.
02418   @return nodeList - A new xmlNodeList object containing all the matched xmlElements.
02419  
02420   For XML, the tagname parameter is case-sensitive, otherwise it depends on the case-sensitivity of the markup language
02421   in use. 
02422 */
02423 ::method getElementsByTagName
02424   use strict arg tagName
02425   elements = .xmlNodeList~new
02426   self~selectElements(self~childNodes, tagName, elements)
02427 return elements
02428 /**
02429    Private method to walk the nodes tree and retrieve nodes by tagName
02430    @param nodes - The sibling nodes to walk thru.
02431    @param tag - The name of the tag to select on.
02432    @param nodelist - The xmlNodeList to append selected nodes to.
02433 */
02434 ::method selectElements private
02435   use strict arg nodes, tag, nodelist
02436   do n=0 to nodes~length-1
02437     node = nodes~item(n)
02438     if (node~nodeType==.xmlNode~elementNode) then do
02439       if tag<>'*' then do
02440         if (node~tagName==tag) then nodelist~append(node)
02441       end
02442       else do
02443         nodelist~append(node)
02444       end
02445       if (node~childNodes~length>0) then do
02446         self~selectElements(node~childNodes, tag, nodelist)
02447       end
02448     end
02449   end
02450 return
02451 /**
02452   Returns a xmlNodeList of all the xmlElements with a given local name and namespace URI in document order.
02453   @param namespaceURI=.nil - The namespace URI of the elements to match on. The special value "*" matches all namespaces.
02454   @param localName - The local name of the elements to match on. The special value "*" matches all local names.
02455   @return nodeList - A new xmlNodeList containing all the matched xmlElements.
02456 */
02457 ::method getElementsByTagNameNS
02458   use strict arg namespaceURI=.nil, localName
02459   raise syntax 93.900 array (isUnderConstruction(.context~name))
02460 return
02461 /**
02462   Imports a node from another document to this document, without altering or removing the source node from the original
02463   document; this method creates a new copy of the source node. The returned node has no parent; (parentNode is null).
02464  
02465   For all nodes, importing a node creates a node object owned by the importing document, with attribute values identical
02466   to the source node's nodeName and nodeType, plus the attributes related to namespaces (prefix, localName, and
02467   namespaceURI). As in the cloneNode operation, the source node is not altered. User data associated to the imported
02468   node is not carried over. However, if any UserDataHandlers has been specified along with the associated data these 
02469   handlers will be called with the appropriate parameters before this method returns.
02470  
02471   Additional information is copied as appropriate to the nodeType, attempting to mirror the behavior expected if a
02472   fragment of XML or HTML source was copied from one document to another, recognizing that the two documents may have
02473   different DTDs in the XML case. 
02474  
02475   The following list describes the specifics for each type of node.
02476   <ul>
02477   <li>ATTRIBUTE_NODE - The ownerElement attribute is set to null and the specified flag is set to true on the generated
02478   xmlAttr. The descendants of the source xmlAttr are recursively imported and the resulting nodes reassembled to form
02479   the corresponding subtree.
02480   <b><u>NOTE</u></b> - The deep parameter has no effect on xmlAttr nodes; they always carry their children with them
02481   when imported.</li>
02482   <li>DOCUMENT_FRAGMENT_NODE - If the deep option was set to true, the descendants of the source DocumentFragment are
02483   recursively imported and the resulting nodes reassembled under the imported DocumentFragment to form the corresponding
02484   subtree. Otherwise, this simply generates an empty DocumentFragment.</li>
02485   <li>DOCUMENT_NODE - Document nodes cannot be imported.</li>
02486   <li>DOCUMENT_TYPE_NODE - DocumentType nodes cannot be imported.</li>
02487   <li>ELEMENT_NODE - Specified attribute nodes of the source element are imported, and the generated xmlAttr nodes are
02488   attached to the generated xmlElement. Default attributes are not copied, though if the document being imported into
02489   defines default attributes for this element name, those are assigned. If the importNode deep parameter was set to
02490   true, the descendants of the source element are recursively imported and the resulting nodes reassembled to form the
02491   corresponding subtree.</li>
02492   <li>ENTITY_NODE - Entity nodes can be imported, however in the current release of the DOM the xmlDocumentType is
02493   readonly. Ability to add these imported nodes to a xmlDocumentType will be considered for addition to a future release
02494   of the DOM.</li>
02495   <li>ENTITY_REFERENCE_NODE - Only the EntityReference itself is copied, even if a deep import is requested, since the
02496   source and destination documents might have defined the entity differently. If the document being imported into
02497   provides a definition for this entity name, its value is assigned.</li>
02498   <li>NOTATION_NODE - Notation nodes can be imported, however they are read-only</li>
02499   <li>PROCESSING_INSTRUCTION_NODE - The imported node copies its target and data from those of the source node.</li>
02500   <li>TEXT_NODE, CDATA_SECTION_NODE, COMMENT_NODE - These three types of nodes inheriting from xmlCharacterData copy
02501   their data and length attributes from those of the source node.</li>
02502   </ul>
02503   @param importNode - The node to import
02504   @param deep=.false - optional boolean to indicate a deep copy
02505   @return node - the imported node that belongs to this xmlDocument now.
02506   @raises user domException - INVALID_CHARACTER_ERR
02507 */
02508 ::method importNode 
02509   use strict arg importNode, deep=.false 
02510   raise syntax 93.900 array (isUnderConstruction(.context~name))
02511 return
02512 /**
02513   This method acts as if the document was going through a save and load cycle, putting the document in a "normal" form.
02514   As a consequence, this method updates the replacement tree of EntityReference nodes and normalizes Text nodes, as
02515   defined in the method xmlNode <i>normalize</i>. 
02516  
02517   Otherwise, the actual result depends on the features being set on the Document.domConfig object and governing what
02518   operations actually take place. Noticeably this method could also make the document namespace well-formed according to
02519   the algorithm described in Namespace Normalization, check the character normalization, remove the CDATASection nodes,
02520   etc. See DOMConfiguration for details. 
02521  
02522   Mutation events, when supported, are generated to reflect the changes occurring on the document.
02523  
02524   If errors occur during the invocation of this method, such as an attempt to update a read-only node or a Node.nodeName
02525   contains an invalid character according to the XML version in use, errors or warnings (DOMError.SEVERITY_ERROR or
02526   DOMError.SEVERITY_WARNING) will be reported using the DOMErrorHandler object associated with the "error-handler"
02527   parameter. Note this method might also report fatal errors (DOMError.SEVERITY_FATAL_ERROR) if an implementation cannot
02528   recover from an error. 
02529 */
02530 ::method normalizeDocument
02531   use strict arg
02532   raise syntax 93.900 array (isUnderConstruction(.context~name))
02533 return
02534 /**
02535   Rename an existing node of type ELEMENT_NODE or ATTRIBUTE_NODE.
02536  
02537   When possible this simply changes the name of the given node, otherwise this creates a new node with the specified
02538   name and replaces the existing node with the new node as described below.
02539  
02540   If simply changing the name of the given node is not possible, the following operations are performed: a new node is
02541   created, any registered event listener is registered on the new node, any user data attached to the old node is
02542   removed from that node, the old node is removed from its parent if it has one, the children are moved to the new node,
02543   if the renamed node is an Element its attributes are moved to the new node, the new node is inserted at the position 
02544   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
02545   node is attached to the new node.
02546  
02547   When the node being renamed is an Element only the specified attributes are moved, default attributes originated from
02548   the DTD are updated according to the new element name. In addition, the implementation may update default attributes
02549   from other schemas. Applications should use Document.normalizeDocument() to guarantee these attributes are up-to-date.
02550  
02551   When the node being renamed is an Attr that is attached to an Element, the node is first removed from the Element
02552   attributes map. Then, once renamed, either by modifying the existing node or creating a new one as described above, it
02553   is put back.
02554   In addition:
02555   <ul>
02556   <li>a user data event NODE_RENAMED is fired</li> 
02557   <li>when the implementation supports the feature "MutationNameEvents", each mutation operation involved in this method
02558   fires the appropriate event, and in the end the event {http://www.w3.org/2001/xml-events, DOMElementNameChanged} or
02559   {http://www.w3.org/2001/xml-events, DOMAttributeNameChanged} is fired.</li>
02560   <\ul>
02561   @param node - The node to rename
02562   @param namespaceURI=.nil - The new namespace URI.
02563   @param qualifiedName - The new qualified name.
02564   @return node - The renamed node. 
02565  
02566   The renamed node is either the specified node or the new node that was created to replace the specified node.
02567  
02568   @raises user domException - NOT_SUPPORTED_ERR
02569   @raises user domException - INVALID_CHARACTER_ERR
02570   @raises user domException - WRONG_DOCUMENT_ERR
02571   @raises user domException - NAMESPACE_ERR
02572 */
02573 ::method renameNode
02574   use strict arg node, namespaceURI=.nil, qualifiedName
02575   raise syntax 93.900 array (isUnderConstruction(.context~name))
02576 return 
02577 /* :end */
02578  
02579 /* CLASS: xmlDomImplementation */
02580 /**
02581   The xmlDomImplementation interface provides a number of methods for performing operations that are independent of any
02582   particular instance of the document object model. 
02583 */
02584 ::class xmlDomImplementation public 
02585 ::attribute features private
02586 ::method init
02587   use strict arg
02588   self~init:super
02589   self~features = .directory~new
02590   self~features["core"] = .directory~new~~putall(.array~of("",1.0,2.0))
02591   self~features["xml"] = .directory~new~~putall(.array~of("",1.0,2.0))
02592   self~features["ls-load"] = .directory~new~~putall(.array~of("",3.0))
02593 return
02594 /**
02595   Creates a DOM Document object of the specified type with its document element.
02596  
02597   Note that based on the DocumentType given to create the document, the implementation may instantiate specialized
02598   Document objects that support additional features than the "Core", such as "HTML" [DOM Level 2 HTML]. On the other
02599   hand, setting the DocumentType after the document was created makes this very unlikely to happen. Alternatively,
02600   specialized Document creation methods, such as createHTMLDocument [DOM Level 2 HTML], can be used to obtain specific
02601   types of Document objects.
02602   @param namespaceURI='' - The (optional) namespace URI of the document element to create or <b>.nil</b>.
02603   @param qualifiedName='' - The (optional) qualified name of the document element to be created or null.
02604   @param docType=.nil - The (optional) type of document to be created or <b..nil</b>.
02605   @return document - A new xmlDocument object with its document element. 
02606   @raises user - domException.INVALID_CHARACTER_ERR
02607   @raises user - domException.NAMESPACE_ERR
02608  
02609   If the namespaceURI, qualifiedName, and docType are <b>.nil</b>, the returned xmlDocument is empty with no document
02610   element.
02611   When <b>docType</b> is not <b>.nil</b>, its <i>ownerDocument</i> attribute is set to the document being created.
02612 */
02613 ::method createDocument
02614   use strict arg namespaceURI='', qualifiedName='', docType=.nil 
02615   if qualifiedName~verify(xmlValidName())>0 
02616     then raise user domException description (.domException~INVALID_CHARACTER_ERR)
02617   prefix = ''
02618   localName = qualifiedName
02619   if qualifiedName~countStr(':')>1 
02620     then raise user domException additional (.domException~namespace_err) description ("Qualified name can contain only one ':' character.")
02621   if qualifiedName~countStr(':')==1 then parse var qualifiedName prefix':'localName
02622   if prefix<>'' & namespaceURI=='' 
02623     then raise user domException additional (.domException~NAMESPACE_ERR) description ("Cannot have a prefix without <i>namespaceURI</i>.") 
02624   if namespaceURI<>'' & qualifiedName=='' 
02625     then raise user domException additional (.domException~NAMESPACE_ERR) description ("Cannot have namespaceURI without prefix.")
02626   if prefix~upper=='XML' & namespaceURI~lower<>'http://www.w3.org/XML/1998/namespace'
02627     then raise user domException additional (.domException~NAMESPACE_ERR) description ("Invalid namespaceURI for prefix" prefix".")    
02628   if docType<>.nil then do
02629     if docType~isA(.xmlDocType) then do
02630       if docType~ownerDocument<>.nil then raise user domException additional (.domException~WRONG_DOCUMENT_ERR) description ("DOCTYTPE belongs to different document.")
02631     end
02632     else raise user domException additional (.domException~SYNTAX_ERR) description ("Argument is NOT a .xmlDocType.")
02633   end
02634   --trace i
02635   document = .xmlDocument~new
02636   document~implementation = self
02637   document~prefix = prefix
02638   document~localName = localName
02639   document~namespaceURI = namespaceURI
02640   if docType<>.nil then do 
02641     document~appendChild(docType) 
02642     docType~ownerDocument = document
02643   end
02644   document~docType = docType
02645   --if namespaceURI<>.nil | qualifiedName<>.nil | docType<>.nil then do 
02646   --  documentElement = document~createElement(qualifiedName)
02647   --  document~appendChild(documentElement)
02648   --  document~documentElement = documentElement
02649   --end
02650 return document
02651 /**
02652   Creates an empty DocumentType node. Entity declarations and notations are not made available. Entity reference
02653   expansions and default attribute additions do not occur.
02654   @param qualifiedName - The qualified name for to new document (e.g. 'gpx')
02655   @param publicId - The public identifier of this document type (e.g. '-//W3C//DTD XHTML 1.0 Strict//EN')
02656   @param systemId - The system identifier for the document type (e.g. 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd')
02657   @return node - An empty xmlDocumentType node.
02658 */
02659 ::method createDocumentType
02660   use strict arg qualifiedName, publicId, systemId
02661   raise syntax 93.900 array (isUnderConstruction(.context~name))
02662 return
02663 /**
02664   This method returns a specialized object which implements the specialized APIs of the specified feature and version,
02665   as specified in DOM Features. The specialized object may also be obtained by using binding-specific casting methods
02666   but is not necessarily expected to, as discussed in Mixed DOM Implementations. This method also allow the
02667   implementation to provide specialized objects which do not support the DOMImplementation interface. 
02668   @param feature - The name of the feature requested. 
02669   @param version - This is the version number of the feature to test.
02670   @return object - Returns a xmlDomObject or <b>.nil</b>.
02671  
02672   The returned xmlDomObject which implements the specialized APIs of the specified feature and version, it is
02673   <b>.nil</b> if there is no object which implements interfaces associated with that feature.
02674  
02675   <b><u>NOTE</u>,/b> - The DOM Level 3 Feature handler support is not currently implemented, therefore <i>getFeature</i>
02676   will always return <b>.nil</b>.
02677 */
02678 ::method getFeature
02679   use strict arg feature, version
02680   featureHandler = .nil
02681   versions = self~features[feature~lower]
02682   if versions<>.nil then do
02683     featureHandler = versions~index(feature)
02684   end
02685 return featureHandler
02686 /**
02687   Test if the DOM implementation implements a specific feature and version, as specified in DOM Features.
02688   @param feature - The name of the feature requested. 
02689   @param version='' - This is the (optional) version number of the feature to test.
02690   @return boolean - Returns <b>.true</b> if the feature is implemented in the specified version, <b>.false</b>
02691   otherwise.
02692 */
02693 ::method hasFeature
02694   use strict arg feature, version=''
02695   versions = self~features[feature~lower]
02696   if versions<>.nil then do
02697     featureSupported = versions~index[feature~lower]
02698   end
02699 return featureSupported<>.nil
02700 /* :end */
02701  
02702 /* CLASS: domBuilder */
02703 /**
02704  
02705 */
02706 ::class dom1Builder public 
02707 /**
02708   The DOM (Level 1) implementation for building a DOM (Level 1)
02709  
02710   <b><u>NOTE</u></b> - The <i>domImplementation</i> is currently only used for it's <i>createDocument</i> method.
02711 */
02712 ::attribute dom private
02713 /**
02714   The DOM document resulting from the XML Parser and DOM (Level 1) builder.
02715 */
02716 ::attribute doc get
02717 ::attribute doc set private
02718 /**
02719   The stack of nested elements with childnodes.
02720  
02721   <b><u>NOTE</u></b> - nodeStack[1] represents the current active Element node.
02722 */
02723 ::attribute nodeStack private
02724 /**
02725   Represents the current active Attr node
02726 */
02727 ::attribute attrNode private
02728 /**
02729   Flag to indicate if the convenience attribute <i>documentElement</i> must be set or not.
02730 */
02731 ::attribute haveDocumentElement private
02732 /**
02733   DOM Builder instance constructor
02734  
02735   <b><u>NOTE</u></b> - domImplementation was introduced in DOM Level2, it is used here only to create a document with no
02736   namespace and doctype.
02737 */
02738 ::method init
02739   self~dom = .xmlDomImplementation~new
02740   self~nodeStack = .queue~new
02741   self~haveDocumentElement = .false
02742 return
02743 /**
02744   The method invoker wants to start a new DOM document. A DOM Level1 document is created with the help of the DOM Level2
02745   DomImplemetation interface.
02746   @param content=.nil - Currently ignored, if present
02747 */
02748 ::method startDocument
02749   use strict arg content=.nil
02750   self~doc = self~dom~createDocument()
02751   self~nodeStack~push(self~doc)
02752 return
02753 /**
02754   Signals the end of DOM building process. At this stage the stack with active nodes should only have the document node
02755   as content.
02756 */
02757 ::method endDocument
02758   use strict arg
02759   -- stack should have just 1 item now
02760   if self~nodeStack~items<>1 then do
02761     raise syntax 93.900 array ("Error in XML input")
02762   end
02763   docNode = self~nodeStack~pull
02764 return
02765 /**
02766   Start a new element node.
02767   @param tagName - the name of the tag for this element node.
02768  
02769   If this is the first element created, the convenience attribute <i>documentElement</i> is set. The new element node is
02770   made the currently active one after being appended as a childnode of the parentnode.
02771 */
02772 ::method startElement
02773   use strict arg tagName
02774   elementNode = self~doc~createElement(tagName)
02775   if (self~haveDocumentElement==.false) then do
02776     self~doc~documentElement = elementNode
02777     self~haveDocumentElement = .true
02778   end
02779   self~nodeStack[1]~appendChild(elementNode)
02780   self~nodeStack~push(elementNode)
02781 return
02782 /**
02783   Finish the currently active element node.
02784   @param tagName - the name of the tag of the element being ended.
02785   @raises syntax 93.900 - Mismatch in start and ending tag.
02786  
02787   The previous elemnt node is made the active node, by removing this active node from the stack.
02788 */
02789 ::method endElement
02790   use strict arg tagName
02791   if self~nodeStack[1]~tagName<>tagName then do
02792     raise syntax 93.900 array ("Mismatch in start and ending tag") 
02793   end
02794   -- get rid of processed node
02795   processedNode = self~nodeStack~pull
02796 return
02797 /**
02798   Handle an attribute's name
02799   @param attrName - the name part of the current element's attribute.
02800  
02801   This will create the Attr node for the attribute, no name space checking is done.
02802 */
02803 ::method nameAttr
02804   use strict arg attrName
02805   self~attrNode = self~doc~createAttribute(attrName)
02806 return
02807 /**
02808   Handle an attibute's value.
02809   @param attrValue - the value part of the current element's attribute.
02810  
02811   Appends this Attr node to the (perhaps empty) list of attributes. Also sets the Attr's node ownerelement.
02812 */
02813 ::method valueAttr
02814   use strict arg attrValue
02815   self~attrNode~nodeValue = attrValue
02816   self~attrNode~ownerElement = self~nodeStack[1]
02817   self~nodeStack[1]~setAttributeNode(self~attrNode)
02818 return
02819 /**
02820   Handle a Processing Instruction (PI). 
02821   @param target - The target for the PI (e.g. 'xml' in '&lt;?xml version=.......?&gt;'.
02822   @param data - The information following the target as a string.
02823  
02824   The PInode is appended as a childnode for the currently active element node.
02825 */
02826 ::method havePI
02827   use strict arg target, data
02828   piNode = self~doc~createProcessingInstruction(target,data)
02829   self~nodeStack[1]~appendChild(piNode)
02830 return  
02831 /**
02832   Handle a Comment.
02833   @param comment - The string representing the comment
02834  
02835   No validity checking is done on the comment's content. The comment node is appended as a childnode for the active
02836   element node.
02837 */
02838 ::method haveComment
02839   use strict arg comment
02840   cmtNode = self~doc~createComment(comment)
02841   self~nodeStack[1]~appendChild(cmtNode)
02842 return
02843 /**
02844   Handle a Text node.
02845   @param text - the (inner) text of the node with entities resolved.
02846  
02847   The text node is appended as a childnode for the active element node.
02848 */
02849 ::method haveText
02850   use strict arg text
02851   txtNode = self~doc~createTextNode(text)
02852   self~nodeStack[1]~appendChild(txtNode)
02853 return
02854 /**
02855   Handle CDATA.
02856   @param cdata - The raw (unparsed) text for the CDATASection node.
02857  
02858   The CDATA node is appended as a childnode for the currently active element node
02859 */
02860 ::method haveCDATA
02861   use strict arg cdata
02862   cdataNode = self~doc~createCDATASection(cdata)
02863   self~nodeStack[1]~appendChild(cdataNode)
02864 return
02865 /* :end */
02866  
02867 /* CLASS: xmlParser */
02868 /**
02869   A non-validating simple XML parser. The parser recognizes the following:
02870   <ul>
02871   <li>Document start, when a XML file has been stringified and when the <i>parseSting</i> method has accepted the
02872   string.</li> 
02873   <li>XML Comments, no test for not allowed comment nesting.</li>
02874   <li>Removable White Space is removed when encountered.</li>
02875   <li>Processing Instructions (PI's), split into target (e.g. xml in &lt;?xml version....?&gt;) and data.</li>
02876   <li>CDATA with it's raw unparsed text.</li>
02877   <li>Attribute only tags, with their parsed, but without namespace checking, attributes.</li>
02878   <li>Tags with atributes as above and their parsed (i.e. resolved entities) text content.</li>
02879   <li>Document end, when the end of the XML string has been reached.</li>
02880   </ul>
02881 */
02882 ::class xmlParser public
02883 /**
02884   The DOM builder given as parameter at instance creation time
02885 */
02886 ::attribute domBuilder private
02887 /**
02888   The xmlParser constructor.
02889   @param domBuilder - the DOM builder the parser should use
02890 */
02891 ::method init
02892   use strict arg domBuilder
02893   self~domBuilder = domBuilder
02894 return
02895 /**
02896   Converts a XML file or stream into a string and passes the string on to <i>parseString</i>.
02897   @param xmlStream - An object with a <i>supplier</i> method
02898   @return domDocument - the DOM created from the input stream or <b>.nil</b> in case of errors
02899 */
02900 ::method parseStream
02901   use strict arg xmlStream
02902   s = xmlStream~supplier
02903   xml = ''
02904   do while s~available
02905     xml ||= s~item || .endofline
02906     s~next
02907   end
02908 return self~parseString(xml)
02909 /**
02910   Analyzes the input string for situations the DOM builder wants to know about and invokes the appropiate methods for
02911   the builder to handle the situations.
02912   @param xml - the XML string to be parsed.
02913   @return domDocument - the DOM created by the builder or <b>.nil</b> in case of errors.
02914 */  
02915 ::method parseString
02916   use strict arg xml
02917   self~domBuilder~startDocument
02918   do while (xml~pos('>')>0)
02919     tagEnd = xml~pos('>')
02920     -- check comment first cause it can appear anywhere
02921     cmtStart = xml~pos("<!--")
02922     if (cmtStart>0 & cmtStart<tagEnd) then do
02923       -- there may be (element) content in front of the comment
02924       parse var xml text "<!--" comment "-->" +3 xml
02925       -- repair comment xml
02926       tag = "<!--"comment"-->"
02927     end
02928     else do
02929       -- there could be (element) content in front of the tag(= '<')
02930       parse var xml text '<' tagContent '>' +1 xml
02931       -- repair tag xml
02932       tag = '<'tagContent'>'
02933     end
02934     -- if there is text it is the content for an element
02935     if (text<>'') then do
02936       -- if it is not ignorable whitespace
02937       if self~removeIgnorableWhiteSpace(text)<>'' 
02938         then self~domBuilder~haveText(self~resolveEntities(text))
02939         else text = ''
02940     end
02941     -- now handle the tag
02942     select 
02943       when (tag~pos("<!--")>0) then do
02944         -- this is a comment
02945         parse var tag "<!--" comment "-->"
02946         self~domBuilder~haveComment(comment)
02947       end
02948       when (tag~pos("<?")>0) then do
02949         -- this is a processing instruction (e.g. &lt;?xml version=....?&gt;)
02950         parse var tag "<?" target data "?>"
02951         self~domBuilder~havePI(target, data)
02952       end
02953       when (tag~pos("<![CDATA[")>0) then do
02954         -- there is unparsed (raw) text
02955         parse var tag "<![CDATA[" rawText "]]>"
02956         self~domBuilder~haveCDATA(rawText)
02957       end
02958       when (tag~pos("/>")>0) then do
02959         -- there is a complete element 
02960         parse var tag '<' tagName attributes "/>"
02961         self~domBuilder~startElement(tagName)
02962         -- handle attributes if any
02963         self~parseAttributes(self~removeIgnorableWhiteSpace(attributes))
02964         self~domBuilder~endElement(tagName)
02965       end
02966       when (tag~pos("</")>0) then do
02967         -- this is an element ending tag
02968         parse var tag "</" tagName '>'
02969         self~domBuilder~endElement(tagName)
02970       end
02971       otherwise do
02972         -- must be a element starting tag
02973         parse var tag '<' tagName attributes '>'
02974         self~domBuilder~startElement(tagName)
02975         -- handle attributes if any
02976         self~parseAttributes(self~removeIgnorableWhiteSpace(attributes))
02977       end
02978     end
02979   end
02980   self~domBuilder~endDocument
02981 return self~domBuilder~doc
02982 /**
02983   Processes the attributes specified within an element tag and passes them on the the builder.
02984   @param attributes - the string containing all the attributes specifications within an element tag.
02985 */
02986 ::method parseAttributes private
02987   use strict arg attributes
02988   attributes = attributes~strip
02989   do while (attributes<>'')
02990     parse var attributes attrName '=' rest  
02991     aposPos = rest~pos("'")
02992     quotPos = rest~pos('"')
02993     select
02994       when (quotPos=0) then delimiter = "'"
02995       when (aposPos=0) then delimiter = '"'
02996       when (aposPos<quotPos) then delimiter = "'"
02997       otherwise delimiter = '"'
02998     end
02999     parse var rest (delimiter) attrValue (delimiter) attributes
03000     attributes = attributes~strip
03001     self~domBuilder~nameAttr(attrName)
03002     self~domBuilder~valueAttr(self~resolveEntities(attrValue))
03003   end
03004 return
03005 /**
03006   Returns a string with whitespace removed.
03007   @param text - A string with embedded whitespace, perhaps
03008   @return text - The string with whitespace removed, if there was any.
03009 */
03010 ::method removeIgnorableWhiteSpace 
03011   use strict arg text
03012 return text~changeStr('09'x,'')~changeStr('0a'x,'')~changeStr('0d'x,'')~strip 
03013 /**
03014   Transforms (the standard) entities to their character representation. 
03015   @param text - A string possibly with entities.
03016   @return text - The string with entities resolved if any.
03017  
03018   <b><u>NOTE</u></b> - As DOCTYPE is not supported (yet) no DOCTYPE defined entities are handled.
03019 */
03020 ::method resolveEntities private
03021   use strict arg text
03022   text = text~changeStr("&lt;",'<')
03023   text = text~changeStr("&gt;",'>') 
03024   text = text~changeStr("&amp;",'&')
03025   text = text~changeStr("&apos;","'")
03026   text = text~changeStr("&quot;",'"')
03027 return text
03028 /* :end */ 
03029  
03030  
03031  
03032  
03033  

Get RexxLiterate at SourceForge.net. Fast, secure and Free Open Source software downloads
Generated on 30 Jul 2015 13:57:01 for xmlDOM for OOrexx by rexxliterate  0.0.1