1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # This file is free software, which comes along with NIT. This software is
4 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
5 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
6 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
7 # is kept unaltered, and a notification of the changes is added.
8 # You are allowed to redistribute it and sell it, alone or is a part of
11 # Basic blocks for DOM-XML representation
13 # DOM entities are defined in this module, specifically:
15 # * `XMLEntity`: Abstract kind of XML-related node
16 # * `XMLDocument`: A well-formed XML document, root of the tree
17 # * `PCDATA`: Raw XML-escaped character data
18 # * `CDATA`: Raw data, may contain invalid XML escape characters
19 # * `XMLTag`: Abstract XML tag element
20 # * `XMLAttrTag`: Abstract XML element, they may contain attributes
21 # * `XMLOnelinerTag`: Any tag contained on one-line only
22 # * `XMLStartTag`: A tag starting a new hierarchy level in the tree
23 # * `XMLPrologTag`: A tag containing meta-information on the document, must start with <?xml
24 # * `XMLProcessingInstructionTag`: Any XML tag starting with <? other than the prolog tag
25 # * `XMLEndTag`: A tag signaling the end of a block
26 # * `XMLCommentTag`: A comment tag
27 # * `XMLSpecialTag`: A special tag, which may contain meta-information
28 # * `XMLDoctypeTag`: A DOCTYPE tag, use to register a DTD
29 # * `XMLAttribute`: Any kind of attribute that may be attached to a tag
30 # * `XMLStringAttr`: An attribute containing a String
31 # * `XMLError`: Any kind of error thrown while parsing a document
36 # Any kind of XML Entity
37 abstract class XMLEntity
38 # Optional parent of `self`
39 var parent
: nullable XMLEntity = null is private writable(set_parent
)
41 # Optional location of the entity in source
42 var location
: nullable Location
44 # The children of `self`
45 var children
: Sequence[XMLEntity] = new XMLEntities(self)
47 # Sets the parent of `self` to `e`
48 fun parent
=(e
: XMLEntity) do
49 var parent
= self.parent
50 if parent
!= null then
51 parent
.children
.remove
(self)
57 # Proxy collection of XMLEntities, ordered, used for the children of an entity
58 private class XMLEntities
59 super Sequence[XMLEntity]
61 # The owner, aka, the parent
64 var entities
= new List[XMLEntity]
66 redef fun length
do return entities
.length
68 redef fun [](i
) do return entities
[i
]
70 redef fun []=(index
, el
) do
71 var olde
= self[index
]
72 var olde_parent
= olde
.parent
73 if olde_parent
!= null then
74 olde_parent
.children
.remove
(el
)
81 if not entities
.has
(e
) then
88 redef fun remove
(e
) do
89 if e
isa XMLEntity then
95 redef fun has
(e
) do return entities
.has
(e
)
97 redef fun iterator
do return entities
.iterator
99 redef fun reverse_iterator
do return entities
.reverse_iterator
107 redef fun unshift
(e
) do
113 var e
= entities
.shift
118 redef fun insert
(it
, index
) do
119 entities
.insert
(it
, index
)
123 redef fun remove_at
(ind
) do
124 var el
= entities
[ind
]
125 entities
.remove_at
(ind
)
130 # Top XML Document-Object Model element
134 redef fun to_s
do return children
.join
137 # PCDATA is any kind of non-xml formatted text
141 # Any string containing non XML-reserved characters
144 redef fun to_s
do return content
147 # CDATA are regions in which no xml entity is parsed, all is ignored
151 # Any string contained within a CDATA block, may contain XML-reserved characters
154 redef fun to_s
do return "<![CDATA[{content}]]>"
157 # A Tag is a node in a DOM tree
158 abstract class XMLTag
161 # The name of the tag
165 # Any kind of XML tag with attributes
166 abstract class XMLAttrTag
169 # List of attributes in a Tag
170 var attributes
: Array[XMLAttribute]
173 # One-liner XML Tag (Ends with />)
178 var s
= "<{tag_name}"
179 if not attributes
.is_empty
then
181 s
+= attributes
.join
(" ")
188 # A (potentially) multi-line spanning XML Tag start
192 # Optional matching tag, must be matched for the document to be well-formed
193 var matching
: nullable XMLEndTag
196 var s
= "<{tag_name}"
197 if not attributes
.is_empty
then
199 s
+= attributes
.join
(" ")
202 for i
in children
do s
+= i
.to_s
203 var matching
= self.matching
204 if matching
!= null then s
+= matching
.to_s
209 # Any prolog style-Tag (starting with <?xml)
213 redef fun to_s
do return """<?{{{tag_name}}} {{{attributes.join(" ")}}}?>"""
216 # Processing instructions start with <? and are to be read by a third-party application
217 class XMLProcessingInstructionTag
220 # Raw content usable by the third-party application
223 redef fun to_s
do return "<?{tag_name} {content}?>"
226 # An end Tag (starting with </)
230 # Optional matching tag, must be matched for the document to be well-formed
231 var matching
: nullable XMLStartTag
233 redef fun to_s
do return "</{tag_name}>"
240 redef fun to_s
do return "<!--{tag_name}-->"
250 redef fun to_s
do return "<!DOCTYPE {content}>"
253 # A Special Tag (starts with !)
255 # TODO: Support the remaining ! tags
259 redef fun to_s
do return "<!{tag_name}>"
262 # Attributes are contained in tags, they provide meta-information on a tag
263 abstract class XMLAttribute
266 # Name of the attribute
270 # An attribute with a String value
274 # Value of the attribute without the double quotes
277 # Type of delimiter (can be either " or ')
280 redef fun to_s
do return "{name}={delimiter}{value}{delimiter}"
283 # Badly formed XML attribute
284 class BadXMLAttribute
287 redef fun to_s
do return name
290 # Internal use only, shows the end of an attribute block
291 private class XMLAttributeEnd
295 # Any XML Error that happens when parsing
299 # Error message reported by the parser
303 var l
= self.location
305 return "XML Error: {message}"
307 return "XML Error: {message} at {l}"