r11859: Canonicalize whitespace
[xmlutils.git] / phtml.txt
1 Preliminary HTML Parser documentation
2
3 Pending tasks:
4
5     . integrate with aserve components, such as htmlgen and LHTML description
6
7
8 Description
9
10 The parse-html function processes HTML input, returning a list of HTML tags,
11 attributes, and text. Here is a simple example:
12
13 (parse-html "<HTML>
14              <HEAD>
15              <TITLE>Example HTML input</TITLE>
16              <BODY>
17              <P>Here is some text with a <B>bold</B> word<br>and a <A HREF=\"help.html\">link</P>
18              </HTML>")
19
20 -->
21
22 ((:html (:head (:title "Example HTML input"))
23   (:body (:p "Here is some text with a " (:b "bold") " word" :br "and a " 
24         ((:a :href "help.html") "link")))))
25
26
27 The output format is known as LHTML format; it is the same format that the
28 aserve htmlgen macro accepts. 
29
30 Here is a description of LHTML:
31
32 LHTML is a list representation of HTML tags and content.
33
34 Each list member may be:
35
36 a. a string containing text content, such as "Here is some text with a "
37
38 b. a keyword package symbol representing a HTML tag with no associated attributes 
39    or content, such as :br.
40
41 c. a list representing an HTML tag with associated attributes and/or content,
42    such as (:b "bold") or ((:a :href "help.html") "link"). If the HTML tag
43    does not have associated attributes, then the first list member will be a
44    keyword package symbol representing the HTML tag, and the other elements will 
45    represent the content, which can be a string (text content), a keyword package symbol (HTML
46    tag with no attributes or content), or list (nested HTML tag with
47    associated attributes and/or content). If there are associated attributes,
48    then the first list member will be a list containing a keyword package symbol
49    followed by two list members for each associated attribute; the first member is a keyword
50    package symbol representing the attribute, and the next member is a string corresponding
51    to the attribute value.
52
53 Here are some additional details about parse-html output:
54
55 1. If excl:*current-case-mode* is :CASE-INSENSITIVE-UPPER, keyword package symbols will be
56    in upper case; otherwise, they will be in lower case.
57
58 2. HTML comments are represented use a :comment symbol. For example,
59
60    (parse-html "<!-- this is a comment-->")
61
62 --> ((:comment " this is a comment"))
63
64 3. All <SCRIPT> and <STYLE> content is not parsed; it is returned as text content.
65
66    For example,
67
68    (parse-html "<SCRIPT>this <B>will not</B> be parsed</SCRIPT>")
69
70 --> ((:script "this <B>will not</B> be parsed"))
71
72 4. Since, some HTML pages contain special XML/SGML tags, non-comment tags
73    starting with '<!' are treated specially:
74
75    (parse-html "<!doctype this is some text>")
76
77 --> ((:!doctype " this is some text"))
78
79 5. There is plenty of illegal and deprecated HTML on the web that popular browsers
80    nonetheless successfully display. The parse-html parser is generous - it will not
81    raise an error condition upon encountering most input. In particular, it does not
82    maintain a list of legal HTML tags and will successfully parse nonsense input.
83
84    For example,
85
86    (parse-html "<this> <is> <some> <nonsense> <input>")
87
88 --> ((:this (:is (:some (:nonsense :input)))))
89
90    In some situations, you may prefer a two-pass parse that results in a parse where
91    deep nesting related to unrecognized tags is minimized:
92
93    (let ((string "<this> <is> <some> <nonsense> </some> <input>"))
94                 (multiple-value-bind (res rogues)
95                     (parse-html string :collect-rogue-tags t)
96                   (declare (ignorable res))
97                   (parse-html string :no-body-tags rogues)))
98
99 --> (:this :is (:some (:nonsense)) :input)
100
101    See the :collect-rogue-tags and :no-body-tags argument descriptions in the reference
102    section below for more information.
103
104 6. As per the HTML 4.0 specification, attributes without specified values are given a lower case
105    string value that matches the attribute name.
106
107    For example,
108    
109    (parse-html "<P here ARE some attributes>")
110
111 --> (((:p :here "here" :are "are" :some "some" :attributes "attributes")))
112
113 7. Existing HTML pages often have character format tags that are interleaved among
114    other tags. Such interleaving is removed in a manner consistent with the HTML 4.0
115    specification.
116
117    For example,
118
119    (parse-html "<P>Here is <B>bold text<P>that spans</B>two paragraphs")
120
121 --> ((:p "Here is " (:b "bold text")) (:p (:b "that spans") "two paragraphs"))
122
123 -----------------------------------------------------
124
125 parse-html reference
126
127 parse-html                                  [Generic function]
128
129 Arguments:   input-source &key callbacks callback-only
130                                collect-rogue-tags no-body-tags
131
132 Returns LHTML output, as described above.
133
134 The callbacks argument, if non-nil, should be an association list. Each list member's
135 car (first) element specifies a keyword package symbol, and each list member's cdr (rest)
136 element specifies a function object or a symbol naming a function. The function should
137 expect one argument. The function will be invoked once for each time the HTML tag
138 corresponding to the specified keyword package symbol is encountered in the HTML input; the
139 argument will be an LHTML list containing the tag, along with associated attributes and
140 content. The default callbacks argument value is nil.
141
142 The callback-only argument, if non-nil, directs parse-html to not generate a complete LHTML
143 output. Instead, LHTML lists will only be generated when necessary as arguments for functions
144 specified in the callbacks association list. This results in faster parser execution. The default
145 callback-only argument value is nil.
146
147 The collect-rogue-tags argument, if non-nil, directs parse-html to return an additional value, 
148 a list containing any unrecognized tags closed by the end of input.
149
150 The no-body-tags argument, if non-nil, should be a list containing unknown tags that, if
151 encountered, will be treated as a tag with no body or content, and thus, no associated end
152 tag. Typically, the argument is a list or modified list resulting from an earlier parse-html
153 execution with the :collect-rogue-tags argument specified as non-nil.
154
155
156
157 parse-html Methods
158
159 parse-html (p stream) &key callbacks callback-only
160                            collect-rogue-tags no-body-tags
161
162 parse-html (str string) &key callbacks callback-only
163                              collect-rogue-tags no-body-tags
164
165 parse-html (file t) &key callbacks callback-only
166                          collect-rogue-tags no-body-tags
167
168 The t method assumes the argument is a pathname suitable
169 for use with the with-open-file macro.
170
171
172 phtml-internal          [Function]
173
174 Arguments: stream read-sequence-func callback-only callbacks
175            collect-rogue-tags no-body-tags
176
177 This function may be used when more control is needed for supplying
178 the HTML input. The read-sequence-func argument, if non-nil, should be a function
179 object or a symbol naming a function. When phtml-internal requires another buffer
180 of HTML input, it will invoke the read-sequence-func function with two arguments -
181 the first argument is an internal buffer character array and the second argument is
182 the phtml-internal stream argument. If read-sequence-fun is nil, phtml-internal
183 will invoke read-sequence to fill the buffer. The read-sequence-func function must
184 return the number of character array elements successfully stored in the buffer.
185
186
187
188
189
190
191