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 '<?xml version=.......?>'. 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 <?xml version....?>) 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. <?xml version=....?>) 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("<",'<') 03023 text = text~changeStr(">",'>') 03024 text = text~changeStr("&",'&') 03025 text = text~changeStr("'","'") 03026 text = text~changeStr(""",'"') 03027 return text 03028 /* :end */ 03029 03030 03031 03032 03033
Generated on 30 Jul 2015 13:57:01 for xmlDOM for OOrexx by 0.0.1 |