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