Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/xml2/SAX2.c
4389 views
1
/*
2
* SAX2.c : Default SAX2 handler to build a tree.
3
*
4
* See Copyright for the status of this software.
5
*
6
* Daniel Veillard <[email protected]>
7
*/
8
9
10
#define IN_LIBXML
11
#include "libxml.h"
12
#include <stdlib.h>
13
#include <string.h>
14
#include <limits.h>
15
#include <stddef.h>
16
#include <libxml/SAX2.h>
17
#include <libxml/xmlmemory.h>
18
#include <libxml/tree.h>
19
#include <libxml/parser.h>
20
#include <libxml/parserInternals.h>
21
#include <libxml/valid.h>
22
#include <libxml/entities.h>
23
#include <libxml/xmlerror.h>
24
#include <libxml/debugXML.h>
25
#include <libxml/xmlIO.h>
26
#include <libxml/uri.h>
27
#include <libxml/valid.h>
28
#include <libxml/HTMLtree.h>
29
30
#include "private/error.h"
31
#include "private/parser.h"
32
#include "private/tree.h"
33
34
/**
35
* TODO:
36
*
37
* macro to flag unimplemented blocks
38
* XML_CATALOG_PREFER user env to select between system/public preferred
39
* option. C.f. Richard Tobin <[email protected]>
40
*> Just FYI, I am using an environment variable XML_CATALOG_PREFER with
41
*> values "system" and "public". I have made the default be "system" to
42
*> match yours.
43
*/
44
#define TODO \
45
xmlGenericError(xmlGenericErrorContext, \
46
"Unimplemented block at %s:%d\n", \
47
__FILE__, __LINE__);
48
49
/*
50
* xmlSAX2ErrMemory:
51
* @ctxt: an XML validation parser context
52
* @msg: a string to accompany the error message
53
*/
54
static void LIBXML_ATTR_FORMAT(2,0)
55
xmlSAX2ErrMemory(xmlParserCtxtPtr ctxt, const char *msg) {
56
xmlStructuredErrorFunc schannel = NULL;
57
const char *str1 = "out of memory\n";
58
59
if (ctxt != NULL) {
60
ctxt->errNo = XML_ERR_NO_MEMORY;
61
if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
62
schannel = ctxt->sax->serror;
63
__xmlRaiseError(schannel,
64
ctxt->vctxt.error, ctxt->vctxt.userData,
65
ctxt, NULL, XML_FROM_PARSER, XML_ERR_NO_MEMORY,
66
XML_ERR_ERROR, NULL, 0, (const char *) str1,
67
NULL, NULL, 0, 0,
68
msg, (const char *) str1, NULL);
69
ctxt->errNo = XML_ERR_NO_MEMORY;
70
ctxt->instate = XML_PARSER_EOF;
71
ctxt->disableSAX = 1;
72
} else {
73
__xmlRaiseError(schannel,
74
NULL, NULL,
75
ctxt, NULL, XML_FROM_PARSER, XML_ERR_NO_MEMORY,
76
XML_ERR_ERROR, NULL, 0, (const char *) str1,
77
NULL, NULL, 0, 0,
78
msg, (const char *) str1, NULL);
79
}
80
}
81
82
/**
83
* xmlValidError:
84
* @ctxt: an XML validation parser context
85
* @error: the error number
86
* @msg: the error message
87
* @str1: extra data
88
* @str2: extra data
89
*
90
* Handle a validation error
91
*/
92
static void LIBXML_ATTR_FORMAT(3,0)
93
xmlErrValid(xmlParserCtxtPtr ctxt, xmlParserErrors error,
94
const char *msg, const char *str1, const char *str2)
95
{
96
xmlStructuredErrorFunc schannel = NULL;
97
98
if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
99
(ctxt->instate == XML_PARSER_EOF))
100
return;
101
if (ctxt != NULL) {
102
ctxt->errNo = error;
103
if ((ctxt->sax != NULL) && (ctxt->sax->initialized == XML_SAX2_MAGIC))
104
schannel = ctxt->sax->serror;
105
__xmlRaiseError(schannel,
106
ctxt->vctxt.error, ctxt->vctxt.userData,
107
ctxt, NULL, XML_FROM_DTD, error,
108
XML_ERR_ERROR, NULL, 0, (const char *) str1,
109
(const char *) str2, NULL, 0, 0,
110
msg, (const char *) str1, (const char *) str2);
111
ctxt->valid = 0;
112
} else {
113
__xmlRaiseError(schannel,
114
NULL, NULL,
115
ctxt, NULL, XML_FROM_DTD, error,
116
XML_ERR_ERROR, NULL, 0, (const char *) str1,
117
(const char *) str2, NULL, 0, 0,
118
msg, (const char *) str1, (const char *) str2);
119
}
120
}
121
122
/**
123
* xmlFatalErrMsg:
124
* @ctxt: an XML parser context
125
* @error: the error number
126
* @msg: the error message
127
* @str1: an error string
128
* @str2: an error string
129
*
130
* Handle a fatal parser error, i.e. violating Well-Formedness constraints
131
*/
132
static void LIBXML_ATTR_FORMAT(3,0)
133
xmlFatalErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
134
const char *msg, const xmlChar *str1, const xmlChar *str2)
135
{
136
if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
137
(ctxt->instate == XML_PARSER_EOF))
138
return;
139
if (ctxt != NULL)
140
ctxt->errNo = error;
141
__xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
142
XML_ERR_FATAL, NULL, 0,
143
(const char *) str1, (const char *) str2,
144
NULL, 0, 0, msg, str1, str2);
145
if (ctxt != NULL) {
146
ctxt->wellFormed = 0;
147
ctxt->valid = 0;
148
if (ctxt->recovery == 0)
149
ctxt->disableSAX = 1;
150
}
151
}
152
153
/**
154
* xmlWarnMsg:
155
* @ctxt: an XML parser context
156
* @error: the error number
157
* @msg: the error message
158
* @str1: an error string
159
* @str2: an error string
160
*
161
* Handle a parser warning
162
*/
163
static void LIBXML_ATTR_FORMAT(3,0)
164
xmlWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
165
const char *msg, const xmlChar *str1)
166
{
167
if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
168
(ctxt->instate == XML_PARSER_EOF))
169
return;
170
if (ctxt != NULL)
171
ctxt->errNo = error;
172
__xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_PARSER, error,
173
XML_ERR_WARNING, NULL, 0,
174
(const char *) str1, NULL,
175
NULL, 0, 0, msg, str1);
176
}
177
178
/**
179
* xmlNsWarnMsg:
180
* @ctxt: an XML parser context
181
* @error: the error number
182
* @msg: the error message
183
* @str1: an error string
184
*
185
* Handle a namespace warning
186
*/
187
static void LIBXML_ATTR_FORMAT(3,0)
188
xmlNsWarnMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
189
const char *msg, const xmlChar *str1, const xmlChar *str2)
190
{
191
if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
192
(ctxt->instate == XML_PARSER_EOF))
193
return;
194
if (ctxt != NULL)
195
ctxt->errNo = error;
196
__xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
197
XML_ERR_WARNING, NULL, 0,
198
(const char *) str1, (const char *) str2,
199
NULL, 0, 0, msg, str1, str2);
200
}
201
202
/**
203
* xmlSAX2GetPublicId:
204
* @ctx: the user data (XML parser context)
205
*
206
* Provides the public ID e.g. "-//SGMLSOURCE//DTD DEMO//EN"
207
*
208
* Returns a xmlChar *
209
*/
210
const xmlChar *
211
xmlSAX2GetPublicId(void *ctx ATTRIBUTE_UNUSED)
212
{
213
/* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
214
return(NULL);
215
}
216
217
/**
218
* xmlSAX2GetSystemId:
219
* @ctx: the user data (XML parser context)
220
*
221
* Provides the system ID, basically URL or filename e.g.
222
* http://www.sgmlsource.com/dtds/memo.dtd
223
*
224
* Returns a xmlChar *
225
*/
226
const xmlChar *
227
xmlSAX2GetSystemId(void *ctx)
228
{
229
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
230
if ((ctx == NULL) || (ctxt->input == NULL)) return(NULL);
231
return((const xmlChar *) ctxt->input->filename);
232
}
233
234
/**
235
* xmlSAX2GetLineNumber:
236
* @ctx: the user data (XML parser context)
237
*
238
* Provide the line number of the current parsing point.
239
*
240
* Returns an int
241
*/
242
int
243
xmlSAX2GetLineNumber(void *ctx)
244
{
245
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
246
if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
247
return(ctxt->input->line);
248
}
249
250
/**
251
* xmlSAX2GetColumnNumber:
252
* @ctx: the user data (XML parser context)
253
*
254
* Provide the column number of the current parsing point.
255
*
256
* Returns an int
257
*/
258
int
259
xmlSAX2GetColumnNumber(void *ctx)
260
{
261
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
262
if ((ctx == NULL) || (ctxt->input == NULL)) return(0);
263
return(ctxt->input->col);
264
}
265
266
/**
267
* xmlSAX2IsStandalone:
268
* @ctx: the user data (XML parser context)
269
*
270
* Is this document tagged standalone ?
271
*
272
* Returns 1 if true
273
*/
274
int
275
xmlSAX2IsStandalone(void *ctx)
276
{
277
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
278
if ((ctx == NULL) || (ctxt->myDoc == NULL)) return(0);
279
return(ctxt->myDoc->standalone == 1);
280
}
281
282
/**
283
* xmlSAX2HasInternalSubset:
284
* @ctx: the user data (XML parser context)
285
*
286
* Does this document has an internal subset
287
*
288
* Returns 1 if true
289
*/
290
int
291
xmlSAX2HasInternalSubset(void *ctx)
292
{
293
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
294
if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
295
return(ctxt->myDoc->intSubset != NULL);
296
}
297
298
/**
299
* xmlSAX2HasExternalSubset:
300
* @ctx: the user data (XML parser context)
301
*
302
* Does this document has an external subset
303
*
304
* Returns 1 if true
305
*/
306
int
307
xmlSAX2HasExternalSubset(void *ctx)
308
{
309
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
310
if ((ctxt == NULL) || (ctxt->myDoc == NULL)) return(0);
311
return(ctxt->myDoc->extSubset != NULL);
312
}
313
314
/**
315
* xmlSAX2InternalSubset:
316
* @ctx: the user data (XML parser context)
317
* @name: the root element name
318
* @ExternalID: the external ID
319
* @SystemID: the SYSTEM ID (e.g. filename or URL)
320
*
321
* Callback on internal subset declaration.
322
*/
323
void
324
xmlSAX2InternalSubset(void *ctx, const xmlChar *name,
325
const xmlChar *ExternalID, const xmlChar *SystemID)
326
{
327
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
328
xmlDtdPtr dtd;
329
if (ctx == NULL) return;
330
331
if (ctxt->myDoc == NULL)
332
return;
333
dtd = xmlGetIntSubset(ctxt->myDoc);
334
if (dtd != NULL) {
335
if (ctxt->html)
336
return;
337
xmlUnlinkNode((xmlNodePtr) dtd);
338
xmlFreeDtd(dtd);
339
ctxt->myDoc->intSubset = NULL;
340
}
341
ctxt->myDoc->intSubset =
342
xmlCreateIntSubset(ctxt->myDoc, name, ExternalID, SystemID);
343
if (ctxt->myDoc->intSubset == NULL)
344
xmlSAX2ErrMemory(ctxt, "xmlSAX2InternalSubset");
345
}
346
347
/**
348
* xmlSAX2ExternalSubset:
349
* @ctx: the user data (XML parser context)
350
* @name: the root element name
351
* @ExternalID: the external ID
352
* @SystemID: the SYSTEM ID (e.g. filename or URL)
353
*
354
* Callback on external subset declaration.
355
*/
356
void
357
xmlSAX2ExternalSubset(void *ctx, const xmlChar *name,
358
const xmlChar *ExternalID, const xmlChar *SystemID)
359
{
360
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
361
if (ctx == NULL) return;
362
if (((ExternalID != NULL) || (SystemID != NULL)) &&
363
(((ctxt->validate) || (ctxt->loadsubset != 0)) &&
364
(ctxt->wellFormed && ctxt->myDoc))) {
365
/*
366
* Try to fetch and parse the external subset.
367
*/
368
xmlParserInputPtr oldinput;
369
int oldinputNr;
370
int oldinputMax;
371
xmlParserInputPtr *oldinputTab;
372
xmlParserInputPtr input = NULL;
373
const xmlChar *oldencoding;
374
int oldprogressive;
375
unsigned long consumed;
376
size_t buffered;
377
378
/*
379
* Ask the Entity resolver to load the damn thing
380
*/
381
if ((ctxt->sax != NULL) && (ctxt->sax->resolveEntity != NULL))
382
input = ctxt->sax->resolveEntity(ctxt->userData, ExternalID,
383
SystemID);
384
if (input == NULL) {
385
return;
386
}
387
388
xmlNewDtd(ctxt->myDoc, name, ExternalID, SystemID);
389
390
/*
391
* make sure we won't destroy the main document context
392
*/
393
oldinput = ctxt->input;
394
oldinputNr = ctxt->inputNr;
395
oldinputMax = ctxt->inputMax;
396
oldinputTab = ctxt->inputTab;
397
oldencoding = ctxt->encoding;
398
oldprogressive = ctxt->progressive;
399
ctxt->encoding = NULL;
400
ctxt->progressive = 0;
401
402
ctxt->inputTab = (xmlParserInputPtr *)
403
xmlMalloc(5 * sizeof(xmlParserInputPtr));
404
if (ctxt->inputTab == NULL) {
405
xmlSAX2ErrMemory(ctxt, "xmlSAX2ExternalSubset");
406
xmlFreeInputStream(input);
407
ctxt->input = oldinput;
408
ctxt->inputNr = oldinputNr;
409
ctxt->inputMax = oldinputMax;
410
ctxt->inputTab = oldinputTab;
411
ctxt->encoding = oldencoding;
412
ctxt->progressive = oldprogressive;
413
return;
414
}
415
ctxt->inputNr = 0;
416
ctxt->inputMax = 5;
417
ctxt->input = NULL;
418
xmlPushInput(ctxt, input);
419
420
if (input->filename == NULL)
421
input->filename = (char *) xmlCanonicPath(SystemID);
422
input->line = 1;
423
input->col = 1;
424
input->base = ctxt->input->cur;
425
input->cur = ctxt->input->cur;
426
input->free = NULL;
427
428
/*
429
* let's parse that entity knowing it's an external subset.
430
*/
431
xmlParseExternalSubset(ctxt, ExternalID, SystemID);
432
433
/*
434
* Free up the external entities
435
*/
436
437
while (ctxt->inputNr > 1)
438
xmlPopInput(ctxt);
439
440
consumed = ctxt->input->consumed;
441
buffered = ctxt->input->cur - ctxt->input->base;
442
if (buffered > ULONG_MAX - consumed)
443
consumed = ULONG_MAX;
444
else
445
consumed += buffered;
446
if (consumed > ULONG_MAX - ctxt->sizeentities)
447
ctxt->sizeentities = ULONG_MAX;
448
else
449
ctxt->sizeentities += consumed;
450
451
xmlFreeInputStream(ctxt->input);
452
xmlFree(ctxt->inputTab);
453
454
/*
455
* Restore the parsing context of the main entity
456
*/
457
ctxt->input = oldinput;
458
ctxt->inputNr = oldinputNr;
459
ctxt->inputMax = oldinputMax;
460
ctxt->inputTab = oldinputTab;
461
if ((ctxt->encoding != NULL) &&
462
((ctxt->dict == NULL) ||
463
(!xmlDictOwns(ctxt->dict, ctxt->encoding))))
464
xmlFree((xmlChar *) ctxt->encoding);
465
ctxt->encoding = oldencoding;
466
ctxt->progressive = oldprogressive;
467
/* ctxt->wellFormed = oldwellFormed; */
468
}
469
}
470
471
/**
472
* xmlSAX2ResolveEntity:
473
* @ctx: the user data (XML parser context)
474
* @publicId: The public ID of the entity
475
* @systemId: The system ID of the entity
476
*
477
* The entity loader, to control the loading of external entities,
478
* the application can either:
479
* - override this xmlSAX2ResolveEntity() callback in the SAX block
480
* - or better use the xmlSetExternalEntityLoader() function to
481
* set up it's own entity resolution routine
482
*
483
* Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour.
484
*/
485
xmlParserInputPtr
486
xmlSAX2ResolveEntity(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
487
{
488
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
489
xmlParserInputPtr ret;
490
xmlChar *URI;
491
const char *base = NULL;
492
493
if (ctx == NULL) return(NULL);
494
if (ctxt->input != NULL)
495
base = ctxt->input->filename;
496
if (base == NULL)
497
base = ctxt->directory;
498
499
URI = xmlBuildURI(systemId, (const xmlChar *) base);
500
501
ret = xmlLoadExternalEntity((const char *) URI,
502
(const char *) publicId, ctxt);
503
if (URI != NULL)
504
xmlFree(URI);
505
return(ret);
506
}
507
508
/**
509
* xmlSAX2GetEntity:
510
* @ctx: the user data (XML parser context)
511
* @name: The entity name
512
*
513
* Get an entity by name
514
*
515
* Returns the xmlEntityPtr if found.
516
*/
517
xmlEntityPtr
518
xmlSAX2GetEntity(void *ctx, const xmlChar *name)
519
{
520
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
521
xmlEntityPtr ret = NULL;
522
523
if (ctx == NULL) return(NULL);
524
525
if (ctxt->inSubset == 0) {
526
ret = xmlGetPredefinedEntity(name);
527
if (ret != NULL)
528
return(ret);
529
}
530
if ((ctxt->myDoc != NULL) && (ctxt->myDoc->standalone == 1)) {
531
if (ctxt->inSubset == 2) {
532
ctxt->myDoc->standalone = 0;
533
ret = xmlGetDocEntity(ctxt->myDoc, name);
534
ctxt->myDoc->standalone = 1;
535
} else {
536
ret = xmlGetDocEntity(ctxt->myDoc, name);
537
if (ret == NULL) {
538
ctxt->myDoc->standalone = 0;
539
ret = xmlGetDocEntity(ctxt->myDoc, name);
540
if (ret != NULL) {
541
xmlFatalErrMsg(ctxt, XML_ERR_NOT_STANDALONE,
542
"Entity(%s) document marked standalone but requires external subset\n",
543
name, NULL);
544
}
545
ctxt->myDoc->standalone = 1;
546
}
547
}
548
} else {
549
ret = xmlGetDocEntity(ctxt->myDoc, name);
550
}
551
return(ret);
552
}
553
554
/**
555
* xmlSAX2GetParameterEntity:
556
* @ctx: the user data (XML parser context)
557
* @name: The entity name
558
*
559
* Get a parameter entity by name
560
*
561
* Returns the xmlEntityPtr if found.
562
*/
563
xmlEntityPtr
564
xmlSAX2GetParameterEntity(void *ctx, const xmlChar *name)
565
{
566
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
567
xmlEntityPtr ret;
568
569
if (ctx == NULL) return(NULL);
570
571
ret = xmlGetParameterEntity(ctxt->myDoc, name);
572
return(ret);
573
}
574
575
576
/**
577
* xmlSAX2EntityDecl:
578
* @ctx: the user data (XML parser context)
579
* @name: the entity name
580
* @type: the entity type
581
* @publicId: The public ID of the entity
582
* @systemId: The system ID of the entity
583
* @content: the entity value (without processing).
584
*
585
* An entity definition has been parsed
586
*/
587
void
588
xmlSAX2EntityDecl(void *ctx, const xmlChar *name, int type,
589
const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
590
{
591
xmlEntityPtr ent;
592
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
593
594
if (ctx == NULL) return;
595
if (ctxt->inSubset == 1) {
596
ent = xmlAddDocEntity(ctxt->myDoc, name, type, publicId,
597
systemId, content);
598
if ((ent == NULL) && (ctxt->pedantic))
599
xmlWarnMsg(ctxt, XML_WAR_ENTITY_REDEFINED,
600
"Entity(%s) already defined in the internal subset\n",
601
name);
602
if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
603
xmlChar *URI;
604
const char *base = NULL;
605
606
if (ctxt->input != NULL)
607
base = ctxt->input->filename;
608
if (base == NULL)
609
base = ctxt->directory;
610
611
URI = xmlBuildURI(systemId, (const xmlChar *) base);
612
ent->URI = URI;
613
}
614
} else if (ctxt->inSubset == 2) {
615
ent = xmlAddDtdEntity(ctxt->myDoc, name, type, publicId,
616
systemId, content);
617
if ((ent == NULL) && (ctxt->pedantic) &&
618
(ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
619
ctxt->sax->warning(ctxt->userData,
620
"Entity(%s) already defined in the external subset\n", name);
621
if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
622
xmlChar *URI;
623
const char *base = NULL;
624
625
if (ctxt->input != NULL)
626
base = ctxt->input->filename;
627
if (base == NULL)
628
base = ctxt->directory;
629
630
URI = xmlBuildURI(systemId, (const xmlChar *) base);
631
ent->URI = URI;
632
}
633
} else {
634
xmlFatalErrMsg(ctxt, XML_ERR_ENTITY_PROCESSING,
635
"SAX.xmlSAX2EntityDecl(%s) called while not in subset\n",
636
name, NULL);
637
}
638
}
639
640
/**
641
* xmlSAX2AttributeDecl:
642
* @ctx: the user data (XML parser context)
643
* @elem: the name of the element
644
* @fullname: the attribute name
645
* @type: the attribute type
646
* @def: the type of default value
647
* @defaultValue: the attribute default value
648
* @tree: the tree of enumerated value set
649
*
650
* An attribute definition has been parsed
651
*/
652
void
653
xmlSAX2AttributeDecl(void *ctx, const xmlChar *elem, const xmlChar *fullname,
654
int type, int def, const xmlChar *defaultValue,
655
xmlEnumerationPtr tree)
656
{
657
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
658
xmlAttributePtr attr;
659
xmlChar *name = NULL, *prefix = NULL;
660
661
/* Avoid unused variable warning if features are disabled. */
662
(void) attr;
663
664
if ((ctxt == NULL) || (ctxt->myDoc == NULL))
665
return;
666
667
if ((xmlStrEqual(fullname, BAD_CAST "xml:id")) &&
668
(type != XML_ATTRIBUTE_ID)) {
669
/*
670
* Raise the error but keep the validity flag
671
*/
672
int tmp = ctxt->valid;
673
xmlErrValid(ctxt, XML_DTD_XMLID_TYPE,
674
"xml:id : attribute type should be ID\n", NULL, NULL);
675
ctxt->valid = tmp;
676
}
677
/* TODO: optimize name/prefix allocation */
678
name = xmlSplitQName(ctxt, fullname, &prefix);
679
ctxt->vctxt.valid = 1;
680
if (ctxt->inSubset == 1)
681
attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, elem,
682
name, prefix, (xmlAttributeType) type,
683
(xmlAttributeDefault) def, defaultValue, tree);
684
else if (ctxt->inSubset == 2)
685
attr = xmlAddAttributeDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, elem,
686
name, prefix, (xmlAttributeType) type,
687
(xmlAttributeDefault) def, defaultValue, tree);
688
else {
689
xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
690
"SAX.xmlSAX2AttributeDecl(%s) called while not in subset\n",
691
name, NULL);
692
xmlFree(name);
693
xmlFreeEnumeration(tree);
694
return;
695
}
696
#ifdef LIBXML_VALID_ENABLED
697
if (ctxt->vctxt.valid == 0)
698
ctxt->valid = 0;
699
if ((attr != NULL) && (ctxt->validate) && (ctxt->wellFormed) &&
700
(ctxt->myDoc->intSubset != NULL))
701
ctxt->valid &= xmlValidateAttributeDecl(&ctxt->vctxt, ctxt->myDoc,
702
attr);
703
#endif /* LIBXML_VALID_ENABLED */
704
if (prefix != NULL)
705
xmlFree(prefix);
706
if (name != NULL)
707
xmlFree(name);
708
}
709
710
/**
711
* xmlSAX2ElementDecl:
712
* @ctx: the user data (XML parser context)
713
* @name: the element name
714
* @type: the element type
715
* @content: the element value tree
716
*
717
* An element definition has been parsed
718
*/
719
void
720
xmlSAX2ElementDecl(void *ctx, const xmlChar * name, int type,
721
xmlElementContentPtr content)
722
{
723
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
724
xmlElementPtr elem = NULL;
725
726
/* Avoid unused variable warning if features are disabled. */
727
(void) elem;
728
729
if ((ctxt == NULL) || (ctxt->myDoc == NULL))
730
return;
731
732
if (ctxt->inSubset == 1)
733
elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->intSubset,
734
name, (xmlElementTypeVal) type, content);
735
else if (ctxt->inSubset == 2)
736
elem = xmlAddElementDecl(&ctxt->vctxt, ctxt->myDoc->extSubset,
737
name, (xmlElementTypeVal) type, content);
738
else {
739
xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
740
"SAX.xmlSAX2ElementDecl(%s) called while not in subset\n",
741
name, NULL);
742
return;
743
}
744
#ifdef LIBXML_VALID_ENABLED
745
if (elem == NULL)
746
ctxt->valid = 0;
747
if (ctxt->validate && ctxt->wellFormed &&
748
ctxt->myDoc && ctxt->myDoc->intSubset)
749
ctxt->valid &=
750
xmlValidateElementDecl(&ctxt->vctxt, ctxt->myDoc, elem);
751
#endif /* LIBXML_VALID_ENABLED */
752
}
753
754
/**
755
* xmlSAX2NotationDecl:
756
* @ctx: the user data (XML parser context)
757
* @name: The name of the notation
758
* @publicId: The public ID of the entity
759
* @systemId: The system ID of the entity
760
*
761
* What to do when a notation declaration has been parsed.
762
*/
763
void
764
xmlSAX2NotationDecl(void *ctx, const xmlChar *name,
765
const xmlChar *publicId, const xmlChar *systemId)
766
{
767
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
768
xmlNotationPtr nota = NULL;
769
770
/* Avoid unused variable warning if features are disabled. */
771
(void) nota;
772
773
if ((ctxt == NULL) || (ctxt->myDoc == NULL))
774
return;
775
776
if ((publicId == NULL) && (systemId == NULL)) {
777
xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
778
"SAX.xmlSAX2NotationDecl(%s) externalID or PublicID missing\n",
779
name, NULL);
780
return;
781
} else if (ctxt->inSubset == 1)
782
nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->intSubset, name,
783
publicId, systemId);
784
else if (ctxt->inSubset == 2)
785
nota = xmlAddNotationDecl(&ctxt->vctxt, ctxt->myDoc->extSubset, name,
786
publicId, systemId);
787
else {
788
xmlFatalErrMsg(ctxt, XML_ERR_NOTATION_PROCESSING,
789
"SAX.xmlSAX2NotationDecl(%s) called while not in subset\n",
790
name, NULL);
791
return;
792
}
793
#ifdef LIBXML_VALID_ENABLED
794
if (nota == NULL) ctxt->valid = 0;
795
if ((ctxt->validate) && (ctxt->wellFormed) &&
796
(ctxt->myDoc->intSubset != NULL))
797
ctxt->valid &= xmlValidateNotationDecl(&ctxt->vctxt, ctxt->myDoc,
798
nota);
799
#endif /* LIBXML_VALID_ENABLED */
800
}
801
802
/**
803
* xmlSAX2UnparsedEntityDecl:
804
* @ctx: the user data (XML parser context)
805
* @name: The name of the entity
806
* @publicId: The public ID of the entity
807
* @systemId: The system ID of the entity
808
* @notationName: the name of the notation
809
*
810
* What to do when an unparsed entity declaration is parsed
811
*/
812
void
813
xmlSAX2UnparsedEntityDecl(void *ctx, const xmlChar *name,
814
const xmlChar *publicId, const xmlChar *systemId,
815
const xmlChar *notationName)
816
{
817
xmlEntityPtr ent;
818
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
819
if (ctx == NULL) return;
820
if (ctxt->inSubset == 1) {
821
ent = xmlAddDocEntity(ctxt->myDoc, name,
822
XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
823
publicId, systemId, notationName);
824
if ((ent == NULL) && (ctxt->pedantic) &&
825
(ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
826
ctxt->sax->warning(ctxt->userData,
827
"Entity(%s) already defined in the internal subset\n", name);
828
if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
829
xmlChar *URI;
830
const char *base = NULL;
831
832
if (ctxt->input != NULL)
833
base = ctxt->input->filename;
834
if (base == NULL)
835
base = ctxt->directory;
836
837
URI = xmlBuildURI(systemId, (const xmlChar *) base);
838
ent->URI = URI;
839
}
840
} else if (ctxt->inSubset == 2) {
841
ent = xmlAddDtdEntity(ctxt->myDoc, name,
842
XML_EXTERNAL_GENERAL_UNPARSED_ENTITY,
843
publicId, systemId, notationName);
844
if ((ent == NULL) && (ctxt->pedantic) &&
845
(ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
846
ctxt->sax->warning(ctxt->userData,
847
"Entity(%s) already defined in the external subset\n", name);
848
if ((ent != NULL) && (ent->URI == NULL) && (systemId != NULL)) {
849
xmlChar *URI;
850
const char *base = NULL;
851
852
if (ctxt->input != NULL)
853
base = ctxt->input->filename;
854
if (base == NULL)
855
base = ctxt->directory;
856
857
URI = xmlBuildURI(systemId, (const xmlChar *) base);
858
ent->URI = URI;
859
}
860
} else {
861
xmlFatalErrMsg(ctxt, XML_ERR_INTERNAL_ERROR,
862
"SAX.xmlSAX2UnparsedEntityDecl(%s) called while not in subset\n",
863
name, NULL);
864
}
865
}
866
867
/**
868
* xmlSAX2SetDocumentLocator:
869
* @ctx: the user data (XML parser context)
870
* @loc: A SAX Locator
871
*
872
* Receive the document locator at startup, actually xmlDefaultSAXLocator
873
* Everything is available on the context, so this is useless in our case.
874
*/
875
void
876
xmlSAX2SetDocumentLocator(void *ctx ATTRIBUTE_UNUSED, xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED)
877
{
878
}
879
880
/**
881
* xmlSAX2StartDocument:
882
* @ctx: the user data (XML parser context)
883
*
884
* called when the document start being processed.
885
*/
886
void
887
xmlSAX2StartDocument(void *ctx)
888
{
889
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
890
xmlDocPtr doc;
891
892
if (ctx == NULL) return;
893
894
if (ctxt->html) {
895
#ifdef LIBXML_HTML_ENABLED
896
if (ctxt->myDoc == NULL)
897
ctxt->myDoc = htmlNewDocNoDtD(NULL, NULL);
898
if (ctxt->myDoc == NULL) {
899
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
900
return;
901
}
902
ctxt->myDoc->properties = XML_DOC_HTML;
903
ctxt->myDoc->parseFlags = ctxt->options;
904
#else
905
xmlGenericError(xmlGenericErrorContext,
906
"libxml2 built without HTML support\n");
907
ctxt->errNo = XML_ERR_INTERNAL_ERROR;
908
ctxt->instate = XML_PARSER_EOF;
909
ctxt->disableSAX = 1;
910
return;
911
#endif
912
} else {
913
doc = ctxt->myDoc = xmlNewDoc(ctxt->version);
914
if (doc != NULL) {
915
doc->properties = 0;
916
if (ctxt->options & XML_PARSE_OLD10)
917
doc->properties |= XML_DOC_OLD10;
918
doc->parseFlags = ctxt->options;
919
doc->standalone = ctxt->standalone;
920
} else {
921
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
922
return;
923
}
924
if ((ctxt->dictNames) && (doc != NULL)) {
925
doc->dict = ctxt->dict;
926
xmlDictReference(doc->dict);
927
}
928
}
929
if ((ctxt->myDoc != NULL) && (ctxt->myDoc->URL == NULL) &&
930
(ctxt->input != NULL) && (ctxt->input->filename != NULL)) {
931
ctxt->myDoc->URL = xmlPathToURI((const xmlChar *)ctxt->input->filename);
932
if (ctxt->myDoc->URL == NULL)
933
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartDocument");
934
}
935
}
936
937
/**
938
* xmlSAX2EndDocument:
939
* @ctx: the user data (XML parser context)
940
*
941
* called when the document end has been detected.
942
*/
943
void
944
xmlSAX2EndDocument(void *ctx)
945
{
946
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
947
xmlDocPtr doc;
948
949
if (ctx == NULL) return;
950
#ifdef LIBXML_VALID_ENABLED
951
if (ctxt->validate && ctxt->wellFormed &&
952
ctxt->myDoc && ctxt->myDoc->intSubset)
953
ctxt->valid &= xmlValidateDocumentFinal(&ctxt->vctxt, ctxt->myDoc);
954
#endif /* LIBXML_VALID_ENABLED */
955
956
doc = ctxt->myDoc;
957
if ((doc != NULL) && (doc->encoding == NULL)) {
958
const xmlChar *encoding = xmlGetActualEncoding(ctxt);
959
960
if (encoding != NULL) {
961
doc->encoding = xmlStrdup(encoding);
962
if (doc->encoding == NULL)
963
xmlSAX2ErrMemory(ctxt, "xmlSAX2EndDocument");
964
}
965
}
966
}
967
968
#if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_LEGACY_ENABLED)
969
/**
970
* xmlNsErrMsg:
971
* @ctxt: an XML parser context
972
* @error: the error number
973
* @msg: the error message
974
* @str1: an error string
975
* @str2: an error string
976
*
977
* Handle a namespace error
978
*/
979
static void LIBXML_ATTR_FORMAT(3,0)
980
xmlNsErrMsg(xmlParserCtxtPtr ctxt, xmlParserErrors error,
981
const char *msg, const xmlChar *str1, const xmlChar *str2)
982
{
983
if ((ctxt != NULL) && (ctxt->disableSAX != 0) &&
984
(ctxt->instate == XML_PARSER_EOF))
985
return;
986
if (ctxt != NULL)
987
ctxt->errNo = error;
988
__xmlRaiseError(NULL, NULL, NULL, ctxt, NULL, XML_FROM_NAMESPACE, error,
989
XML_ERR_ERROR, NULL, 0,
990
(const char *) str1, (const char *) str2,
991
NULL, 0, 0, msg, str1, str2);
992
}
993
994
/**
995
* xmlSAX2AttributeInternal:
996
* @ctx: the user data (XML parser context)
997
* @fullname: The attribute name, including namespace prefix
998
* @value: The attribute value
999
* @prefix: the prefix on the element node
1000
*
1001
* Handle an attribute that has been read by the parser.
1002
* The default handling is to convert the attribute into an
1003
* DOM subtree and past it in a new xmlAttr element added to
1004
* the element.
1005
*/
1006
static void
1007
xmlSAX2AttributeInternal(void *ctx, const xmlChar *fullname,
1008
const xmlChar *value, const xmlChar *prefix ATTRIBUTE_UNUSED)
1009
{
1010
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1011
xmlAttrPtr ret;
1012
xmlChar *name;
1013
xmlChar *ns;
1014
xmlChar *nval;
1015
xmlNsPtr namespace;
1016
1017
if (ctxt->html) {
1018
name = xmlStrdup(fullname);
1019
ns = NULL;
1020
namespace = NULL;
1021
} else {
1022
/*
1023
* Split the full name into a namespace prefix and the tag name
1024
*/
1025
name = xmlSplitQName(ctxt, fullname, &ns);
1026
if ((name != NULL) && (name[0] == 0)) {
1027
if (xmlStrEqual(ns, BAD_CAST "xmlns")) {
1028
xmlNsErrMsg(ctxt, XML_ERR_NS_DECL_ERROR,
1029
"invalid namespace declaration '%s'\n",
1030
fullname, NULL);
1031
} else {
1032
xmlNsWarnMsg(ctxt, XML_WAR_NS_COLUMN,
1033
"Avoid attribute ending with ':' like '%s'\n",
1034
fullname, NULL);
1035
}
1036
if (ns != NULL)
1037
xmlFree(ns);
1038
ns = NULL;
1039
xmlFree(name);
1040
name = xmlStrdup(fullname);
1041
}
1042
}
1043
if (name == NULL) {
1044
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1045
if (ns != NULL)
1046
xmlFree(ns);
1047
return;
1048
}
1049
1050
#ifdef LIBXML_HTML_ENABLED
1051
if ((ctxt->html) &&
1052
(value == NULL) && (htmlIsBooleanAttr(fullname))) {
1053
nval = xmlStrdup(fullname);
1054
value = (const xmlChar *) nval;
1055
} else
1056
#endif
1057
{
1058
#ifdef LIBXML_VALID_ENABLED
1059
/*
1060
* Do the last stage of the attribute normalization
1061
* Needed for HTML too:
1062
* http://www.w3.org/TR/html4/types.html#h-6.2
1063
*/
1064
ctxt->vctxt.valid = 1;
1065
nval = xmlValidCtxtNormalizeAttributeValue(&ctxt->vctxt,
1066
ctxt->myDoc, ctxt->node,
1067
fullname, value);
1068
if (ctxt->vctxt.valid != 1) {
1069
ctxt->valid = 0;
1070
}
1071
if (nval != NULL)
1072
value = nval;
1073
#else
1074
nval = NULL;
1075
#endif /* LIBXML_VALID_ENABLED */
1076
}
1077
1078
/*
1079
* Check whether it's a namespace definition
1080
*/
1081
if ((!ctxt->html) && (ns == NULL) &&
1082
(name[0] == 'x') && (name[1] == 'm') && (name[2] == 'l') &&
1083
(name[3] == 'n') && (name[4] == 's') && (name[5] == 0)) {
1084
xmlNsPtr nsret;
1085
xmlChar *val;
1086
1087
/* Avoid unused variable warning if features are disabled. */
1088
(void) nsret;
1089
1090
if (!ctxt->replaceEntities) {
1091
ctxt->depth++;
1092
val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1093
0,0,0);
1094
ctxt->depth--;
1095
if (val == NULL) {
1096
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1097
if (name != NULL)
1098
xmlFree(name);
1099
if (nval != NULL)
1100
xmlFree(nval);
1101
return;
1102
}
1103
} else {
1104
val = (xmlChar *) value;
1105
}
1106
1107
if (val[0] != 0) {
1108
xmlURIPtr uri;
1109
1110
uri = xmlParseURI((const char *)val);
1111
if (uri == NULL) {
1112
if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1113
ctxt->sax->warning(ctxt->userData,
1114
"xmlns: %s not a valid URI\n", val);
1115
} else {
1116
if (uri->scheme == NULL) {
1117
if ((ctxt->sax != NULL) && (ctxt->sax->warning != NULL))
1118
ctxt->sax->warning(ctxt->userData,
1119
"xmlns: URI %s is not absolute\n", val);
1120
}
1121
xmlFreeURI(uri);
1122
}
1123
}
1124
1125
/* a default namespace definition */
1126
nsret = xmlNewNs(ctxt->node, val, NULL);
1127
1128
#ifdef LIBXML_VALID_ENABLED
1129
/*
1130
* Validate also for namespace decls, they are attributes from
1131
* an XML-1.0 perspective
1132
*/
1133
if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1134
ctxt->myDoc && ctxt->myDoc->intSubset)
1135
ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1136
ctxt->node, prefix, nsret, val);
1137
#endif /* LIBXML_VALID_ENABLED */
1138
if (name != NULL)
1139
xmlFree(name);
1140
if (nval != NULL)
1141
xmlFree(nval);
1142
if (val != value)
1143
xmlFree(val);
1144
return;
1145
}
1146
if ((!ctxt->html) &&
1147
(ns != NULL) && (ns[0] == 'x') && (ns[1] == 'm') && (ns[2] == 'l') &&
1148
(ns[3] == 'n') && (ns[4] == 's') && (ns[5] == 0)) {
1149
xmlNsPtr nsret;
1150
xmlChar *val;
1151
1152
/* Avoid unused variable warning if features are disabled. */
1153
(void) nsret;
1154
1155
if (!ctxt->replaceEntities) {
1156
ctxt->depth++;
1157
val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1158
0,0,0);
1159
ctxt->depth--;
1160
if (val == NULL) {
1161
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1162
xmlFree(ns);
1163
if (name != NULL)
1164
xmlFree(name);
1165
if (nval != NULL)
1166
xmlFree(nval);
1167
return;
1168
}
1169
} else {
1170
val = (xmlChar *) value;
1171
}
1172
1173
if (val[0] == 0) {
1174
xmlNsErrMsg(ctxt, XML_NS_ERR_EMPTY,
1175
"Empty namespace name for prefix %s\n", name, NULL);
1176
}
1177
if ((ctxt->pedantic != 0) && (val[0] != 0)) {
1178
xmlURIPtr uri;
1179
1180
uri = xmlParseURI((const char *)val);
1181
if (uri == NULL) {
1182
xmlNsWarnMsg(ctxt, XML_WAR_NS_URI,
1183
"xmlns:%s: %s not a valid URI\n", name, value);
1184
} else {
1185
if (uri->scheme == NULL) {
1186
xmlNsWarnMsg(ctxt, XML_WAR_NS_URI_RELATIVE,
1187
"xmlns:%s: URI %s is not absolute\n", name, value);
1188
}
1189
xmlFreeURI(uri);
1190
}
1191
}
1192
1193
/* a standard namespace definition */
1194
nsret = xmlNewNs(ctxt->node, val, name);
1195
xmlFree(ns);
1196
#ifdef LIBXML_VALID_ENABLED
1197
/*
1198
* Validate also for namespace decls, they are attributes from
1199
* an XML-1.0 perspective
1200
*/
1201
if (nsret != NULL && ctxt->validate && ctxt->wellFormed &&
1202
ctxt->myDoc && ctxt->myDoc->intSubset)
1203
ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
1204
ctxt->node, prefix, nsret, value);
1205
#endif /* LIBXML_VALID_ENABLED */
1206
if (name != NULL)
1207
xmlFree(name);
1208
if (nval != NULL)
1209
xmlFree(nval);
1210
if (val != value)
1211
xmlFree(val);
1212
return;
1213
}
1214
1215
if (ns != NULL) {
1216
namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, ns);
1217
1218
if (namespace == NULL) {
1219
xmlNsErrMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
1220
"Namespace prefix %s of attribute %s is not defined\n",
1221
ns, name);
1222
} else {
1223
xmlAttrPtr prop;
1224
1225
prop = ctxt->node->properties;
1226
while (prop != NULL) {
1227
if (prop->ns != NULL) {
1228
if ((xmlStrEqual(name, prop->name)) &&
1229
((namespace == prop->ns) ||
1230
(xmlStrEqual(namespace->href, prop->ns->href)))) {
1231
xmlNsErrMsg(ctxt, XML_ERR_ATTRIBUTE_REDEFINED,
1232
"Attribute %s in %s redefined\n",
1233
name, namespace->href);
1234
ctxt->wellFormed = 0;
1235
if (ctxt->recovery == 0) ctxt->disableSAX = 1;
1236
if (name != NULL)
1237
xmlFree(name);
1238
goto error;
1239
}
1240
}
1241
prop = prop->next;
1242
}
1243
}
1244
} else {
1245
namespace = NULL;
1246
}
1247
1248
/* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
1249
ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
1250
if (ret == NULL)
1251
goto error;
1252
1253
if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1254
xmlNodePtr tmp;
1255
1256
ret->children = xmlStringGetNodeList(ctxt->myDoc, value);
1257
tmp = ret->children;
1258
while (tmp != NULL) {
1259
tmp->parent = (xmlNodePtr) ret;
1260
if (tmp->next == NULL)
1261
ret->last = tmp;
1262
tmp = tmp->next;
1263
}
1264
} else if (value != NULL) {
1265
ret->children = xmlNewDocText(ctxt->myDoc, value);
1266
ret->last = ret->children;
1267
if (ret->children != NULL)
1268
ret->children->parent = (xmlNodePtr) ret;
1269
}
1270
1271
#ifdef LIBXML_VALID_ENABLED
1272
if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1273
ctxt->myDoc && ctxt->myDoc->intSubset) {
1274
1275
/*
1276
* If we don't substitute entities, the validation should be
1277
* done on a value with replaced entities anyway.
1278
*/
1279
if (!ctxt->replaceEntities) {
1280
xmlChar *val;
1281
1282
ctxt->depth++;
1283
val = xmlStringDecodeEntities(ctxt, value, XML_SUBSTITUTE_REF,
1284
0,0,0);
1285
ctxt->depth--;
1286
1287
if (val == NULL)
1288
ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1289
ctxt->myDoc, ctxt->node, ret, value);
1290
else {
1291
xmlChar *nvalnorm;
1292
1293
/*
1294
* Do the last stage of the attribute normalization
1295
* It need to be done twice ... it's an extra burden related
1296
* to the ability to keep xmlSAX2References in attributes
1297
*/
1298
nvalnorm = xmlValidNormalizeAttributeValue(ctxt->myDoc,
1299
ctxt->node, fullname, val);
1300
if (nvalnorm != NULL) {
1301
xmlFree(val);
1302
val = nvalnorm;
1303
}
1304
1305
ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1306
ctxt->myDoc, ctxt->node, ret, val);
1307
xmlFree(val);
1308
}
1309
} else {
1310
ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt, ctxt->myDoc,
1311
ctxt->node, ret, value);
1312
}
1313
} else
1314
#endif /* LIBXML_VALID_ENABLED */
1315
if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
1316
(((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
1317
((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0))) &&
1318
/* Don't create IDs containing entity references */
1319
(ret->children != NULL) &&
1320
(ret->children->type == XML_TEXT_NODE) &&
1321
(ret->children->next == NULL)) {
1322
xmlChar *content = ret->children->content;
1323
/*
1324
* when validating, the ID registration is done at the attribute
1325
* validation level. Otherwise we have to do specific handling here.
1326
*/
1327
if (xmlStrEqual(fullname, BAD_CAST "xml:id")) {
1328
/*
1329
* Add the xml:id value
1330
*
1331
* Open issue: normalization of the value.
1332
*/
1333
if (xmlValidateNCName(content, 1) != 0) {
1334
xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
1335
"xml:id : attribute value %s is not an NCName\n",
1336
(const char *) content, NULL);
1337
}
1338
xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
1339
} else if (xmlIsID(ctxt->myDoc, ctxt->node, ret))
1340
xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
1341
else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret))
1342
xmlAddRef(&ctxt->vctxt, ctxt->myDoc, content, ret);
1343
}
1344
1345
error:
1346
if (nval != NULL)
1347
xmlFree(nval);
1348
if (ns != NULL)
1349
xmlFree(ns);
1350
}
1351
1352
/*
1353
* xmlCheckDefaultedAttributes:
1354
*
1355
* Check defaulted attributes from the DTD
1356
*/
1357
static void
1358
xmlCheckDefaultedAttributes(xmlParserCtxtPtr ctxt, const xmlChar *name,
1359
const xmlChar *prefix, const xmlChar **atts) {
1360
xmlElementPtr elemDecl;
1361
const xmlChar *att;
1362
int internal = 1;
1363
int i;
1364
1365
elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->intSubset, name, prefix);
1366
if (elemDecl == NULL) {
1367
elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset, name, prefix);
1368
internal = 0;
1369
}
1370
1371
process_external_subset:
1372
1373
if (elemDecl != NULL) {
1374
xmlAttributePtr attr = elemDecl->attributes;
1375
/*
1376
* Check against defaulted attributes from the external subset
1377
* if the document is stamped as standalone
1378
*/
1379
if ((ctxt->myDoc->standalone == 1) &&
1380
(ctxt->myDoc->extSubset != NULL) &&
1381
(ctxt->validate)) {
1382
while (attr != NULL) {
1383
if ((attr->defaultValue != NULL) &&
1384
(xmlGetDtdQAttrDesc(ctxt->myDoc->extSubset,
1385
attr->elem, attr->name,
1386
attr->prefix) == attr) &&
1387
(xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1388
attr->elem, attr->name,
1389
attr->prefix) == NULL)) {
1390
xmlChar *fulln;
1391
1392
if (attr->prefix != NULL) {
1393
fulln = xmlStrdup(attr->prefix);
1394
fulln = xmlStrcat(fulln, BAD_CAST ":");
1395
fulln = xmlStrcat(fulln, attr->name);
1396
} else {
1397
fulln = xmlStrdup(attr->name);
1398
}
1399
if (fulln == NULL) {
1400
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1401
break;
1402
}
1403
1404
/*
1405
* Check that the attribute is not declared in the
1406
* serialization
1407
*/
1408
att = NULL;
1409
if (atts != NULL) {
1410
i = 0;
1411
att = atts[i];
1412
while (att != NULL) {
1413
if (xmlStrEqual(att, fulln))
1414
break;
1415
i += 2;
1416
att = atts[i];
1417
}
1418
}
1419
if (att == NULL) {
1420
xmlErrValid(ctxt, XML_DTD_STANDALONE_DEFAULTED,
1421
"standalone: attribute %s on %s defaulted from external subset\n",
1422
(const char *)fulln,
1423
(const char *)attr->elem);
1424
}
1425
xmlFree(fulln);
1426
}
1427
attr = attr->nexth;
1428
}
1429
}
1430
1431
/*
1432
* Actually insert defaulted values when needed
1433
*/
1434
attr = elemDecl->attributes;
1435
while (attr != NULL) {
1436
/*
1437
* Make sure that attributes redefinition occurring in the
1438
* internal subset are not overridden by definitions in the
1439
* external subset.
1440
*/
1441
if (attr->defaultValue != NULL) {
1442
/*
1443
* the element should be instantiated in the tree if:
1444
* - this is a namespace prefix
1445
* - the user required for completion in the tree
1446
* like XSLT
1447
* - there isn't already an attribute definition
1448
* in the internal subset overriding it.
1449
*/
1450
if (((attr->prefix != NULL) &&
1451
(xmlStrEqual(attr->prefix, BAD_CAST "xmlns"))) ||
1452
((attr->prefix == NULL) &&
1453
(xmlStrEqual(attr->name, BAD_CAST "xmlns"))) ||
1454
(ctxt->loadsubset & XML_COMPLETE_ATTRS)) {
1455
xmlAttributePtr tst;
1456
1457
tst = xmlGetDtdQAttrDesc(ctxt->myDoc->intSubset,
1458
attr->elem, attr->name,
1459
attr->prefix);
1460
if ((tst == attr) || (tst == NULL)) {
1461
xmlChar fn[50];
1462
xmlChar *fulln;
1463
1464
fulln = xmlBuildQName(attr->name, attr->prefix, fn, 50);
1465
if (fulln == NULL) {
1466
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1467
return;
1468
}
1469
1470
/*
1471
* Check that the attribute is not declared in the
1472
* serialization
1473
*/
1474
att = NULL;
1475
if (atts != NULL) {
1476
i = 0;
1477
att = atts[i];
1478
while (att != NULL) {
1479
if (xmlStrEqual(att, fulln))
1480
break;
1481
i += 2;
1482
att = atts[i];
1483
}
1484
}
1485
if (att == NULL) {
1486
xmlSAX2AttributeInternal(ctxt, fulln,
1487
attr->defaultValue, prefix);
1488
}
1489
if ((fulln != fn) && (fulln != attr->name))
1490
xmlFree(fulln);
1491
}
1492
}
1493
}
1494
attr = attr->nexth;
1495
}
1496
if (internal == 1) {
1497
elemDecl = xmlGetDtdQElementDesc(ctxt->myDoc->extSubset,
1498
name, prefix);
1499
internal = 0;
1500
goto process_external_subset;
1501
}
1502
}
1503
}
1504
1505
/**
1506
* xmlSAX2StartElement:
1507
* @ctx: the user data (XML parser context)
1508
* @fullname: The element name, including namespace prefix
1509
* @atts: An array of name/value attributes pairs, NULL terminated
1510
*
1511
* called when an opening tag has been processed.
1512
*/
1513
void
1514
xmlSAX2StartElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
1515
{
1516
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1517
xmlNodePtr ret;
1518
xmlNodePtr parent;
1519
xmlNsPtr ns;
1520
xmlChar *name;
1521
xmlChar *prefix;
1522
const xmlChar *att;
1523
const xmlChar *value;
1524
int i;
1525
1526
if ((ctx == NULL) || (fullname == NULL) || (ctxt->myDoc == NULL)) return;
1527
1528
/*
1529
* First check on validity:
1530
*/
1531
if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
1532
((ctxt->myDoc->intSubset == NULL) ||
1533
((ctxt->myDoc->intSubset->notations == NULL) &&
1534
(ctxt->myDoc->intSubset->elements == NULL) &&
1535
(ctxt->myDoc->intSubset->attributes == NULL) &&
1536
(ctxt->myDoc->intSubset->entities == NULL)))) {
1537
xmlErrValid(ctxt, XML_ERR_NO_DTD,
1538
"Validation failed: no DTD found !", NULL, NULL);
1539
ctxt->validate = 0;
1540
}
1541
1542
if (ctxt->html) {
1543
prefix = NULL;
1544
name = xmlStrdup(fullname);
1545
} else {
1546
/*
1547
* Split the full name into a namespace prefix and the tag name
1548
*/
1549
name = xmlSplitQName(ctxt, fullname, &prefix);
1550
}
1551
1552
/*
1553
* Note : the namespace resolution is deferred until the end of the
1554
* attributes parsing, since local namespace can be defined as
1555
* an attribute at this level.
1556
*/
1557
ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
1558
if (ret == NULL) {
1559
if (prefix != NULL)
1560
xmlFree(prefix);
1561
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElement");
1562
return;
1563
}
1564
ctxt->nodemem = -1;
1565
if (ctxt->linenumbers) {
1566
if (ctxt->input != NULL) {
1567
if ((unsigned) ctxt->input->line < (unsigned) USHRT_MAX)
1568
ret->line = ctxt->input->line;
1569
else
1570
ret->line = USHRT_MAX;
1571
}
1572
}
1573
1574
/* Initialize parent before pushing node */
1575
parent = ctxt->node;
1576
if (parent == NULL)
1577
parent = (xmlNodePtr) ctxt->myDoc;
1578
1579
/*
1580
* We are parsing a new node.
1581
*/
1582
if (nodePush(ctxt, ret) < 0) {
1583
xmlUnlinkNode(ret);
1584
xmlFreeNode(ret);
1585
if (prefix != NULL)
1586
xmlFree(prefix);
1587
return;
1588
}
1589
1590
/*
1591
* Link the child element
1592
*/
1593
xmlAddChild(parent, ret);
1594
1595
if (!ctxt->html) {
1596
/*
1597
* Insert all the defaulted attributes from the DTD especially
1598
* namespaces
1599
*/
1600
if ((ctxt->myDoc->intSubset != NULL) ||
1601
(ctxt->myDoc->extSubset != NULL)) {
1602
xmlCheckDefaultedAttributes(ctxt, name, prefix, atts);
1603
}
1604
1605
/*
1606
* process all the attributes whose name start with "xmlns"
1607
*/
1608
if (atts != NULL) {
1609
i = 0;
1610
att = atts[i++];
1611
value = atts[i++];
1612
while ((att != NULL) && (value != NULL)) {
1613
if ((att[0] == 'x') && (att[1] == 'm') && (att[2] == 'l') &&
1614
(att[3] == 'n') && (att[4] == 's'))
1615
xmlSAX2AttributeInternal(ctxt, att, value, prefix);
1616
1617
att = atts[i++];
1618
value = atts[i++];
1619
}
1620
}
1621
1622
/*
1623
* Search the namespace, note that since the attributes have been
1624
* processed, the local namespaces are available.
1625
*/
1626
ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
1627
if ((ns == NULL) && (parent != NULL))
1628
ns = xmlSearchNs(ctxt->myDoc, parent, prefix);
1629
if ((prefix != NULL) && (ns == NULL)) {
1630
ns = xmlNewNs(ret, NULL, prefix);
1631
xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
1632
"Namespace prefix %s is not defined\n",
1633
prefix, NULL);
1634
}
1635
1636
/*
1637
* set the namespace node, making sure that if the default namespace
1638
* is unbound on a parent we simply keep it NULL
1639
*/
1640
if ((ns != NULL) && (ns->href != NULL) &&
1641
((ns->href[0] != 0) || (ns->prefix != NULL)))
1642
xmlSetNs(ret, ns);
1643
}
1644
1645
/*
1646
* process all the other attributes
1647
*/
1648
if (atts != NULL) {
1649
i = 0;
1650
att = atts[i++];
1651
value = atts[i++];
1652
if (ctxt->html) {
1653
while (att != NULL) {
1654
xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1655
att = atts[i++];
1656
value = atts[i++];
1657
}
1658
} else {
1659
while ((att != NULL) && (value != NULL)) {
1660
if ((att[0] != 'x') || (att[1] != 'm') || (att[2] != 'l') ||
1661
(att[3] != 'n') || (att[4] != 's'))
1662
xmlSAX2AttributeInternal(ctxt, att, value, NULL);
1663
1664
/*
1665
* Next ones
1666
*/
1667
att = atts[i++];
1668
value = atts[i++];
1669
}
1670
}
1671
}
1672
1673
#ifdef LIBXML_VALID_ENABLED
1674
/*
1675
* If it's the Document root, finish the DTD validation and
1676
* check the document root element for validity
1677
*/
1678
if ((ctxt->validate) &&
1679
((ctxt->vctxt.flags & XML_VCTXT_DTD_VALIDATED) == 0)) {
1680
int chk;
1681
1682
chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
1683
if (chk <= 0)
1684
ctxt->valid = 0;
1685
if (chk < 0)
1686
ctxt->wellFormed = 0;
1687
ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
1688
ctxt->vctxt.flags |= XML_VCTXT_DTD_VALIDATED;
1689
}
1690
#endif /* LIBXML_VALID_ENABLED */
1691
1692
if (prefix != NULL)
1693
xmlFree(prefix);
1694
1695
}
1696
1697
/**
1698
* xmlSAX2EndElement:
1699
* @ctx: the user data (XML parser context)
1700
* @name: The element name
1701
*
1702
* called when the end of an element has been detected.
1703
*/
1704
void
1705
xmlSAX2EndElement(void *ctx, const xmlChar *name ATTRIBUTE_UNUSED)
1706
{
1707
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
1708
1709
if (ctx == NULL) return;
1710
1711
ctxt->nodemem = -1;
1712
1713
#ifdef LIBXML_VALID_ENABLED
1714
if (ctxt->validate && ctxt->wellFormed &&
1715
ctxt->myDoc && ctxt->myDoc->intSubset)
1716
ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
1717
ctxt->node);
1718
#endif /* LIBXML_VALID_ENABLED */
1719
1720
1721
/*
1722
* end of parsing of this node.
1723
*/
1724
nodePop(ctxt);
1725
}
1726
#endif /* LIBXML_SAX1_ENABLED || LIBXML_HTML_ENABLED || LIBXML_LEGACY_ENABLED */
1727
1728
/*
1729
* xmlSAX2TextNode:
1730
* @ctxt: the parser context
1731
* @str: the input string
1732
* @len: the string length
1733
*
1734
* Callback for a text node
1735
*
1736
* Returns the newly allocated string or NULL if not needed or error
1737
*/
1738
static xmlNodePtr
1739
xmlSAX2TextNode(xmlParserCtxtPtr ctxt, const xmlChar *str, int len) {
1740
xmlNodePtr ret;
1741
const xmlChar *intern = NULL;
1742
1743
/*
1744
* Allocate
1745
*/
1746
if (ctxt->freeElems != NULL) {
1747
ret = ctxt->freeElems;
1748
ctxt->freeElems = ret->next;
1749
ctxt->freeElemsNr--;
1750
} else {
1751
ret = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
1752
}
1753
if (ret == NULL) {
1754
xmlErrMemory(ctxt, "xmlSAX2Characters");
1755
return(NULL);
1756
}
1757
memset(ret, 0, sizeof(xmlNode));
1758
/*
1759
* intern the formatting blanks found between tags, or the
1760
* very short strings
1761
*/
1762
if (ctxt->dictNames) {
1763
xmlChar cur = str[len];
1764
1765
if ((len < (int) (2 * sizeof(void *))) &&
1766
(ctxt->options & XML_PARSE_COMPACT)) {
1767
/* store the string in the node overriding properties and nsDef */
1768
xmlChar *tmp = (xmlChar *) &(ret->properties);
1769
memcpy(tmp, str, len);
1770
tmp[len] = 0;
1771
intern = tmp;
1772
} else if ((len <= 3) && ((cur == '"') || (cur == '\'') ||
1773
((cur == '<') && (str[len + 1] != '!')))) {
1774
intern = xmlDictLookup(ctxt->dict, str, len);
1775
} else if (IS_BLANK_CH(*str) && (len < 60) && (cur == '<') &&
1776
(str[len + 1] != '!')) {
1777
int i;
1778
1779
for (i = 1;i < len;i++) {
1780
if (!IS_BLANK_CH(str[i])) goto skip;
1781
}
1782
intern = xmlDictLookup(ctxt->dict, str, len);
1783
}
1784
}
1785
skip:
1786
ret->type = XML_TEXT_NODE;
1787
1788
ret->name = xmlStringText;
1789
if (intern == NULL) {
1790
ret->content = xmlStrndup(str, len);
1791
if (ret->content == NULL) {
1792
xmlSAX2ErrMemory(ctxt, "xmlSAX2TextNode");
1793
xmlFree(ret);
1794
return(NULL);
1795
}
1796
} else
1797
ret->content = (xmlChar *) intern;
1798
1799
if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1800
xmlRegisterNodeDefaultValue(ret);
1801
return(ret);
1802
}
1803
1804
#ifdef LIBXML_VALID_ENABLED
1805
/*
1806
* xmlSAX2DecodeAttrEntities:
1807
* @ctxt: the parser context
1808
* @str: the input string
1809
* @len: the string length
1810
*
1811
* Remove the entities from an attribute value
1812
*
1813
* Returns the newly allocated string or NULL if not needed or error
1814
*/
1815
static xmlChar *
1816
xmlSAX2DecodeAttrEntities(xmlParserCtxtPtr ctxt, const xmlChar *str,
1817
const xmlChar *end) {
1818
const xmlChar *in;
1819
xmlChar *ret;
1820
1821
in = str;
1822
while (in < end)
1823
if (*in++ == '&')
1824
goto decode;
1825
return(NULL);
1826
decode:
1827
ctxt->depth++;
1828
ret = xmlStringLenDecodeEntities(ctxt, str, end - str,
1829
XML_SUBSTITUTE_REF, 0,0,0);
1830
ctxt->depth--;
1831
return(ret);
1832
}
1833
#endif /* LIBXML_VALID_ENABLED */
1834
1835
/**
1836
* xmlSAX2AttributeNs:
1837
* @ctx: the user data (XML parser context)
1838
* @localname: the local name of the attribute
1839
* @prefix: the attribute namespace prefix if available
1840
* @URI: the attribute namespace name if available
1841
* @value: Start of the attribute value
1842
* @valueend: end of the attribute value
1843
*
1844
* Handle an attribute that has been read by the parser.
1845
* The default handling is to convert the attribute into an
1846
* DOM subtree and past it in a new xmlAttr element added to
1847
* the element.
1848
*
1849
* Returns the new attribute or NULL in case of error.
1850
*/
1851
static xmlAttrPtr
1852
xmlSAX2AttributeNs(xmlParserCtxtPtr ctxt,
1853
const xmlChar * localname,
1854
const xmlChar * prefix,
1855
const xmlChar * value,
1856
const xmlChar * valueend)
1857
{
1858
xmlAttrPtr ret;
1859
xmlNsPtr namespace = NULL;
1860
xmlChar *dup = NULL;
1861
1862
/*
1863
* Note: if prefix == NULL, the attribute is not in the default namespace
1864
*/
1865
if (prefix != NULL) {
1866
namespace = xmlParserNsLookupSax(ctxt, prefix);
1867
if ((namespace == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
1868
namespace = xmlSearchNs(ctxt->myDoc, ctxt->node, prefix);
1869
}
1870
}
1871
1872
/*
1873
* allocate the node
1874
*/
1875
if (ctxt->freeAttrs != NULL) {
1876
ret = ctxt->freeAttrs;
1877
ctxt->freeAttrs = ret->next;
1878
ctxt->freeAttrsNr--;
1879
} else {
1880
ret = xmlMalloc(sizeof(*ret));
1881
if (ret == NULL) {
1882
xmlSAX2ErrMemory(ctxt, NULL);
1883
return(NULL);
1884
}
1885
}
1886
1887
memset(ret, 0, sizeof(xmlAttr));
1888
ret->type = XML_ATTRIBUTE_NODE;
1889
1890
/*
1891
* xmlParseBalancedChunkMemoryRecover had a bug that could result in
1892
* a mismatch between ctxt->node->doc and ctxt->myDoc. We use
1893
* ctxt->node->doc here, but we should somehow make sure that the
1894
* document pointers match.
1895
*/
1896
1897
/* assert(ctxt->node->doc == ctxt->myDoc); */
1898
1899
ret->parent = ctxt->node;
1900
ret->doc = ctxt->node->doc;
1901
ret->ns = namespace;
1902
1903
if (ctxt->dictNames)
1904
ret->name = localname;
1905
else
1906
ret->name = xmlStrdup(localname);
1907
1908
if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
1909
xmlRegisterNodeDefaultValue((xmlNodePtr)ret);
1910
1911
if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
1912
xmlNodePtr tmp;
1913
1914
/*
1915
* We know that if there is an entity reference, then
1916
* the string has been dup'ed and terminates with 0
1917
* otherwise with ' or "
1918
*/
1919
if (*valueend != 0) {
1920
tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1921
ret->children = tmp;
1922
ret->last = tmp;
1923
if (tmp != NULL) {
1924
tmp->doc = ret->doc;
1925
tmp->parent = (xmlNodePtr) ret;
1926
}
1927
} else {
1928
ret->children = xmlStringLenGetNodeList(ctxt->myDoc, value,
1929
valueend - value);
1930
tmp = ret->children;
1931
while (tmp != NULL) {
1932
tmp->doc = ret->doc;
1933
tmp->parent = (xmlNodePtr) ret;
1934
if (tmp->next == NULL)
1935
ret->last = tmp;
1936
tmp = tmp->next;
1937
}
1938
}
1939
} else if (value != NULL) {
1940
xmlNodePtr tmp;
1941
1942
tmp = xmlSAX2TextNode(ctxt, value, valueend - value);
1943
ret->children = tmp;
1944
ret->last = tmp;
1945
if (tmp != NULL) {
1946
tmp->doc = ret->doc;
1947
tmp->parent = (xmlNodePtr) ret;
1948
}
1949
}
1950
1951
#ifdef LIBXML_VALID_ENABLED
1952
if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
1953
ctxt->myDoc && ctxt->myDoc->intSubset) {
1954
/*
1955
* If we don't substitute entities, the validation should be
1956
* done on a value with replaced entities anyway.
1957
*/
1958
if (!ctxt->replaceEntities) {
1959
dup = xmlSAX2DecodeAttrEntities(ctxt, value, valueend);
1960
if (dup == NULL) {
1961
if (*valueend == 0) {
1962
ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1963
ctxt->myDoc, ctxt->node, ret, value);
1964
} else {
1965
/*
1966
* That should already be normalized.
1967
* cheaper to finally allocate here than duplicate
1968
* entry points in the full validation code
1969
*/
1970
dup = xmlStrndup(value, valueend - value);
1971
1972
ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
1973
ctxt->myDoc, ctxt->node, ret, dup);
1974
}
1975
} else {
1976
/*
1977
* dup now contains a string of the flattened attribute
1978
* content with entities substituted. Check if we need to
1979
* apply an extra layer of normalization.
1980
* It need to be done twice ... it's an extra burden related
1981
* to the ability to keep references in attributes
1982
*/
1983
if (ctxt->attsSpecial != NULL) {
1984
xmlChar *nvalnorm;
1985
xmlChar fn[50];
1986
xmlChar *fullname;
1987
1988
fullname = xmlBuildQName(localname, prefix, fn, 50);
1989
if (fullname != NULL) {
1990
ctxt->vctxt.valid = 1;
1991
nvalnorm = xmlValidCtxtNormalizeAttributeValue(
1992
&ctxt->vctxt, ctxt->myDoc,
1993
ctxt->node, fullname, dup);
1994
if (ctxt->vctxt.valid != 1)
1995
ctxt->valid = 0;
1996
1997
if ((fullname != fn) && (fullname != localname))
1998
xmlFree(fullname);
1999
if (nvalnorm != NULL) {
2000
xmlFree(dup);
2001
dup = nvalnorm;
2002
}
2003
}
2004
}
2005
2006
ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2007
ctxt->myDoc, ctxt->node, ret, dup);
2008
}
2009
} else {
2010
/*
2011
* if entities already have been substituted, then
2012
* the attribute as passed is already normalized
2013
*/
2014
dup = xmlStrndup(value, valueend - value);
2015
2016
ctxt->valid &= xmlValidateOneAttribute(&ctxt->vctxt,
2017
ctxt->myDoc, ctxt->node, ret, dup);
2018
}
2019
} else
2020
#endif /* LIBXML_VALID_ENABLED */
2021
if (((ctxt->loadsubset & XML_SKIP_IDS) == 0) &&
2022
(((ctxt->replaceEntities == 0) && (ctxt->external != 2)) ||
2023
((ctxt->replaceEntities != 0) && (ctxt->inSubset == 0))) &&
2024
/* Don't create IDs containing entity references */
2025
(ret->children != NULL) &&
2026
(ret->children->type == XML_TEXT_NODE) &&
2027
(ret->children->next == NULL)) {
2028
xmlChar *content = ret->children->content;
2029
/*
2030
* when validating, the ID registration is done at the attribute
2031
* validation level. Otherwise we have to do specific handling here.
2032
*/
2033
if ((prefix == ctxt->str_xml) &&
2034
(localname[0] == 'i') && (localname[1] == 'd') &&
2035
(localname[2] == 0)) {
2036
/*
2037
* Add the xml:id value
2038
*
2039
* Open issue: normalization of the value.
2040
*/
2041
if (xmlValidateNCName(content, 1) != 0) {
2042
xmlErrValid(ctxt, XML_DTD_XMLID_VALUE,
2043
"xml:id : attribute value %s is not an NCName\n",
2044
(const char *) content, NULL);
2045
}
2046
xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
2047
} else if (xmlIsID(ctxt->myDoc, ctxt->node, ret)) {
2048
xmlAddID(&ctxt->vctxt, ctxt->myDoc, content, ret);
2049
} else if (xmlIsRef(ctxt->myDoc, ctxt->node, ret)) {
2050
xmlAddRef(&ctxt->vctxt, ctxt->myDoc, content, ret);
2051
}
2052
}
2053
if (dup != NULL)
2054
xmlFree(dup);
2055
2056
return(ret);
2057
}
2058
2059
/**
2060
* xmlSAX2StartElementNs:
2061
* @ctx: the user data (XML parser context)
2062
* @localname: the local name of the element
2063
* @prefix: the element namespace prefix if available
2064
* @URI: the element namespace name if available
2065
* @nb_namespaces: number of namespace definitions on that node
2066
* @namespaces: pointer to the array of prefix/URI pairs namespace definitions
2067
* @nb_attributes: the number of attributes on that node
2068
* @nb_defaulted: the number of defaulted attributes.
2069
* @attributes: pointer to the array of (localname/prefix/URI/value/end)
2070
* attribute values.
2071
*
2072
* SAX2 callback when an element start has been detected by the parser.
2073
* It provides the namespace information for the element, as well as
2074
* the new namespace declarations on the element.
2075
*/
2076
void
2077
xmlSAX2StartElementNs(void *ctx,
2078
const xmlChar *localname,
2079
const xmlChar *prefix,
2080
const xmlChar *URI,
2081
int nb_namespaces,
2082
const xmlChar **namespaces,
2083
int nb_attributes,
2084
int nb_defaulted,
2085
const xmlChar **attributes)
2086
{
2087
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2088
xmlNodePtr ret;
2089
xmlNodePtr parent;
2090
xmlNsPtr last = NULL, ns;
2091
const xmlChar *uri, *pref;
2092
xmlChar *lname = NULL;
2093
int i, j;
2094
2095
if (ctx == NULL) return;
2096
/*
2097
* First check on validity:
2098
*/
2099
if (ctxt->validate && (ctxt->myDoc->extSubset == NULL) &&
2100
((ctxt->myDoc->intSubset == NULL) ||
2101
((ctxt->myDoc->intSubset->notations == NULL) &&
2102
(ctxt->myDoc->intSubset->elements == NULL) &&
2103
(ctxt->myDoc->intSubset->attributes == NULL) &&
2104
(ctxt->myDoc->intSubset->entities == NULL)))) {
2105
xmlErrValid(ctxt, XML_DTD_NO_DTD,
2106
"Validation failed: no DTD found !", NULL, NULL);
2107
ctxt->validate = 0;
2108
}
2109
2110
/*
2111
* Take care of the rare case of an undefined namespace prefix
2112
*/
2113
if ((prefix != NULL) && (URI == NULL)) {
2114
if (ctxt->dictNames) {
2115
const xmlChar *fullname;
2116
2117
fullname = xmlDictQLookup(ctxt->dict, prefix, localname);
2118
if (fullname != NULL)
2119
localname = fullname;
2120
} else {
2121
lname = xmlBuildQName(localname, prefix, NULL, 0);
2122
}
2123
}
2124
/*
2125
* allocate the node
2126
*/
2127
if (ctxt->freeElems != NULL) {
2128
ret = ctxt->freeElems;
2129
ctxt->freeElems = ret->next;
2130
ctxt->freeElemsNr--;
2131
memset(ret, 0, sizeof(xmlNode));
2132
ret->doc = ctxt->myDoc;
2133
ret->type = XML_ELEMENT_NODE;
2134
2135
if (ctxt->dictNames)
2136
ret->name = localname;
2137
else {
2138
if (lname == NULL)
2139
ret->name = xmlStrdup(localname);
2140
else
2141
ret->name = lname;
2142
if (ret->name == NULL) {
2143
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
2144
xmlFree(ret);
2145
return;
2146
}
2147
}
2148
if ((__xmlRegisterCallbacks) && (xmlRegisterNodeDefaultValue))
2149
xmlRegisterNodeDefaultValue(ret);
2150
} else {
2151
if (ctxt->dictNames)
2152
ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
2153
(xmlChar *) localname, NULL);
2154
else if (lname == NULL)
2155
ret = xmlNewDocNode(ctxt->myDoc, NULL, localname, NULL);
2156
else
2157
ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL,
2158
(xmlChar *) lname, NULL);
2159
if (ret == NULL) {
2160
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
2161
return;
2162
}
2163
}
2164
if (ctxt->linenumbers) {
2165
if (ctxt->input != NULL) {
2166
if ((unsigned) ctxt->input->line < (unsigned) USHRT_MAX)
2167
ret->line = ctxt->input->line;
2168
else
2169
ret->line = USHRT_MAX;
2170
}
2171
}
2172
2173
/*
2174
* Build the namespace list
2175
*/
2176
for (i = 0,j = 0;j < nb_namespaces;j++) {
2177
pref = namespaces[i++];
2178
uri = namespaces[i++];
2179
ns = xmlNewNs(NULL, uri, pref);
2180
if (ns != NULL) {
2181
if (last == NULL) {
2182
ret->nsDef = last = ns;
2183
} else {
2184
last->next = ns;
2185
last = ns;
2186
}
2187
if ((URI != NULL) && (prefix == pref))
2188
ret->ns = ns;
2189
} else {
2190
/*
2191
* any out of memory error would already have been raised
2192
* but we can't be guaranteed it's the actual error due to the
2193
* API, best is to skip in this case
2194
*/
2195
continue;
2196
}
2197
2198
xmlParserNsUpdateSax(ctxt, pref, ns);
2199
2200
#ifdef LIBXML_VALID_ENABLED
2201
if ((!ctxt->html) && ctxt->validate && ctxt->wellFormed &&
2202
ctxt->myDoc && ctxt->myDoc->intSubset) {
2203
ctxt->valid &= xmlValidateOneNamespace(&ctxt->vctxt, ctxt->myDoc,
2204
ret, prefix, ns, uri);
2205
}
2206
#endif /* LIBXML_VALID_ENABLED */
2207
}
2208
ctxt->nodemem = -1;
2209
2210
/* Initialize parent before pushing node */
2211
parent = ctxt->node;
2212
if (parent == NULL)
2213
parent = (xmlNodePtr) ctxt->myDoc;
2214
2215
/*
2216
* We are parsing a new node.
2217
*/
2218
if (nodePush(ctxt, ret) < 0) {
2219
xmlUnlinkNode(ret);
2220
xmlFreeNode(ret);
2221
return;
2222
}
2223
2224
/*
2225
* Link the child element
2226
*/
2227
xmlAddChild(parent, ret);
2228
2229
/*
2230
* Insert the defaulted attributes from the DTD only if requested:
2231
*/
2232
if ((nb_defaulted != 0) &&
2233
((ctxt->loadsubset & XML_COMPLETE_ATTRS) == 0))
2234
nb_attributes -= nb_defaulted;
2235
2236
/*
2237
* Search the namespace if it wasn't already found
2238
* Note that, if prefix is NULL, this searches for the default Ns
2239
*/
2240
if ((URI != NULL) && (ret->ns == NULL)) {
2241
ret->ns = xmlParserNsLookupSax(ctxt, prefix);
2242
if ((ret->ns == NULL) && (xmlStrEqual(prefix, BAD_CAST "xml"))) {
2243
ret->ns = xmlSearchNs(ctxt->myDoc, ret, prefix);
2244
}
2245
if (ret->ns == NULL) {
2246
ns = xmlNewNs(ret, NULL, prefix);
2247
if (ns == NULL) {
2248
2249
xmlSAX2ErrMemory(ctxt, "xmlSAX2StartElementNs");
2250
return;
2251
}
2252
if (prefix != NULL)
2253
xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
2254
"Namespace prefix %s was not found\n",
2255
prefix, NULL);
2256
else
2257
xmlNsWarnMsg(ctxt, XML_NS_ERR_UNDEFINED_NAMESPACE,
2258
"Namespace default prefix was not found\n",
2259
NULL, NULL);
2260
}
2261
}
2262
2263
/*
2264
* process all the other attributes
2265
*/
2266
if (nb_attributes > 0) {
2267
xmlAttrPtr prev = NULL;
2268
2269
for (j = 0,i = 0;i < nb_attributes;i++,j+=5) {
2270
xmlAttrPtr attr = NULL;
2271
2272
/*
2273
* Handle the rare case of an undefined attribute prefix
2274
*/
2275
if ((attributes[j+1] != NULL) && (attributes[j+2] == NULL)) {
2276
if (ctxt->dictNames) {
2277
const xmlChar *fullname;
2278
2279
fullname = xmlDictQLookup(ctxt->dict, attributes[j+1],
2280
attributes[j]);
2281
if (fullname != NULL) {
2282
attr = xmlSAX2AttributeNs(ctxt, fullname, NULL,
2283
attributes[j+3],
2284
attributes[j+4]);
2285
goto have_attr;
2286
}
2287
} else {
2288
lname = xmlBuildQName(attributes[j], attributes[j+1],
2289
NULL, 0);
2290
if (lname != NULL) {
2291
attr = xmlSAX2AttributeNs(ctxt, lname, NULL,
2292
attributes[j+3],
2293
attributes[j+4]);
2294
xmlFree(lname);
2295
goto have_attr;
2296
}
2297
}
2298
}
2299
attr = xmlSAX2AttributeNs(ctxt, attributes[j], attributes[j+1],
2300
attributes[j+3], attributes[j+4]);
2301
have_attr:
2302
if (attr == NULL)
2303
continue;
2304
2305
/* link at the end to preserve order */
2306
if (prev == NULL) {
2307
ctxt->node->properties = attr;
2308
} else {
2309
prev->next = attr;
2310
attr->prev = prev;
2311
}
2312
2313
prev = attr;
2314
}
2315
}
2316
2317
#ifdef LIBXML_VALID_ENABLED
2318
/*
2319
* If it's the Document root, finish the DTD validation and
2320
* check the document root element for validity
2321
*/
2322
if ((ctxt->validate) &&
2323
((ctxt->vctxt.flags & XML_VCTXT_DTD_VALIDATED) == 0)) {
2324
int chk;
2325
2326
chk = xmlValidateDtdFinal(&ctxt->vctxt, ctxt->myDoc);
2327
if (chk <= 0)
2328
ctxt->valid = 0;
2329
if (chk < 0)
2330
ctxt->wellFormed = 0;
2331
ctxt->valid &= xmlValidateRoot(&ctxt->vctxt, ctxt->myDoc);
2332
ctxt->vctxt.flags |= XML_VCTXT_DTD_VALIDATED;
2333
}
2334
#endif /* LIBXML_VALID_ENABLED */
2335
}
2336
2337
/**
2338
* xmlSAX2EndElementNs:
2339
* @ctx: the user data (XML parser context)
2340
* @localname: the local name of the element
2341
* @prefix: the element namespace prefix if available
2342
* @URI: the element namespace name if available
2343
*
2344
* SAX2 callback when an element end has been detected by the parser.
2345
* It provides the namespace information for the element.
2346
*/
2347
void
2348
xmlSAX2EndElementNs(void *ctx,
2349
const xmlChar * localname ATTRIBUTE_UNUSED,
2350
const xmlChar * prefix ATTRIBUTE_UNUSED,
2351
const xmlChar * URI ATTRIBUTE_UNUSED)
2352
{
2353
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2354
2355
if (ctx == NULL) return;
2356
ctxt->nodemem = -1;
2357
2358
#ifdef LIBXML_VALID_ENABLED
2359
if (ctxt->validate && ctxt->wellFormed &&
2360
ctxt->myDoc && ctxt->myDoc->intSubset)
2361
ctxt->valid &= xmlValidateOneElement(&ctxt->vctxt, ctxt->myDoc,
2362
ctxt->node);
2363
#endif /* LIBXML_VALID_ENABLED */
2364
2365
/*
2366
* end of parsing of this node.
2367
*/
2368
nodePop(ctxt);
2369
}
2370
2371
/**
2372
* xmlSAX2Reference:
2373
* @ctx: the user data (XML parser context)
2374
* @name: The entity name
2375
*
2376
* called when an entity xmlSAX2Reference is detected.
2377
*/
2378
void
2379
xmlSAX2Reference(void *ctx, const xmlChar *name)
2380
{
2381
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2382
xmlNodePtr ret;
2383
2384
if (ctx == NULL) return;
2385
ret = xmlNewReference(ctxt->myDoc, name);
2386
if (xmlAddChild(ctxt->node, ret) == NULL) {
2387
xmlFreeNode(ret);
2388
}
2389
}
2390
2391
/**
2392
* xmlSAX2Text:
2393
* @ctx: the user data (XML parser context)
2394
* @ch: a xmlChar string
2395
* @len: the number of xmlChar
2396
* @type: text or cdata
2397
*
2398
* Append characters.
2399
*/
2400
static void
2401
xmlSAX2Text(xmlParserCtxtPtr ctxt, const xmlChar *ch, int len,
2402
xmlElementType type)
2403
{
2404
xmlNodePtr lastChild;
2405
2406
if (ctxt == NULL) return;
2407
/*
2408
* Handle the data if any. If there is no child
2409
* add it as content, otherwise if the last child is text,
2410
* concatenate it, else create a new node of type text.
2411
*/
2412
2413
if (ctxt->node == NULL) {
2414
return;
2415
}
2416
lastChild = ctxt->node->last;
2417
2418
/*
2419
* Here we needed an accelerator mechanism in case of very large
2420
* elements. Use an attribute in the structure !!!
2421
*/
2422
if (lastChild == NULL) {
2423
if (type == XML_TEXT_NODE)
2424
lastChild = xmlSAX2TextNode(ctxt, ch, len);
2425
else
2426
lastChild = xmlNewCDataBlock(ctxt->myDoc, ch, len);
2427
if (lastChild != NULL) {
2428
ctxt->node->children = lastChild;
2429
ctxt->node->last = lastChild;
2430
lastChild->parent = ctxt->node;
2431
lastChild->doc = ctxt->node->doc;
2432
ctxt->nodelen = len;
2433
ctxt->nodemem = len + 1;
2434
} else {
2435
xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2436
return;
2437
}
2438
} else {
2439
int coalesceText = (lastChild != NULL) &&
2440
(lastChild->type == type) &&
2441
((type != XML_TEXT_NODE) ||
2442
(lastChild->name == xmlStringText));
2443
if ((coalesceText) && (ctxt->nodemem != 0)) {
2444
/*
2445
* The whole point of maintaining nodelen and nodemem,
2446
* xmlTextConcat is too costly, i.e. compute length,
2447
* reallocate a new buffer, move data, append ch. Here
2448
* We try to minimize realloc() uses and avoid copying
2449
* and recomputing length over and over.
2450
*/
2451
if (lastChild->content == (xmlChar *)&(lastChild->properties)) {
2452
lastChild->content = xmlStrdup(lastChild->content);
2453
lastChild->properties = NULL;
2454
} else if ((ctxt->nodemem == ctxt->nodelen + 1) &&
2455
(xmlDictOwns(ctxt->dict, lastChild->content))) {
2456
lastChild->content = xmlStrdup(lastChild->content);
2457
}
2458
if (lastChild->content == NULL) {
2459
xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: xmlStrdup returned NULL");
2460
return;
2461
}
2462
if (ctxt->nodelen > INT_MAX - len) {
2463
xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters overflow prevented");
2464
return;
2465
}
2466
if ((ctxt->nodelen + len > XML_MAX_TEXT_LENGTH) &&
2467
((ctxt->options & XML_PARSE_HUGE) == 0)) {
2468
xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters: huge text node");
2469
return;
2470
}
2471
if (ctxt->nodelen + len >= ctxt->nodemem) {
2472
xmlChar *newbuf;
2473
int size;
2474
2475
size = ctxt->nodemem > INT_MAX - len ?
2476
INT_MAX :
2477
ctxt->nodemem + len;
2478
size = size > INT_MAX / 2 ? INT_MAX : size * 2;
2479
newbuf = (xmlChar *) xmlRealloc(lastChild->content,size);
2480
if (newbuf == NULL) {
2481
xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2482
return;
2483
}
2484
ctxt->nodemem = size;
2485
lastChild->content = newbuf;
2486
}
2487
memcpy(&lastChild->content[ctxt->nodelen], ch, len);
2488
ctxt->nodelen += len;
2489
lastChild->content[ctxt->nodelen] = 0;
2490
} else if (coalesceText) {
2491
if (xmlTextConcat(lastChild, ch, len)) {
2492
xmlSAX2ErrMemory(ctxt, "xmlSAX2Characters");
2493
}
2494
if (ctxt->node->children != NULL) {
2495
ctxt->nodelen = xmlStrlen(lastChild->content);
2496
ctxt->nodemem = ctxt->nodelen + 1;
2497
}
2498
} else {
2499
/* Mixed content, first time */
2500
if (type == XML_TEXT_NODE) {
2501
lastChild = xmlSAX2TextNode(ctxt, ch, len);
2502
if (lastChild != NULL)
2503
lastChild->doc = ctxt->myDoc;
2504
} else
2505
lastChild = xmlNewCDataBlock(ctxt->myDoc, ch, len);
2506
if (lastChild != NULL) {
2507
xmlAddChild(ctxt->node, lastChild);
2508
if (ctxt->node->children != NULL) {
2509
ctxt->nodelen = len;
2510
ctxt->nodemem = len + 1;
2511
}
2512
}
2513
}
2514
}
2515
2516
if ((lastChild != NULL) &&
2517
(type == XML_TEXT_NODE) &&
2518
(ctxt->linenumbers) &&
2519
(ctxt->input != NULL)) {
2520
if ((unsigned) ctxt->input->line < (unsigned) USHRT_MAX)
2521
lastChild->line = ctxt->input->line;
2522
else {
2523
lastChild->line = USHRT_MAX;
2524
if (ctxt->options & XML_PARSE_BIG_LINES)
2525
lastChild->psvi = (void *) (ptrdiff_t) ctxt->input->line;
2526
}
2527
}
2528
}
2529
2530
/**
2531
* xmlSAX2Characters:
2532
* @ctx: the user data (XML parser context)
2533
* @ch: a xmlChar string
2534
* @len: the number of xmlChar
2535
*
2536
* receiving some chars from the parser.
2537
*/
2538
void
2539
xmlSAX2Characters(void *ctx, const xmlChar *ch, int len)
2540
{
2541
xmlSAX2Text((xmlParserCtxtPtr) ctx, ch, len, XML_TEXT_NODE);
2542
}
2543
2544
/**
2545
* xmlSAX2IgnorableWhitespace:
2546
* @ctx: the user data (XML parser context)
2547
* @ch: a xmlChar string
2548
* @len: the number of xmlChar
2549
*
2550
* receiving some ignorable whitespaces from the parser.
2551
* UNUSED: by default the DOM building will use xmlSAX2Characters
2552
*/
2553
void
2554
xmlSAX2IgnorableWhitespace(void *ctx ATTRIBUTE_UNUSED, const xmlChar *ch ATTRIBUTE_UNUSED, int len ATTRIBUTE_UNUSED)
2555
{
2556
}
2557
2558
/**
2559
* xmlSAX2ProcessingInstruction:
2560
* @ctx: the user data (XML parser context)
2561
* @target: the target name
2562
* @data: the PI data's
2563
*
2564
* A processing instruction has been parsed.
2565
*/
2566
void
2567
xmlSAX2ProcessingInstruction(void *ctx, const xmlChar *target,
2568
const xmlChar *data)
2569
{
2570
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2571
xmlNodePtr ret;
2572
xmlNodePtr parent;
2573
2574
if (ctx == NULL) return;
2575
parent = ctxt->node;
2576
2577
ret = xmlNewDocPI(ctxt->myDoc, target, data);
2578
if (ret == NULL) return;
2579
2580
if (ctxt->linenumbers) {
2581
if (ctxt->input != NULL) {
2582
if ((unsigned) ctxt->input->line < (unsigned) USHRT_MAX)
2583
ret->line = ctxt->input->line;
2584
else
2585
ret->line = USHRT_MAX;
2586
}
2587
}
2588
if (ctxt->inSubset == 1) {
2589
xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2590
return;
2591
} else if (ctxt->inSubset == 2) {
2592
xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2593
return;
2594
}
2595
if (parent == NULL) {
2596
xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2597
return;
2598
}
2599
if (parent->type == XML_ELEMENT_NODE) {
2600
xmlAddChild(parent, ret);
2601
} else {
2602
xmlAddSibling(parent, ret);
2603
}
2604
}
2605
2606
/**
2607
* xmlSAX2Comment:
2608
* @ctx: the user data (XML parser context)
2609
* @value: the xmlSAX2Comment content
2610
*
2611
* A xmlSAX2Comment has been parsed.
2612
*/
2613
void
2614
xmlSAX2Comment(void *ctx, const xmlChar *value)
2615
{
2616
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2617
xmlNodePtr ret;
2618
xmlNodePtr parent;
2619
2620
if (ctx == NULL) return;
2621
parent = ctxt->node;
2622
ret = xmlNewDocComment(ctxt->myDoc, value);
2623
if (ret == NULL) return;
2624
if (ctxt->linenumbers) {
2625
if (ctxt->input != NULL) {
2626
if ((unsigned) ctxt->input->line < (unsigned) USHRT_MAX)
2627
ret->line = ctxt->input->line;
2628
else
2629
ret->line = USHRT_MAX;
2630
}
2631
}
2632
2633
if (ctxt->inSubset == 1) {
2634
xmlAddChild((xmlNodePtr) ctxt->myDoc->intSubset, ret);
2635
return;
2636
} else if (ctxt->inSubset == 2) {
2637
xmlAddChild((xmlNodePtr) ctxt->myDoc->extSubset, ret);
2638
return;
2639
}
2640
if (parent == NULL) {
2641
xmlAddChild((xmlNodePtr) ctxt->myDoc, (xmlNodePtr) ret);
2642
return;
2643
}
2644
if (parent->type == XML_ELEMENT_NODE) {
2645
xmlAddChild(parent, ret);
2646
} else {
2647
xmlAddSibling(parent, ret);
2648
}
2649
}
2650
2651
/**
2652
* xmlSAX2CDataBlock:
2653
* @ctx: the user data (XML parser context)
2654
* @value: The pcdata content
2655
* @len: the block length
2656
*
2657
* called when a pcdata block has been parsed
2658
*/
2659
void
2660
xmlSAX2CDataBlock(void *ctx, const xmlChar *value, int len)
2661
{
2662
xmlSAX2Text((xmlParserCtxtPtr) ctx, value, len, XML_CDATA_SECTION_NODE);
2663
}
2664
2665
static int xmlSAX2DefaultVersionValue = 2;
2666
2667
#ifdef LIBXML_SAX1_ENABLED
2668
/**
2669
* xmlSAXDefaultVersion:
2670
* @version: the version, 1 or 2
2671
*
2672
* DEPRECATED: Use parser option XML_PARSE_SAX1.
2673
*
2674
* Set the default version of SAX used globally by the library.
2675
* By default, during initialization the default is set to 2.
2676
* Note that it is generally a better coding style to use
2677
* xmlSAXVersion() to set up the version explicitly for a given
2678
* parsing context.
2679
*
2680
* Returns the previous value in case of success and -1 in case of error.
2681
*/
2682
int
2683
xmlSAXDefaultVersion(int version)
2684
{
2685
int ret = xmlSAX2DefaultVersionValue;
2686
2687
if ((version != 1) && (version != 2))
2688
return(-1);
2689
xmlSAX2DefaultVersionValue = version;
2690
return(ret);
2691
}
2692
#endif /* LIBXML_SAX1_ENABLED */
2693
2694
/**
2695
* xmlSAXVersion:
2696
* @hdlr: the SAX handler
2697
* @version: the version, 1 or 2
2698
*
2699
* Initialize the default XML SAX handler according to the version
2700
*
2701
* Returns 0 in case of success and -1 in case of error.
2702
*/
2703
int
2704
xmlSAXVersion(xmlSAXHandler *hdlr, int version)
2705
{
2706
if (hdlr == NULL) return(-1);
2707
if (version == 2) {
2708
hdlr->startElementNs = xmlSAX2StartElementNs;
2709
hdlr->endElementNs = xmlSAX2EndElementNs;
2710
hdlr->serror = NULL;
2711
hdlr->initialized = XML_SAX2_MAGIC;
2712
#ifdef LIBXML_SAX1_ENABLED
2713
} else if (version == 1) {
2714
hdlr->initialized = 1;
2715
#endif /* LIBXML_SAX1_ENABLED */
2716
} else
2717
return(-1);
2718
#ifdef LIBXML_SAX1_ENABLED
2719
hdlr->startElement = xmlSAX2StartElement;
2720
hdlr->endElement = xmlSAX2EndElement;
2721
#else
2722
hdlr->startElement = NULL;
2723
hdlr->endElement = NULL;
2724
#endif /* LIBXML_SAX1_ENABLED */
2725
hdlr->internalSubset = xmlSAX2InternalSubset;
2726
hdlr->externalSubset = xmlSAX2ExternalSubset;
2727
hdlr->isStandalone = xmlSAX2IsStandalone;
2728
hdlr->hasInternalSubset = xmlSAX2HasInternalSubset;
2729
hdlr->hasExternalSubset = xmlSAX2HasExternalSubset;
2730
hdlr->resolveEntity = xmlSAX2ResolveEntity;
2731
hdlr->getEntity = xmlSAX2GetEntity;
2732
hdlr->getParameterEntity = xmlSAX2GetParameterEntity;
2733
hdlr->entityDecl = xmlSAX2EntityDecl;
2734
hdlr->attributeDecl = xmlSAX2AttributeDecl;
2735
hdlr->elementDecl = xmlSAX2ElementDecl;
2736
hdlr->notationDecl = xmlSAX2NotationDecl;
2737
hdlr->unparsedEntityDecl = xmlSAX2UnparsedEntityDecl;
2738
hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2739
hdlr->startDocument = xmlSAX2StartDocument;
2740
hdlr->endDocument = xmlSAX2EndDocument;
2741
hdlr->reference = xmlSAX2Reference;
2742
hdlr->characters = xmlSAX2Characters;
2743
hdlr->cdataBlock = xmlSAX2CDataBlock;
2744
hdlr->ignorableWhitespace = xmlSAX2Characters;
2745
hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2746
hdlr->comment = xmlSAX2Comment;
2747
hdlr->warning = xmlParserWarning;
2748
hdlr->error = xmlParserError;
2749
hdlr->fatalError = xmlParserError;
2750
2751
return(0);
2752
}
2753
2754
/**
2755
* xmlSAX2InitDefaultSAXHandler:
2756
* @hdlr: the SAX handler
2757
* @warning: flag if non-zero sets the handler warning procedure
2758
*
2759
* Initialize the default XML SAX2 handler
2760
*/
2761
void
2762
xmlSAX2InitDefaultSAXHandler(xmlSAXHandler *hdlr, int warning)
2763
{
2764
if ((hdlr == NULL) || (hdlr->initialized != 0))
2765
return;
2766
2767
xmlSAXVersion(hdlr, xmlSAX2DefaultVersionValue);
2768
if (warning == 0)
2769
hdlr->warning = NULL;
2770
else
2771
hdlr->warning = xmlParserWarning;
2772
}
2773
2774
/**
2775
* xmlDefaultSAXHandlerInit:
2776
*
2777
* DEPRECATED: This function is a no-op. Call xmlInitParser to
2778
* initialize the library.
2779
*
2780
* Initialize the default SAX2 handler
2781
*/
2782
void
2783
xmlDefaultSAXHandlerInit(void)
2784
{
2785
}
2786
2787
#ifdef LIBXML_HTML_ENABLED
2788
2789
/**
2790
* xmlSAX2InitHtmlDefaultSAXHandler:
2791
* @hdlr: the SAX handler
2792
*
2793
* Initialize the default HTML SAX2 handler
2794
*/
2795
void
2796
xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr)
2797
{
2798
if ((hdlr == NULL) || (hdlr->initialized != 0))
2799
return;
2800
2801
hdlr->internalSubset = xmlSAX2InternalSubset;
2802
hdlr->externalSubset = NULL;
2803
hdlr->isStandalone = NULL;
2804
hdlr->hasInternalSubset = NULL;
2805
hdlr->hasExternalSubset = NULL;
2806
hdlr->resolveEntity = NULL;
2807
hdlr->getEntity = xmlSAX2GetEntity;
2808
hdlr->getParameterEntity = NULL;
2809
hdlr->entityDecl = NULL;
2810
hdlr->attributeDecl = NULL;
2811
hdlr->elementDecl = NULL;
2812
hdlr->notationDecl = NULL;
2813
hdlr->unparsedEntityDecl = NULL;
2814
hdlr->setDocumentLocator = xmlSAX2SetDocumentLocator;
2815
hdlr->startDocument = xmlSAX2StartDocument;
2816
hdlr->endDocument = xmlSAX2EndDocument;
2817
hdlr->startElement = xmlSAX2StartElement;
2818
hdlr->endElement = xmlSAX2EndElement;
2819
hdlr->reference = NULL;
2820
hdlr->characters = xmlSAX2Characters;
2821
hdlr->cdataBlock = xmlSAX2CDataBlock;
2822
hdlr->ignorableWhitespace = xmlSAX2IgnorableWhitespace;
2823
hdlr->processingInstruction = xmlSAX2ProcessingInstruction;
2824
hdlr->comment = xmlSAX2Comment;
2825
hdlr->warning = xmlParserWarning;
2826
hdlr->error = xmlParserError;
2827
hdlr->fatalError = xmlParserError;
2828
2829
hdlr->initialized = 1;
2830
}
2831
2832
/**
2833
* htmlDefaultSAXHandlerInit:
2834
*
2835
* DEPRECATED: This function is a no-op. Call xmlInitParser to
2836
* initialize the library.
2837
*/
2838
void
2839
htmlDefaultSAXHandlerInit(void)
2840
{
2841
}
2842
2843
#endif /* LIBXML_HTML_ENABLED */
2844
2845