blob: b4165565fdbbd77897fc37a9d43e62a93bab5ee0 [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 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000024 * Returns 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 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000039 * Returns 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 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000053 * Returns 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 *
Daniel Veillard1e346af1999-02-22 10:33:01 +000067 * Returns 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 Veillard1e346af1999-02-22 10:33:01 +000095 * Returns 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.
117 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000118void
119notationDecl(xmlParserCtxtPtr ctxt, const CHAR *name,
120 const CHAR *publicId, const CHAR *systemId)
121{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000122#ifdef DEBUG_SAX
123 fprintf(stderr, "SAX.notationDecl(%s, %s, %s)\n", name, publicId, systemId);
124#endif
125}
126
Daniel Veillard97b58771998-10-20 06:14:16 +0000127/**
128 * unparsedEntityDecl:
129 * @ctxt: An XML parser context
130 * @name: The name of the entity
131 * @publicId: The public ID of the entity
132 * @systemId: The system ID of the entity
133 * @notationName: the name of the notation
134 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000135 * What to do when an unparsed entity declaration is parsed
136 * TODO Create an Entity node.
137 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000138void
139unparsedEntityDecl(xmlParserCtxtPtr ctxt, const CHAR *name,
140 const CHAR *publicId, const CHAR *systemId,
141 const CHAR *notationName)
142{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000143#ifdef DEBUG_SAX
144 fprintf(stderr, "SAX.unparsedEntityDecl(%s, %s, %s, %s)\n",
145 name, publicId, systemId, notationName);
146#endif
147}
148
Daniel Veillard97b58771998-10-20 06:14:16 +0000149/**
150 * setDocumentLocator:
151 * @ctxt: An XML parser context
152 * @loc: A SAX Locator
153 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000154 * Receive the document locator at startup, actually xmlDefaultSAXLocator
155 * Everything is available on the context, so this is useless in our case.
156 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000157void
158setDocumentLocator(xmlParserCtxtPtr ctxt, xmlSAXLocatorPtr loc)
159{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000160#ifdef DEBUG_SAX
161 fprintf(stderr, "SAX.setDocumentLocator()\n");
162#endif
163}
164
Daniel Veillard97b58771998-10-20 06:14:16 +0000165/**
166 * startDocument:
167 * @ctxt: An XML parser context
168 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000169 * called when the document start being processed.
170 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000171void
172startDocument(xmlParserCtxtPtr ctxt)
173{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000174#ifdef DEBUG_SAX
175 fprintf(stderr, "SAX.startDocument()\n");
176#endif
177}
178
Daniel Veillard97b58771998-10-20 06:14:16 +0000179/**
180 * endDocument:
181 * @ctxt: An XML parser context
182 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000183 * called when the document end has been detected.
184 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000185void
186endDocument(xmlParserCtxtPtr ctxt)
187{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000188#ifdef DEBUG_SAX
189 fprintf(stderr, "SAX.endDocument()\n");
190#endif
191}
192
Daniel Veillard97b58771998-10-20 06:14:16 +0000193/**
194 * startElement:
195 * @ctxt: An XML parser context
196 * @name: The element name
197 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000198 * called when an opening tag has been processed.
199 * TODO We currently have a small pblm with the arguments ...
200 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000201void
202startElement(xmlParserCtxtPtr ctxt, const CHAR *name)
203{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000204#ifdef DEBUG_SAX
205 fprintf(stderr, "SAX.startElement(%s)\n", name);
206#endif
Daniel Veillard260a68f1998-08-13 03:39:55 +0000207}
208
Daniel Veillard97b58771998-10-20 06:14:16 +0000209/**
210 * endElement:
211 * @ctxt: An XML parser context
212 * @name: The element name
213 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000214 * called when the end of an element has been detected.
215 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000216void
217endElement(xmlParserCtxtPtr ctxt, const CHAR *name)
218{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000219#ifdef DEBUG_SAX
220 fprintf(stderr, "SAX.endElement(%s)\n", name);
221#endif
222}
223
Daniel Veillard97b58771998-10-20 06:14:16 +0000224/**
Daniel Veillard11e00581998-10-24 18:27:49 +0000225 * attribute:
226 * @ctxt: An XML parser context
227 * @name: The attribute name
228 * @value: The attribute value
229 *
230 * called when an attribute has been read by the parser.
231 * The default handling is to convert the attribute into an
232 * DOM subtree and past it in a new xmlAttr element added to
233 * the element.
Daniel Veillard11e00581998-10-24 18:27:49 +0000234 */
235void
236attribute(xmlParserCtxtPtr ctxt, const CHAR *name, const CHAR *value)
237{
238#ifdef DEBUG_SAX
239 fprintf(stderr, "SAX.attribute(%s, %s)\n", name, value);
240#endif
Daniel Veillard11e00581998-10-24 18:27:49 +0000241}
242
243/**
Daniel Veillard97b58771998-10-20 06:14:16 +0000244 * characters:
245 * @ctxt: An XML parser context
246 * @ch: a CHAR string
247 * @start: the first char in the string
248 * @len: the number of CHAR
249 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000250 * receiving some chars from the parser.
251 * Question: how much at a time ???
252 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000253void
254characters(xmlParserCtxtPtr ctxt, const CHAR *ch, int start, int len)
255{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000256 xmlNodePtr lastChild;
257
258#ifdef DEBUG_SAX
259 fprintf(stderr, "SAX.characters(%.30s, %d, %d)\n", ch, start, len);
260#endif
261 /*
262 * Handle the data if any. If there is no child
263 * add it as content, otherwise if the last child is text,
264 * concatenate it, else create a new node of type text.
265 */
266
267 lastChild = xmlGetLastChild(ctxt->node);
268 if (lastChild == NULL)
269 xmlNodeAddContentLen(ctxt->node, &ch[start], len);
270 else {
271 if (xmlNodeIsText(lastChild))
272 xmlTextConcat(lastChild, &ch[start], len);
273 else {
274 lastChild = xmlNewTextLen(&ch[start], len);
275 xmlAddChild(ctxt->node, lastChild);
276 }
277 }
278}
279
Daniel Veillard97b58771998-10-20 06:14:16 +0000280/**
281 * ignorableWhitespace:
282 * @ctxt: An XML parser context
283 * @ch: a CHAR string
284 * @start: the first char in the string
285 * @len: the number of CHAR
286 *
Daniel Veillard260a68f1998-08-13 03:39:55 +0000287 * receiving some ignorable whitespaces from the parser.
288 * Question: how much at a time ???
289 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000290void
291ignorableWhitespace(xmlParserCtxtPtr ctxt, const CHAR *ch, int start, int len)
292{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000293#ifdef DEBUG_SAX
294 fprintf(stderr, "SAX.ignorableWhitespace(%.30s, %d, %d)\n", ch, start, len);
295#endif
296}
297
Daniel Veillard97b58771998-10-20 06:14:16 +0000298/**
299 * processingInstruction:
300 * @ctxt: An XML parser context
301 * @target: the target name
302 * @data: the PI data's
303 * @len: the number of CHAR
304 *
305 * A processing instruction has been parsed.
Daniel Veillard260a68f1998-08-13 03:39:55 +0000306 */
Daniel Veillard97b58771998-10-20 06:14:16 +0000307void
308processingInstruction(xmlParserCtxtPtr ctxt, const CHAR *target,
309 const CHAR *data)
310{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000311#ifdef DEBUG_SAX
312 fprintf(stderr, "SAX.processingInstruction(%s, %s)\n", target, data);
313#endif
314}
315
316xmlSAXHandler xmlDefaultSAXHandler = {
317 resolveEntity,
318 notationDecl,
319 unparsedEntityDecl,
320 setDocumentLocator,
321 startDocument,
322 endDocument,
323 startElement,
324 endElement,
Daniel Veillard11e00581998-10-24 18:27:49 +0000325 attribute,
Daniel Veillard260a68f1998-08-13 03:39:55 +0000326 characters,
327 ignorableWhitespace,
328 processingInstruction,
329 xmlParserWarning,
330 xmlParserError,
331 xmlParserError,
332};
333
Daniel Veillard97b58771998-10-20 06:14:16 +0000334/**
335 * xmlDefaultSAXHandlerInit:
336 *
337 * Initialize the default SAX handler
Daniel Veillard97b58771998-10-20 06:14:16 +0000338 */
339void
340xmlDefaultSAXHandlerInit(void)
341{
Daniel Veillard260a68f1998-08-13 03:39:55 +0000342 xmlDefaultSAXHandler.resolveEntity = resolveEntity;
343 xmlDefaultSAXHandler.notationDecl = notationDecl;
344 xmlDefaultSAXHandler.unparsedEntityDecl = unparsedEntityDecl;
345 xmlDefaultSAXHandler.setDocumentLocator = setDocumentLocator;
346 xmlDefaultSAXHandler.startDocument = startDocument;
347 xmlDefaultSAXHandler.endDocument = endDocument;
348 xmlDefaultSAXHandler.startElement = startElement;
349 xmlDefaultSAXHandler.endElement = endElement;
Daniel Veillard11e00581998-10-24 18:27:49 +0000350 xmlDefaultSAXHandler.attribute = attribute;
Daniel Veillard260a68f1998-08-13 03:39:55 +0000351 xmlDefaultSAXHandler.characters = characters;
352 xmlDefaultSAXHandler.ignorableWhitespace = ignorableWhitespace;
353 xmlDefaultSAXHandler.processingInstruction = processingInstruction;
354 xmlDefaultSAXHandler.warning = xmlParserWarning;
355 xmlDefaultSAXHandler.error = xmlParserError;
356 xmlDefaultSAXHandler.fatalError = xmlParserError;
357}