blob: 46afbb9b2eacf5a22e8c9fc1cb6e76d149b4f850 [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 *
Daniel Veillard39a1f9a1999-01-17 19:11:59 +00004 * See Copyright for the status of this software.
5 *
Daniel Veillard97b58771998-10-20 06:14:16 +00006 * Daniel Veillard <Daniel.Veillard@w3.org>
Daniel Veillard260a68f1998-08-13 03:39:55 +00007 */
8
9#include <stdio.h>
Seth Alvese7f12e61998-10-01 20:51:15 +000010#include <stdlib.h>
Daniel Veillard260a68f1998-08-13 03:39:55 +000011#include "tree.h"
12#include "parser.h"
Daniel Veillardccb09631998-10-27 06:21:04 +000013#include "entities.h"
Daniel Veillard260a68f1998-08-13 03:39:55 +000014#include "error.h"
15
16/* #define DEBUG_SAX */
17
Daniel Veillard97b58771998-10-20 06:14:16 +000018/**
19 * getPublicId:
20 * @ctxt: An XML parser context
21 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000022 * Return the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
Daniel Veillard97b58771998-10-20 06:14:16 +000023 *
24 * return values: a CHAR *
Daniel Veillard260a68f1998-08-13 03:39:55 +000025 */
Daniel Veillard97b58771998-10-20 06:14:16 +000026const CHAR *
27getPublicId(xmlParserCtxtPtr ctxt)
28{
Daniel Veillard260a68f1998-08-13 03:39:55 +000029 return(NULL);
30}
31
Daniel Veillard97b58771998-10-20 06:14:16 +000032/**
33 * getSystemId:
34 * @ctxt: An XML parser context
35 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000036 * Return the system ID, basically URI or filename e.g.
Daniel Veillard97b58771998-10-20 06:14:16 +000037 * http://www.sgmlsource.com/dtds/memo.dtd
38 *
39 * return values: a CHAR *
Daniel Veillard260a68f1998-08-13 03:39:55 +000040 */
Daniel Veillard97b58771998-10-20 06:14:16 +000041const CHAR *
42getSystemId(xmlParserCtxtPtr ctxt)
43{
Daniel Veillard260a68f1998-08-13 03:39:55 +000044 return(ctxt->input->filename);
45}
46
Daniel Veillard97b58771998-10-20 06:14:16 +000047/**
48 * getLineNumber:
49 * @ctxt: An XML parser context
50 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000051 * Return the line number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000052 *
53 * return values: an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000054 */
Daniel Veillard97b58771998-10-20 06:14:16 +000055int
56getLineNumber(xmlParserCtxtPtr ctxt)
57{
Daniel Veillard260a68f1998-08-13 03:39:55 +000058 return(ctxt->input->line);
59}
Daniel Veillard97b58771998-10-20 06:14:16 +000060
61/**
62 * getColumnNumber:
63 * @ctxt: An XML parser context
64 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000065 * Return the column number of the current parsing point.
Daniel Veillard97b58771998-10-20 06:14:16 +000066 *
67 * return values: an int
Daniel Veillard260a68f1998-08-13 03:39:55 +000068 */
Daniel Veillard97b58771998-10-20 06:14:16 +000069int
70getColumnNumber(xmlParserCtxtPtr ctxt)
71{
Daniel Veillard260a68f1998-08-13 03:39:55 +000072 return(ctxt->input->col);
73}
74
75/*
76 * The default SAX Locator.
77 */
78
79xmlSAXLocator xmlDefaultSAXLocator = {
80 getPublicId, getSystemId, getLineNumber, getColumnNumber
81};
82
Daniel Veillard97b58771998-10-20 06:14:16 +000083/**
84 * resolveEntity:
85 * @ctxt: An XML parser context
86 * @publicId: The public ID of the entity
87 * @systemId: The system ID of the entity
88 *
Daniel Veillard260a68f1998-08-13 03:39:55 +000089 * Special entity resolver, better left to the parser, it has
90 * more context than the application layer.
Daniel Veillardccb09631998-10-27 06:21:04 +000091 * The default behaviour is to NOT resolve the entities, in that case
92 * the ENTITY_REF nodes are built in the structure (and the parameter
93 * values).
Daniel Veillard97b58771998-10-20 06:14:16 +000094 *
Daniel Veillardccb09631998-10-27 06:21:04 +000095 * return values: the xmlParserInputPtr if inlined or NULL for DOM behaviour.
Daniel Veillard260a68f1998-08-13 03:39:55 +000096 */
Daniel Veillard97b58771998-10-20 06:14:16 +000097xmlParserInputPtr
98resolveEntity(xmlParserCtxtPtr ctxt, const CHAR *publicId, const CHAR *systemId)
99{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000100
101#ifdef DEBUG_SAX
102 fprintf(stderr, "SAX.resolveEntity(%s, %s)\n", publicId, systemId);
103#endif
Daniel Veillardccb09631998-10-27 06:21:04 +0000104
Daniel Veillard260a68f1998-08-13 03:39:55 +0000105 return(NULL);
106}
107
Daniel Veillard97b58771998-10-20 06:14:16 +0000108/**
109 * notationDecl:
110 * @ctxt: An XML parser context
111 * @name: The name of the notation
112 * @publicId: The public ID of the entity
113 * @systemId: The system ID of the entity
114 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000115 * What to do when a notation declaration has been parsed.
116 * TODO Not handled currently.
Daniel Veillard97b58771998-10-20 06:14:16 +0000117 *
118 * return values:
Daniel Veillard260a68f1998-08-13 03:39:55 +0000119 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000120void
121notationDecl(xmlParserCtxtPtr ctxt, const CHAR *name,
122 const CHAR *publicId, const CHAR *systemId)
123{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000124#ifdef DEBUG_SAX
125 fprintf(stderr, "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
126#endif
127}
128
Daniel Veillard97b58771998-10-20 06:14:16 +0000129/**
130 * unparsedEntityDecl:
131 * @ctxt: An XML parser context
132 * @name: The name of the entity
133 * @publicId: The public ID of the entity
134 * @systemId: The system ID of the entity
135 * @notationName: the name of the notation
136 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000137 * What to do when an unparsed entity declaration is parsed
138 * TODO Create an Entity node.
Daniel Veillard97b58771998-10-20 06:14:16 +0000139 *
140 * return values:
Daniel Veillard260a68f1998-08-13 03:39:55 +0000141 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000142void
143unparsedEntityDecl(xmlParserCtxtPtr ctxt, const CHAR *name,
144 const CHAR *publicId, const CHAR *systemId,
145 const CHAR *notationName)
146{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000147#ifdef DEBUG_SAX
148 fprintf(stderr, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
149 name, publicId, systemId, notationName);
150#endif
151}
152
Daniel Veillard97b58771998-10-20 06:14:16 +0000153/**
154 * setDocumentLocator:
155 * @ctxt: An XML parser context
156 * @loc: A SAX Locator
157 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000158 * Receive the document locator at startup, actually xmlDefaultSAXLocator
159 * Everything is available on the context, so this is useless in our case.
Daniel Veillard97b58771998-10-20 06:14:16 +0000160 *
161 * return values:
Daniel Veillard260a68f1998-08-13 03:39:55 +0000162 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000163void
164setDocumentLocator(xmlParserCtxtPtr ctxt, xmlSAXLocatorPtr loc)
165{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000166#ifdef DEBUG_SAX
167 fprintf(stderr, "SAX.setDocumentLocator()\n");
168#endif
169}
170
Daniel Veillard97b58771998-10-20 06:14:16 +0000171/**
172 * startDocument:
173 * @ctxt: An XML parser context
174 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000175 * called when the document start being processed.
Daniel Veillard97b58771998-10-20 06:14:16 +0000176 *
177 * return values:
Daniel Veillard260a68f1998-08-13 03:39:55 +0000178 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000179void
180startDocument(xmlParserCtxtPtr ctxt)
181{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000182#ifdef DEBUG_SAX
183 fprintf(stderr, "SAX.startDocument()\n");
184#endif
185}
186
Daniel Veillard97b58771998-10-20 06:14:16 +0000187/**
188 * endDocument:
189 * @ctxt: An XML parser context
190 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000191 * called when the document end has been detected.
Daniel Veillard97b58771998-10-20 06:14:16 +0000192 *
193 * return values:
Daniel Veillard260a68f1998-08-13 03:39:55 +0000194 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000195void
196endDocument(xmlParserCtxtPtr ctxt)
197{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000198#ifdef DEBUG_SAX
199 fprintf(stderr, "SAX.endDocument()\n");
200#endif
201}
202
Daniel Veillard97b58771998-10-20 06:14:16 +0000203/**
204 * startElement:
205 * @ctxt: An XML parser context
206 * @name: The element name
207 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000208 * called when an opening tag has been processed.
209 * TODO We currently have a small pblm with the arguments ...
Daniel Veillard97b58771998-10-20 06:14:16 +0000210 *
211 * return values:
Daniel Veillard260a68f1998-08-13 03:39:55 +0000212 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000213void
214startElement(xmlParserCtxtPtr ctxt, const CHAR *name)
215{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000216#ifdef DEBUG_SAX
217 fprintf(stderr, "SAX.startElement(%s)\n", name);
218#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000219}
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
Daniel Veillard11e00581998-10-24 18:27:49 +0000257}
258
259/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000260 * characters:
261 * @ctxt: An XML parser context
262 * @ch: a CHAR string
263 * @start: the first char in the string
264 * @len: the number of CHAR
265 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000266 * receiving some chars from the parser.
267 * Question: how much at a time ???
Daniel Veillard97b58771998-10-20 06:14:16 +0000268 *
269 * return values:
Daniel Veillard260a68f1998-08-13 03:39:55 +0000270 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000271void
272characters(xmlParserCtxtPtr ctxt, const CHAR *ch, int start, int len)
273{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000274 xmlNodePtr lastChild;
275
276#ifdef DEBUG_SAX
277 fprintf(stderr, "SAX.characters(%.30s, %d, %d)\n", ch, start, len);
278#endif
279 /*
280 * Handle the data if any. If there is no child
281 * add it as content, otherwise if the last child is text,
282 * concatenate it, else create a new node of type text.
283 */
284
285 lastChild = xmlGetLastChild(ctxt->node);
286 if (lastChild == NULL)
287 xmlNodeAddContentLen(ctxt->node, &ch[start], len);
288 else {
289 if (xmlNodeIsText(lastChild))
290 xmlTextConcat(lastChild, &ch[start], len);
291 else {
292 lastChild = xmlNewTextLen(&ch[start], len);
293 xmlAddChild(ctxt->node, lastChild);
294 }
295 }
296}
297
Daniel Veillard97b58771998-10-20 06:14:16 +0000298/**
299 * ignorableWhitespace:
300 * @ctxt: An XML parser context
301 * @ch: a CHAR string
302 * @start: the first char in the string
303 * @len: the number of CHAR
304 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000305 * receiving some ignorable whitespaces from the parser.
306 * Question: how much at a time ???
Daniel Veillard97b58771998-10-20 06:14:16 +0000307 *
308 * return values:
Daniel Veillard260a68f1998-08-13 03:39:55 +0000309 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000310void
311ignorableWhitespace(xmlParserCtxtPtr ctxt, const CHAR *ch, int start, int len)
312{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000313#ifdef DEBUG_SAX
314 fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d, %d)\n", ch, start, len);
315#endif
316}
317
Daniel Veillard97b58771998-10-20 06:14:16 +0000318/**
319 * processingInstruction:
320 * @ctxt: An XML parser context
321 * @target: the target name
322 * @data: the PI data's
323 * @len: the number of CHAR
324 *
325 * A processing instruction has been parsed.
326 *
327 * return values:
Daniel Veillard260a68f1998-08-13 03:39:55 +0000328 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000329void
330processingInstruction(xmlParserCtxtPtr ctxt, const CHAR *target,
331 const CHAR *data)
332{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000333#ifdef DEBUG_SAX
334 fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
335#endif
336}
337
338xmlSAXHandler xmlDefaultSAXHandler = {
339 resolveEntity,
340 notationDecl,
341 unparsedEntityDecl,
342 setDocumentLocator,
343 startDocument,
344 endDocument,
345 startElement,
346 endElement,
Daniel Veillard11e00581998-10-24 18:27:49 +0000347 attribute,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000348 characters,
349 ignorableWhitespace,
350 processingInstruction,
351 xmlParserWarning,
352 xmlParserError,
353 xmlParserError,
354};
355
Daniel Veillard97b58771998-10-20 06:14:16 +0000356/**
357 * xmlDefaultSAXHandlerInit:
358 *
359 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +0000360 */
361void
362xmlDefaultSAXHandlerInit(void)
363{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000364 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
365 xmlDefaultSAXHandler.notationDecl = notationDecl;
366 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
367 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
368 xmlDefaultSAXHandler.startDocument = startDocument;
369 xmlDefaultSAXHandler.endDocument = endDocument;
370 xmlDefaultSAXHandler.startElement = startElement;
371 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard11e00581998-10-24 18:27:49 +0000372 xmlDefaultSAXHandler.attribute = attribute;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000373 xmlDefaultSAXHandler.characters = characters;
374 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
375 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
376 xmlDefaultSAXHandler.warning = xmlParserWarning;
377 xmlDefaultSAXHandler.error = xmlParserError;
378 xmlDefaultSAXHandler.fatalError = xmlParserError;
379}