blob: a8e91da7949dbbc58485ec12555fbe0fc00fdf91 [file] [log] [blame]
Daniel Veillard167b5091999-07-07 04:19:20 +00001/*
2 * HTMLtree.c : implemetation of access function for an HTML tree.
3 *
4 * See Copyright for the status of this software.
5 *
6 * Daniel.Veillard@w3.org
7 */
8
9#include "config.h"
10#include <stdio.h>
11#include <ctype.h>
12#include <stdlib.h>
13#include <string.h> /* for memset() only ! */
14
15#include "tree.h"
16#include "entities.h"
17#include "valid.h"
18
19#define HTML_TEXT_NODE XML_TEXT_NODE
20#define HTML_ENTITY_REF_NODE XML_ENTITY_REF_NODE
21#define HTML_COMMENT_NODE XML_COMMENT_NODE
22
23/**
24 * htmlDtdDump:
25 * @buf: the HTML buffer output
26 * @doc: the document
27 *
28 * Dump the HTML document DTD, if any.
29 */
30static void
31htmlDtdDump(xmlBufferPtr buf, xmlDocPtr doc) {
32 xmlDtdPtr cur = doc->intSubset;
33
34 if (cur == NULL) {
35 fprintf(stderr, "htmlDtdDump : no internal subset\n");
36 return;
37 }
38 xmlBufferWriteChar(buf, "<!DOCTYPE ");
39 xmlBufferWriteCHAR(buf, cur->name);
40 if (cur->ExternalID != NULL) {
41 xmlBufferWriteChar(buf, " PUBLIC ");
42 xmlBufferWriteQuotedString(buf, cur->ExternalID);
43 xmlBufferWriteChar(buf, " ");
44 xmlBufferWriteQuotedString(buf, cur->SystemID);
45 } else if (cur->SystemID != NULL) {
46 xmlBufferWriteChar(buf, " SYSTEM ");
47 xmlBufferWriteQuotedString(buf, cur->SystemID);
48 }
49 if ((cur->entities == NULL) && (cur->elements == NULL) &&
50 (cur->attributes == NULL) && (cur->notations == NULL)) {
51 xmlBufferWriteChar(buf, ">\n");
52 return;
53 }
54 xmlBufferWriteChar(buf, " [\n");
55 if (cur->entities != NULL)
56 xmlDumpEntitiesTable(buf, (xmlEntitiesTablePtr) cur->entities);
57 if (cur->notations != NULL)
58 xmlDumpNotationTable(buf, (xmlNotationTablePtr) cur->notations);
59 if (cur->elements != NULL)
60 xmlDumpElementTable(buf, (xmlElementTablePtr) cur->elements);
61 if (cur->attributes != NULL)
62 xmlDumpAttributeTable(buf, (xmlAttributeTablePtr) cur->attributes);
63 xmlBufferWriteChar(buf, "]");
64
65 /* TODO !!! a lot more things to dump ... */
66 xmlBufferWriteChar(buf, ">\n");
67}
68
69/**
70 * htmlAttrDump:
71 * @buf: the HTML buffer output
72 * @doc: the document
73 * @cur: the attribute pointer
74 *
75 * Dump an HTML attribute
76 */
77static void
78htmlAttrDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
79 CHAR *value;
80
81 if (cur == NULL) {
82 fprintf(stderr, "htmlAttrDump : property == NULL\n");
83 return;
84 }
85 xmlBufferWriteChar(buf, " ");
86 xmlBufferWriteCHAR(buf, cur->name);
87 value = xmlNodeListGetString(doc, cur->val, 0);
88 if (value) {
89 xmlBufferWriteChar(buf, "=");
90 xmlBufferWriteQuotedString(buf, value);
91 free(value);
92 } else {
93 xmlBufferWriteChar(buf, "=\"\"");
94 }
95}
96
97/**
98 * htmlAttrListDump:
99 * @buf: the HTML buffer output
100 * @doc: the document
101 * @cur: the first attribute pointer
102 *
103 * Dump a list of HTML attributes
104 */
105static void
106htmlAttrListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr cur) {
107 if (cur == NULL) {
108 fprintf(stderr, "htmlAttrListDump : property == NULL\n");
109 return;
110 }
111 while (cur != NULL) {
112 htmlAttrDump(buf, doc, cur);
113 cur = cur->next;
114 }
115}
116
117
118static void
119htmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level);
120/**
121 * htmlNodeListDump:
122 * @buf: the HTML buffer output
123 * @doc: the document
124 * @cur: the first node
125 * @level: the imbrication level for indenting
126 *
127 * Dump an HTML node list, recursive behaviour,children are printed too.
128 */
129static void
130htmlNodeListDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level) {
131 int i;
132
133 if (cur == NULL) {
134 fprintf(stderr, "htmlNodeListDump : node == NULL\n");
135 return;
136 }
137 while (cur != NULL) {
138 if ((cur->type != HTML_TEXT_NODE) &&
139 (cur->type != HTML_ENTITY_REF_NODE)) {
140 xmlBufferWriteChar(buf, "\n");
141 }
142 htmlNodeDump(buf, doc, cur, level);
143 cur = cur->next;
144 }
145}
146
147/**
148 * htmlNodeDump:
149 * @buf: the HTML buffer output
150 * @doc: the document
151 * @cur: the current node
152 * @level: the imbrication level for indenting
153 *
154 * Dump an HTML node, recursive behaviour,children are printed too.
155 */
156static void
157htmlNodeDump(xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level) {
158 int i;
159
160 if (cur == NULL) {
161 fprintf(stderr, "htmlNodeDump : node == NULL\n");
162 return;
163 }
164 if (cur->type == HTML_TEXT_NODE) {
165 if (cur->content != NULL) {
166 CHAR *buffer;
167
168 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
169 if (buffer != NULL) {
170 xmlBufferWriteCHAR(buf, buffer);
171 free(buffer);
172 }
173 }
174 return;
175 }
176 if (cur->type == HTML_COMMENT_NODE) {
177 if (cur->content != NULL) {
178 xmlBufferWriteChar(buf, "<!--");
179 xmlBufferWriteCHAR(buf, cur->content);
180 xmlBufferWriteChar(buf, "-->");
181 }
182 return;
183 }
184 if (cur->type == HTML_ENTITY_REF_NODE) {
185 xmlBufferWriteChar(buf, "&");
186 xmlBufferWriteCHAR(buf, cur->name);
187 xmlBufferWriteChar(buf, ";");
188 return;
189 }
190
191 xmlBufferWriteChar(buf, "<");
192 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
193 xmlBufferWriteCHAR(buf, cur->ns->prefix);
194 xmlBufferWriteChar(buf, ":");
195 }
196
197 xmlBufferWriteCHAR(buf, cur->name);
198 if (cur->nsDef)
199 xmlNsListDump(buf, cur->nsDef);
200 if (cur->properties != NULL)
201 htmlAttrListDump(buf, doc, cur->properties);
202
203 if ((cur->content == NULL) && (cur->childs == NULL)) {
204 xmlBufferWriteChar(buf, "/>\n");
205 return;
206 }
207 xmlBufferWriteChar(buf, ">");
208 if (cur->content != NULL) {
209 CHAR *buffer;
210
211 buffer = xmlEncodeEntitiesReentrant(doc, cur->content);
212 if (buffer != NULL) {
213 xmlBufferWriteCHAR(buf, buffer);
214 free(buffer);
215 }
216 }
217 if (cur->childs != NULL) {
218 htmlNodeListDump(buf, doc, cur->childs, level + 1);
219 }
220 xmlBufferWriteChar(buf, "</");
221 if ((cur->ns != NULL) && (cur->ns->prefix != NULL)) {
222 xmlBufferWriteCHAR(buf, cur->ns->prefix);
223 xmlBufferWriteChar(buf, ":");
224 }
225
226 xmlBufferWriteCHAR(buf, cur->name);
227 xmlBufferWriteChar(buf, ">\n");
228}
229
230/**
231 * htmlDocContentDump:
232 * @buf: the HTML buffer output
233 * @cur: the document
234 *
235 * Dump an HTML document.
236 */
237static void
238htmlDocContentDump(xmlBufferPtr buf, xmlDocPtr cur) {
239 xmlBufferWriteChar(buf, "<?xml version=");
240 if (cur->version != NULL)
241 xmlBufferWriteQuotedString(buf, cur->version);
242 else
243 xmlBufferWriteChar(buf, "\"1.0\"");
244 if (cur->encoding != NULL) {
245 xmlBufferWriteChar(buf, " encoding=");
246 xmlBufferWriteQuotedString(buf, cur->encoding);
247 }
248 switch (cur->standalone) {
249 case 0:
250 xmlBufferWriteChar(buf, " standalone=\"no\"");
251 break;
252 case 1:
253 xmlBufferWriteChar(buf, " standalone=\"yes\"");
254 break;
255 }
256 xmlBufferWriteChar(buf, "?>\n");
257 if (cur->intSubset != NULL)
258 htmlDtdDump(buf, cur);
259 if (cur->root != NULL) {
260 htmlNodeDump(buf, cur, cur->root, 0);
261 }
262}
263
264/**
265 * htmlDocDumpMemory:
266 * @cur: the document
267 * @mem: OUT: the memory pointer
268 * @size: OUT: the memory lenght
269 *
270 * Dump an HTML document in memory and return the CHAR * and it's size.
271 * It's up to the caller to free the memory.
272 */
273void
274htmlDocDumpMemory(xmlDocPtr cur, CHAR**mem, int *size) {
275 xmlBufferPtr buf;
276
277 if (cur == NULL) {
278#ifdef DEBUG_TREE
279 fprintf(stderr, "xmlDocDumpMemory : document == NULL\n");
280#endif
281 *mem = NULL;
282 *size = 0;
283 return;
284 }
285 buf = xmlBufferCreate();
286 if (buf == NULL) {
287 *mem = NULL;
288 *size = 0;
289 return;
290 }
291 htmlDocContentDump(buf, cur);
292 *mem = buf->content;
293 *size = buf->use;
294 memset(buf, -1, sizeof(xmlBuffer));
295 free(buf);
296}
297
298
299/**
300 * htmlDocDump:
301 * @f: the FILE*
302 * @cur: the document
303 *
304 * Dump an HTML document to an open FILE.
305 */
306void
307htmlDocDump(FILE *f, xmlDocPtr cur) {
308 xmlBufferPtr buf;
309
310 if (cur == NULL) {
311#ifdef DEBUG_TREE
312 fprintf(stderr, "xmlDocDump : document == NULL\n");
313#endif
314 return;
315 }
316 buf = xmlBufferCreate();
317 if (buf == NULL) return;
318 htmlDocContentDump(buf, cur);
319 xmlBufferDump(f, buf);
320 xmlBufferFree(buf);
321}
322
323/**
324 * htmlSaveFile:
325 * @filename: the filename
326 * @cur: the document
327 *
328 * Dump an HTML document to a file.
329 *
330 * returns: the number of byte written or -1 in case of failure.
331 */
332int
333htmlSaveFile(const char *filename, xmlDocPtr cur) {
334 xmlBufferPtr buf;
335 FILE *output = NULL;
336 int ret;
337
338 /*
339 * save the content to a temp buffer.
340 */
341 buf = xmlBufferCreate();
342 if (buf == NULL) return(0);
343 htmlDocContentDump(buf, cur);
344
345 output = fopen(filename, "w");
346 if (output == NULL) return(-1);
347 ret = xmlBufferDump(output, buf);
348 fclose(output);
349
350 xmlBufferFree(buf);
351 return(ret * sizeof(CHAR));
352}
353