blob: 56585ebde4fa253d85aa71b63675412b2eafa65d [file] [log] [blame]
Daniel Veillard260a68f1998-08-13 03:39:55 +00001/*
2 * SAX.c : Default SAX handler to build a tree.
Daniel Veillard97b58771998-10-20 06:14:16 +00003 *
4 * Daniel Veillard <Daniel.Veillard@w3.org>
Daniel Veillard260a68f1998-08-13 03:39:55 +00005 */
6
7#include <stdio.h>
Seth Alvese7f12e61998-10-01 20:51:15 +00008#include <stdlib.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +00009#include "tree.h"
10#include "parser.h"
11#include "error.h"
12
13/* #define DEBUG_SAX */
14
Daniel Veillard97b58771998-10-20 06:14:16 +000015/**
16 * getPublicId:
17 * @ctxt: An XML parser context
18 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000019 * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
Daniel Veillard97b58771998-10-20 06:14:16 +000020 *
21 * return values: a CHAR *
Daniel Veillard260a68f1998-08-13 03:39:55 +000022 */
Daniel Veillard97b58771998-10-20 06:14:16 +000023const CHAR *
24getPublicId(xmlParserCtxtPtr ctxt)
25{
Daniel Veillard260a68f1998-08-13 03:39:55 +000026 return(NULL);
27}
28
Daniel Veillard97b58771998-10-20 06:14:16 +000029/**
30 * getSystemId:
31 * @ctxt: An XML parser context
32 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000033 * Return the system ID, basically URI or filename e.g.
Daniel Veillard97b58771998-10-20 06:14:16 +000034 * http://www.sgmlsource.com/dtds/memo.dtd
35 *
36 * return values: a CHAR *
Daniel Veillard260a68f1998-08-13 03:39:55 +000037 */
Daniel Veillard97b58771998-10-20 06:14:16 +000038const CHAR *
39getSystemId(xmlParserCtxtPtr ctxt)
40{
Daniel Veillard260a68f1998-08-13 03:39:55 +000041 return(ctxt->input->filename);
42}
43
Daniel Veillard97b58771998-10-20 06:14:16 +000044/**
45 * getLineNumber:
46 * @ctxt: An XML parser context
47 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000048 * Return the line number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000049 *
50 * return values: an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000051 */
Daniel Veillard97b58771998-10-20 06:14:16 +000052int
53getLineNumber(xmlParserCtxtPtr ctxt)
54{
Daniel Veillard260a68f1998-08-13 03:39:55 +000055 return(ctxt->input->line);
56}
Daniel Veillard97b58771998-10-20 06:14:16 +000057
58/**
59 * getColumnNumber:
60 * @ctxt: An XML parser context
61 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000062 * Return the column number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000063 *
64 * return values: an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000065 */
Daniel Veillard97b58771998-10-20 06:14:16 +000066int
67getColumnNumber(xmlParserCtxtPtr ctxt)
68{
Daniel Veillard260a68f1998-08-13 03:39:55 +000069 return(ctxt->input->col);
70}
71
72/*
73 * The default SAX Locator.
74 */
75
76xmlSAXLocator xmlDefaultSAXLocator = {
77 getPublicId, getSystemId, getLineNumber, getColumnNumber
78};
79
Daniel Veillard97b58771998-10-20 06:14:16 +000080/**
81 * resolveEntity:
82 * @ctxt: An XML parser context
83 * @publicId: The public ID of the entity
84 * @systemId: The system ID of the entity
85 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000086 * Special entity resolver, better left to the parser, it has
87 * more context than the application layer.
Daniel Veillard97b58771998-10-20 06:14:16 +000088 *
89 * return values: an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000090 */
Daniel Veillard97b58771998-10-20 06:14:16 +000091xmlParserInputPtr
92resolveEntity(xmlParserCtxtPtr ctxt, const CHAR *publicId, const CHAR *systemId)
93{
Daniel Veillard260a68f1998-08-13 03:39:55 +000094
95#ifdef DEBUG_SAX
96 fprintf(stderr, "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
97#endif
98 return(NULL);
99}
100
Daniel Veillard97b58771998-10-20 06:14:16 +0000101/**
102 * notationDecl:
103 * @ctxt: An XML parser context
104 * @name: The name of the notation
105 * @publicId: The public ID of the entity
106 * @systemId: The system ID of the entity
107 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000108 * What to do when a notation declaration has been parsed.
109 * TODO Not handled currently.
Daniel Veillard97b58771998-10-20 06:14:16 +0000110 *
111 * return values:
Daniel Veillard260a68f1998-08-13 03:39:55 +0000112 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000113void
114notationDecl(xmlParserCtxtPtr ctxt, const CHAR *name,
115 const CHAR *publicId, const CHAR *systemId)
116{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000117#ifdef DEBUG_SAX
118 fprintf(stderr, "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
119#endif
120}
121
Daniel Veillard97b58771998-10-20 06:14:16 +0000122/**
123 * unparsedEntityDecl:
124 * @ctxt: An XML parser context
125 * @name: The name of the entity
126 * @publicId: The public ID of the entity
127 * @systemId: The system ID of the entity
128 * @notationName: the name of the notation
129 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000130 * What to do when an unparsed entity declaration is parsed
131 * TODO Create an Entity node.
Daniel Veillard97b58771998-10-20 06:14:16 +0000132 *
133 * return values:
Daniel Veillard260a68f1998-08-13 03:39:55 +0000134 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000135void
136unparsedEntityDecl(xmlParserCtxtPtr ctxt, const CHAR *name,
137 const CHAR *publicId, const CHAR *systemId,
138 const CHAR *notationName)
139{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000140#ifdef DEBUG_SAX
141 fprintf(stderr, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
142 name, publicId, systemId, notationName);
143#endif
144}
145
Daniel Veillard97b58771998-10-20 06:14:16 +0000146/**
147 * setDocumentLocator:
148 * @ctxt: An XML parser context
149 * @loc: A SAX Locator
150 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000151 * Receive the document locator at startup, actually xmlDefaultSAXLocator
152 * Everything is available on the context, so this is useless in our case.
Daniel Veillard97b58771998-10-20 06:14:16 +0000153 *
154 * return values:
Daniel Veillard260a68f1998-08-13 03:39:55 +0000155 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000156void
157setDocumentLocator(xmlParserCtxtPtr ctxt, xmlSAXLocatorPtr loc)
158{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000159#ifdef DEBUG_SAX
160 fprintf(stderr, "SAX.setDocumentLocator()\n");
161#endif
162}
163
Daniel Veillard97b58771998-10-20 06:14:16 +0000164/**
165 * startDocument:
166 * @ctxt: An XML parser context
167 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000168 * called when the document start being processed.
Daniel Veillard97b58771998-10-20 06:14:16 +0000169 *
170 * return values:
Daniel Veillard260a68f1998-08-13 03:39:55 +0000171 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000172void
173startDocument(xmlParserCtxtPtr ctxt)
174{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000175#ifdef DEBUG_SAX
176 fprintf(stderr, "SAX.startDocument()\n");
177#endif
178}
179
Daniel Veillard97b58771998-10-20 06:14:16 +0000180/**
181 * endDocument:
182 * @ctxt: An XML parser context
183 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000184 * called when the document end has been detected.
Daniel Veillard97b58771998-10-20 06:14:16 +0000185 *
186 * return values:
Daniel Veillard260a68f1998-08-13 03:39:55 +0000187 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000188void
189endDocument(xmlParserCtxtPtr ctxt)
190{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000191#ifdef DEBUG_SAX
192 fprintf(stderr, "SAX.endDocument()\n");
193#endif
194}
195
Daniel Veillard97b58771998-10-20 06:14:16 +0000196/**
197 * startElement:
198 * @ctxt: An XML parser context
199 * @name: The element name
200 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000201 * called when an opening tag has been processed.
202 * TODO We currently have a small pblm with the arguments ...
Daniel Veillard97b58771998-10-20 06:14:16 +0000203 *
204 * return values:
Daniel Veillard260a68f1998-08-13 03:39:55 +0000205 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000206void
207startElement(xmlParserCtxtPtr ctxt, const CHAR *name)
208{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000209 xmlNodePtr parent;
210
211#ifdef DEBUG_SAX
212 fprintf(stderr, "SAX.startElement(%s)\n", name);
213#endif
214 if (ctxt->nodeNr < 2) return;
215 parent = ctxt->nodeTab[ctxt->nodeNr - 2];
216 if (parent != NULL)
217 xmlAddChild(parent, ctxt->node);
218
219}
220
Daniel Veillard97b58771998-10-20 06:14:16 +0000221/**
222 * endElement:
223 * @ctxt: An XML parser context
224 * @name: The element name
225 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000226 * called when the end of an element has been detected.
Daniel Veillard97b58771998-10-20 06:14:16 +0000227 *
228 * return values:
Daniel Veillard260a68f1998-08-13 03:39:55 +0000229 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000230void
231endElement(xmlParserCtxtPtr ctxt, const CHAR *name)
232{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000233#ifdef DEBUG_SAX
234 fprintf(stderr, "SAX.endElement(%s)\n", name);
235#endif
236}
237
Daniel Veillard97b58771998-10-20 06:14:16 +0000238/**
Daniel Veillard11e00581998-10-24 18:27:49 +0000239 * attribute:
240 * @ctxt: An XML parser context
241 * @name: The attribute name
242 * @value: The attribute value
243 *
244 * called when an attribute has been read by the parser.
245 * The default handling is to convert the attribute into an
246 * DOM subtree and past it in a new xmlAttr element added to
247 * the element.
248 *
249 * return values:
250 */
251void
252attribute(xmlParserCtxtPtr ctxt, const CHAR *name, const CHAR *value)
253{
254#ifdef DEBUG_SAX
255 fprintf(stderr, "SAX.attribute(%s, %s)\n", name, value);
256#endif
257 xmlNewProp(ctxt->node, name, value);
258}
259
260/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000261 * characters:
262 * @ctxt: An XML parser context
263 * @ch: a CHAR string
264 * @start: the first char in the string
265 * @len: the number of CHAR
266 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000267 * receiving some chars from the parser.
268 * Question: how much at a time ???
Daniel Veillard97b58771998-10-20 06:14:16 +0000269 *
270 * return values:
Daniel Veillard260a68f1998-08-13 03:39:55 +0000271 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000272void
273characters(xmlParserCtxtPtr ctxt, const CHAR *ch, int start, int len)
274{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000275 xmlNodePtr lastChild;
276
277#ifdef DEBUG_SAX
278 fprintf(stderr, "SAX.characters(%.30s, %d, %d)\n", ch, start, len);
279#endif
280 /*
281 * Handle the data if any. If there is no child
282 * add it as content, otherwise if the last child is text,
283 * concatenate it, else create a new node of type text.
284 */
285
286 lastChild = xmlGetLastChild(ctxt->node);
287 if (lastChild == NULL)
288 xmlNodeAddContentLen(ctxt->node, &ch[start], len);
289 else {
290 if (xmlNodeIsText(lastChild))
291 xmlTextConcat(lastChild, &ch[start], len);
292 else {
293 lastChild = xmlNewTextLen(&ch[start], len);
294 xmlAddChild(ctxt->node, lastChild);
295 }
296 }
297}
298
Daniel Veillard97b58771998-10-20 06:14:16 +0000299/**
300 * ignorableWhitespace:
301 * @ctxt: An XML parser context
302 * @ch: a CHAR string
303 * @start: the first char in the string
304 * @len: the number of CHAR
305 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000306 * receiving some ignorable whitespaces from the parser.
307 * Question: how much at a time ???
Daniel Veillard97b58771998-10-20 06:14:16 +0000308 *
309 * return values:
Daniel Veillard260a68f1998-08-13 03:39:55 +0000310 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000311void
312ignorableWhitespace(xmlParserCtxtPtr ctxt, const CHAR *ch, int start, int len)
313{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000314#ifdef DEBUG_SAX
315 fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d, %d)\n", ch, start, len);
316#endif
317}
318
Daniel Veillard97b58771998-10-20 06:14:16 +0000319/**
320 * processingInstruction:
321 * @ctxt: An XML parser context
322 * @target: the target name
323 * @data: the PI data's
324 * @len: the number of CHAR
325 *
326 * A processing instruction has been parsed.
327 *
328 * return values:
Daniel Veillard260a68f1998-08-13 03:39:55 +0000329 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000330void
331processingInstruction(xmlParserCtxtPtr ctxt, const CHAR *target,
332 const CHAR *data)
333{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000334#ifdef DEBUG_SAX
335 fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
336#endif
337}
338
339xmlSAXHandler xmlDefaultSAXHandler = {
340 resolveEntity,
341 notationDecl,
342 unparsedEntityDecl,
343 setDocumentLocator,
344 startDocument,
345 endDocument,
346 startElement,
347 endElement,
Daniel Veillard11e00581998-10-24 18:27:49 +0000348 attribute,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000349 characters,
350 ignorableWhitespace,
351 processingInstruction,
352 xmlParserWarning,
353 xmlParserError,
354 xmlParserError,
355};
356
Daniel Veillard97b58771998-10-20 06:14:16 +0000357/**
358 * xmlDefaultSAXHandlerInit:
359 *
360 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +0000361 */
362void
363xmlDefaultSAXHandlerInit(void)
364{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000365 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
366 xmlDefaultSAXHandler.notationDecl = notationDecl;
367 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
368 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
369 xmlDefaultSAXHandler.startDocument = startDocument;
370 xmlDefaultSAXHandler.endDocument = endDocument;
371 xmlDefaultSAXHandler.startElement = startElement;
372 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard11e00581998-10-24 18:27:49 +0000373 xmlDefaultSAXHandler.attribute = attribute;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000374 xmlDefaultSAXHandler.characters = characters;
375 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
376 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
377 xmlDefaultSAXHandler.warning = xmlParserWarning;
378 xmlDefaultSAXHandler.error = xmlParserError;
379 xmlDefaultSAXHandler.fatalError = xmlParserError;
380}