Annotation of XML/entities.c, revision 1.59
1.1 httpng 1: /*
2: * entities.c : implementation for the XML entities handking
1.9 veillard 3: *
4: * See Copyright for the status of this software.
5: *
1.23 daniel 6: * Daniel.Veillard@w3.org
1.1 httpng 7: */
8:
1.42 daniel 9: #ifdef WIN32
10: #include "win32config.h"
11: #else
1.37 daniel 12: #include "config.h"
13: #endif
14:
1.1 httpng 15: #include <stdio.h>
1.37 daniel 16: #include <string.h>
17: #ifdef HAVE_STDLIB_H
1.17 daniel 18: #include <stdlib.h>
1.37 daniel 19: #endif
1.56 daniel 20: #include <libxml/xmlmemory.h>
21: #include <libxml/entities.h>
22: #include <libxml/parser.h>
1.1 httpng 23:
1.54 daniel 24: #define DEBUG_ENT_REF /* debugging of cross entities dependancies */
25:
1.1 httpng 26: /*
1.15 daniel 27: * The XML predefined entities.
28: */
29:
30: struct xmlPredefinedEntityValue {
31: const char *name;
32: const char *value;
33: };
34: struct xmlPredefinedEntityValue xmlPredefinedEntityValues[] = {
35: { "lt", "<" },
36: { "gt", ">" },
37: { "apos", "'" },
38: { "quot", "\"" },
39: { "amp", "&" }
40: };
41:
42: xmlEntitiesTablePtr xmlPredefinedEntities = NULL;
43:
44: /*
1.2 httpng 45: * xmlFreeEntity : clean-up an entity record.
1.1 httpng 46: */
1.2 httpng 47: void xmlFreeEntity(xmlEntityPtr entity) {
48: if (entity == NULL) return;
49:
1.52 daniel 50: if (entity->children)
51: xmlFreeNodeList(entity->children);
1.11 daniel 52: if (entity->name != NULL)
1.36 daniel 53: xmlFree((char *) entity->name);
1.14 daniel 54: if (entity->ExternalID != NULL)
1.36 daniel 55: xmlFree((char *) entity->ExternalID);
1.14 daniel 56: if (entity->SystemID != NULL)
1.36 daniel 57: xmlFree((char *) entity->SystemID);
1.14 daniel 58: if (entity->content != NULL)
1.36 daniel 59: xmlFree((char *) entity->content);
1.27 daniel 60: if (entity->orig != NULL)
1.36 daniel 61: xmlFree((char *) entity->orig);
1.55 daniel 62: #ifdef WITH_EXTRA_ENT_DETECT
1.54 daniel 63: if (entity->entTab != NULL) {
64: int i;
65:
66: for (i = 0; i < entity->entNr; i++)
67: xmlFree(entity->entTab[i]);
68: xmlFree(entity->entTab);
69: }
1.55 daniel 70: #endif
1.14 daniel 71: memset(entity, -1, sizeof(xmlEntity));
1.51 daniel 72: xmlFree(entity);
1.2 httpng 73: }
1.1 httpng 74:
75: /*
1.22 daniel 76: * xmlAddEntity : register a new entity for an entities table.
1.1 httpng 77: */
1.51 daniel 78: static xmlEntityPtr
1.38 daniel 79: xmlAddEntity(xmlEntitiesTablePtr table, const xmlChar *name, int type,
80: const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content) {
1.2 httpng 81: int i;
1.51 daniel 82: xmlEntityPtr ret;
1.1 httpng 83:
1.2 httpng 84: for (i = 0;i < table->nb_entities;i++) {
1.51 daniel 85: ret = table->table[i];
86: if (!xmlStrcmp(ret->name, name)) {
1.13 daniel 87: /*
88: * The entity is already defined in this Dtd, the spec says to NOT
89: * override it ... Is it worth a Warning ??? !!!
1.33 daniel 90: * Not having a cprinting context this seems hard ...
1.13 daniel 91: */
1.30 daniel 92: if (((type == XML_INTERNAL_PARAMETER_ENTITY) ||
93: (type == XML_EXTERNAL_PARAMETER_ENTITY)) &&
1.51 daniel 94: ((ret->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
95: (ret->etype == XML_EXTERNAL_PARAMETER_ENTITY)))
96: return(NULL);
1.30 daniel 97: else
98: if (((type != XML_INTERNAL_PARAMETER_ENTITY) &&
99: (type != XML_EXTERNAL_PARAMETER_ENTITY)) &&
1.51 daniel 100: ((ret->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
101: (ret->etype != XML_EXTERNAL_PARAMETER_ENTITY)))
102: return(NULL);
1.7 veillard 103: }
1.2 httpng 104: }
105: if (table->nb_entities >= table->max_entities) {
106: /*
107: * need more elements.
108: */
109: table->max_entities *= 2;
1.51 daniel 110: table->table = (xmlEntityPtr *)
111: xmlRealloc(table->table,
112: table->max_entities * sizeof(xmlEntityPtr));
1.29 daniel 113: if (table->table == NULL) {
1.2 httpng 114: perror("realloc failed");
1.51 daniel 115: return(NULL);
1.2 httpng 116: }
117: }
1.51 daniel 118: ret = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
119: if (ret == NULL) {
120: fprintf(stderr, "xmlAddEntity: out of memory\n");
121: return(NULL);
122: }
123: memset(ret, 0, sizeof(xmlEntity));
124: ret->type = XML_ENTITY_DECL;
125: table->table[table->nb_entities] = ret;
126:
127: /*
128: * fill the structure.
129: */
130: ret->name = xmlStrdup(name);
1.58 veillard 131: ret->etype = (xmlEntityType) type;
1.13 daniel 132: if (ExternalID != NULL)
1.51 daniel 133: ret->ExternalID = xmlStrdup(ExternalID);
1.13 daniel 134: if (SystemID != NULL)
1.51 daniel 135: ret->SystemID = xmlStrdup(SystemID);
1.43 daniel 136: if (content != NULL) {
1.51 daniel 137: ret->length = xmlStrlen(content);
138: ret->content = xmlStrndup(content, ret->length);
1.43 daniel 139: } else {
1.51 daniel 140: ret->length = 0;
141: ret->content = NULL;
1.43 daniel 142: }
1.51 daniel 143: ret->orig = NULL;
1.2 httpng 144: table->nb_entities++;
1.51 daniel 145:
146: return(ret);
1.2 httpng 147: }
1.1 httpng 148:
1.22 daniel 149: /**
150: * xmlInitializePredefinedEntities:
151: *
152: * Set up the predefined entities.
1.15 daniel 153: */
154: void xmlInitializePredefinedEntities(void) {
155: int i;
1.38 daniel 156: xmlChar name[50];
157: xmlChar value[50];
1.15 daniel 158: const char *in;
1.38 daniel 159: xmlChar *out;
1.15 daniel 160:
161: if (xmlPredefinedEntities != NULL) return;
162:
163: xmlPredefinedEntities = xmlCreateEntitiesTable();
164: for (i = 0;i < sizeof(xmlPredefinedEntityValues) /
165: sizeof(xmlPredefinedEntityValues[0]);i++) {
166: in = xmlPredefinedEntityValues[i].name;
167: out = &name[0];
1.38 daniel 168: for (;(*out++ = (xmlChar) *in);)in++;
1.15 daniel 169: in = xmlPredefinedEntityValues[i].value;
170: out = &value[0];
1.38 daniel 171: for (;(*out++ = (xmlChar) *in);)in++;
172: xmlAddEntity(xmlPredefinedEntities, (const xmlChar *) &name[0],
1.18 daniel 173: XML_INTERNAL_PREDEFINED_ENTITY, NULL, NULL,
1.15 daniel 174: &value[0]);
175: }
176: }
1.17 daniel 177:
178: /**
1.40 daniel 179: * xmlCleanupPredefinedEntities:
180: *
181: * Cleanup up the predefined entities table.
182: */
183: void xmlCleanupPredefinedEntities(void) {
184: if (xmlPredefinedEntities == NULL) return;
185:
186: xmlFreeEntitiesTable(xmlPredefinedEntities);
187: xmlPredefinedEntities = NULL;
188: }
189:
190: /**
1.17 daniel 191: * xmlGetPredefinedEntity:
192: * @name: the entity name
193: *
194: * Check whether this name is an predefined entity.
195: *
1.24 daniel 196: * Returns NULL if not, othervise the entity
1.17 daniel 197: */
198: xmlEntityPtr
1.38 daniel 199: xmlGetPredefinedEntity(const xmlChar *name) {
1.17 daniel 200: int i;
201: xmlEntityPtr cur;
202:
203: if (xmlPredefinedEntities == NULL)
204: xmlInitializePredefinedEntities();
205: for (i = 0;i < xmlPredefinedEntities->nb_entities;i++) {
1.51 daniel 206: cur = xmlPredefinedEntities->table[i];
1.17 daniel 207: if (!xmlStrcmp(cur->name, name)) return(cur);
208: }
209: return(NULL);
210: }
211:
1.22 daniel 212: /**
213: * xmlAddDtdEntity:
214: * @doc: the document
215: * @name: the entity name
216: * @type: the entity type XML_xxx_yyy_ENTITY
217: * @ExternalID: the entity external ID if available
218: * @SystemID: the entity system ID if available
219: * @content: the entity content
220: *
1.51 daniel 221: * Register a new entity for this document DTD external subset.
222: *
223: * Returns a pointer to the entity or NULL in case of error
1.1 httpng 224: */
1.51 daniel 225: xmlEntityPtr
1.38 daniel 226: xmlAddDtdEntity(xmlDocPtr doc, const xmlChar *name, int type,
1.51 daniel 227: const xmlChar *ExternalID, const xmlChar *SystemID,
228: const xmlChar *content) {
1.2 httpng 229: xmlEntitiesTablePtr table;
1.51 daniel 230: xmlEntityPtr ret;
231: xmlDtdPtr dtd;
1.1 httpng 232:
1.51 daniel 233: if (doc == NULL) {
234: fprintf(stderr,
235: "xmlAddDtdEntity: doc == NULL !\n");
236: return(NULL);
237: }
1.22 daniel 238: if (doc->extSubset == NULL) {
239: fprintf(stderr,
240: "xmlAddDtdEntity: document without external subset !\n");
1.51 daniel 241: return(NULL);
1.16 daniel 242: }
1.51 daniel 243: dtd = doc->extSubset;
244: table = (xmlEntitiesTablePtr) dtd->entities;
1.2 httpng 245: if (table == NULL) {
246: table = xmlCreateEntitiesTable();
1.51 daniel 247: dtd->entities = table;
1.1 httpng 248: }
1.51 daniel 249: ret = xmlAddEntity(table, name, type, ExternalID, SystemID, content);
250: if (ret == NULL) return(NULL);
251:
252: /*
253: * Link it to the Dtd
254: */
255: ret->parent = dtd;
256: ret->doc = dtd->doc;
257: if (dtd->last == NULL) {
258: dtd->children = dtd->last = (xmlNodePtr) ret;
259: } else {
260: dtd->last->next = (xmlNodePtr) ret;
261: ret->prev = dtd->last;
262: dtd->last = (xmlNodePtr) ret;
263: }
264: return(ret);
1.1 httpng 265: }
266:
1.22 daniel 267: /**
268: * xmlAddDocEntity:
269: * @doc: the document
270: * @name: the entity name
271: * @type: the entity type XML_xxx_yyy_ENTITY
272: * @ExternalID: the entity external ID if available
273: * @SystemID: the entity system ID if available
274: * @content: the entity content
275: *
276: * Register a new entity for this document.
1.51 daniel 277: *
278: * Returns a pointer to the entity or NULL in case of error
1.1 httpng 279: */
1.51 daniel 280: xmlEntityPtr
1.38 daniel 281: xmlAddDocEntity(xmlDocPtr doc, const xmlChar *name, int type,
1.51 daniel 282: const xmlChar *ExternalID, const xmlChar *SystemID,
283: const xmlChar *content) {
1.16 daniel 284: xmlEntitiesTablePtr table;
1.51 daniel 285: xmlEntityPtr ret;
286: xmlDtdPtr dtd;
1.16 daniel 287:
1.22 daniel 288: if (doc == NULL) {
289: fprintf(stderr,
290: "xmlAddDocEntity: document is NULL !\n");
1.51 daniel 291: return(NULL);
1.22 daniel 292: }
293: if (doc->intSubset == NULL) {
294: fprintf(stderr,
295: "xmlAddDtdEntity: document without internal subset !\n");
1.51 daniel 296: return(NULL);
1.22 daniel 297: }
1.51 daniel 298: dtd = doc->intSubset;
1.22 daniel 299: table = (xmlEntitiesTablePtr) doc->intSubset->entities;
1.16 daniel 300: if (table == NULL) {
301: table = xmlCreateEntitiesTable();
1.22 daniel 302: doc->intSubset->entities = table;
1.2 httpng 303: }
1.51 daniel 304: ret = xmlAddEntity(table, name, type, ExternalID, SystemID, content);
305: if (ret == NULL) return(NULL);
306:
307: /*
308: * Link it to the Dtd
309: */
310: ret->parent = dtd;
311: ret->doc = dtd->doc;
312: if (dtd->last == NULL) {
313: dtd->children = dtd->last = (xmlNodePtr) ret;
314: } else {
315: dtd->last->next = (xmlNodePtr) ret;
316: ret->prev = dtd->last;
317: dtd->last = (xmlNodePtr) ret;
318: }
319: return(ret);
1.54 daniel 320: }
321:
1.55 daniel 322: #ifdef WITH_EXTRA_ENT_DETECT
1.54 daniel 323: /**
324: * xmlEntityCheckReference:
325: * @ent: an existing entity
326: * @to: the entity name it's referencing
327: *
328: * Function to keep track of references and detect cycles (well formedness
329: * errors !).
330: *
331: * Returns: 0 if Okay, -1 in case of general error, 1 in case of loop
332: * detection.
333: */
334: int
335: xmlEntityCheckReference(xmlEntityPtr ent, const xmlChar *to) {
336: int i;
337: xmlDocPtr doc;
338:
339: if (ent == NULL) return(-1);
340: if (to == NULL) return(-1);
341:
342: doc = ent->doc;
343: if (doc == NULL) return(-1);
344:
345: #ifdef DEBUG_ENT_REF
346: printf("xmlEntityCheckReference(%s to %s)\n", ent->name, to);
347: #endif
348:
349:
350: /*
351: * Do a recursive checking
352: */
353: for (i = 0;i < ent->entNr;i++) {
354: xmlEntityPtr indir = NULL;
355:
356: if (!xmlStrcmp(to, ent->entTab[i]))
357: return(1);
358:
359: switch (ent->etype) {
360: case XML_INTERNAL_GENERAL_ENTITY:
361: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
362: indir = xmlGetDocEntity(doc, ent->entTab[i]);
363: break;
364: case XML_INTERNAL_PARAMETER_ENTITY:
365: case XML_EXTERNAL_PARAMETER_ENTITY:
366: indir = xmlGetDtdEntity(doc, ent->entTab[i]);
367: break;
368: case XML_INTERNAL_PREDEFINED_ENTITY:
369: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
370: break;
371: }
372: if (xmlEntityCheckReference(indir, to) == 1)
373: return(1);
374: }
375: return(0);
376: }
377:
378: /**
379: * xmlEntityAddReference:
380: * @ent: an existing entity
381: * @to: the entity name it's referencing
382: *
383: * Function to register reuse of an existing entity from a (new) one
384: * Used to keep track of references and detect cycles (well formedness
385: * errors !).
386: *
387: * Returns: 0 if Okay, -1 in case of general error, 1 in case of loop
388: * detection.
389: */
390: int
391: xmlEntityAddReference(xmlEntityPtr ent, const xmlChar *to) {
392: int i;
393: xmlDocPtr doc;
394: xmlEntityPtr indir = NULL;
395:
396: if (ent == NULL) return(-1);
397: if (to == NULL) return(-1);
398:
399: doc = ent->doc;
400: if (doc == NULL) return(-1);
401:
402: #ifdef DEBUG_ENT_REF
403: printf("xmlEntityAddReference(%s to %s)\n", ent->name, to);
404: #endif
405: if (ent->entTab == NULL) {
406: ent->entNr = 0;
407: ent->entMax = 5;
408: ent->entTab = (xmlChar **) xmlMalloc(ent->entMax * sizeof(xmlChar *));
409: if (ent->entTab == NULL) {
410: fprintf(stderr, "xmlEntityAddReference: out of memory !\n");
411: return(-1);
412: }
413: }
414:
415: for (i = 0;i < ent->entNr;i++) {
416: if (!xmlStrcmp(to, ent->entTab[i]))
417: return(0);
418: }
419:
420: /*
421: * Do a recursive checking
422: */
423:
424: switch (ent->etype) {
425: case XML_INTERNAL_GENERAL_ENTITY:
426: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
427: indir = xmlGetDocEntity(doc, to);
428: break;
429: case XML_INTERNAL_PARAMETER_ENTITY:
430: case XML_EXTERNAL_PARAMETER_ENTITY:
431: indir = xmlGetDtdEntity(doc, to);
432: break;
433: case XML_INTERNAL_PREDEFINED_ENTITY:
434: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
435: break;
436: }
437: if ((indir != NULL) &&
438: (xmlEntityCheckReference(indir, ent->name) == 1))
439: return(1);
440:
441: /*
442: * Add this to the list
443: */
444: if (ent->entMax <= ent->entNr) {
445: ent->entMax *= 2;
446: ent->entTab = (xmlChar **) xmlRealloc(ent->entTab,
447: ent->entMax * sizeof(xmlChar *));
448: if (ent->entTab == NULL) {
449: fprintf(stderr, "xmlEntityAddReference: out of memory !\n");
450: return(-1);
451: }
452: }
453: ent->entTab[ent->entNr++] = xmlStrdup(to);
454: return(0);
1.1 httpng 455: }
1.55 daniel 456: #endif
1.1 httpng 457:
1.22 daniel 458: /**
1.30 daniel 459: * xmlGetParameterEntity:
460: * @doc: the document referencing the entity
461: * @name: the entity name
462: *
463: * Do an entity lookup in the internal and external subsets and
464: * returns the corresponding parameter entity, if found.
465: *
466: * Returns A pointer to the entity structure or NULL if not found.
467: */
468: xmlEntityPtr
1.38 daniel 469: xmlGetParameterEntity(xmlDocPtr doc, const xmlChar *name) {
1.30 daniel 470: int i;
471: xmlEntityPtr cur;
472: xmlEntitiesTablePtr table;
473:
474: if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
475: table = (xmlEntitiesTablePtr) doc->intSubset->entities;
476: for (i = 0;i < table->nb_entities;i++) {
1.51 daniel 477: cur = table->table[i];
1.49 daniel 478: if (((cur->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
479: (cur->etype == XML_EXTERNAL_PARAMETER_ENTITY)) &&
1.30 daniel 480: (!xmlStrcmp(cur->name, name))) return(cur);
481: }
482: }
483: if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
484: table = (xmlEntitiesTablePtr) doc->extSubset->entities;
485: for (i = 0;i < table->nb_entities;i++) {
1.51 daniel 486: cur = table->table[i];
1.49 daniel 487: if (((cur->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
488: (cur->etype == XML_EXTERNAL_PARAMETER_ENTITY)) &&
1.30 daniel 489: (!xmlStrcmp(cur->name, name))) return(cur);
490: }
491: }
1.35 daniel 492: if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
493: table = (xmlEntitiesTablePtr) doc->extSubset->entities;
494: for (i = 0;i < table->nb_entities;i++) {
1.51 daniel 495: cur = table->table[i];
1.49 daniel 496: if (((cur->etype == XML_INTERNAL_PARAMETER_ENTITY) ||
497: (cur->etype == XML_EXTERNAL_PARAMETER_ENTITY)) &&
1.35 daniel 498: (!xmlStrcmp(cur->name, name))) return(cur);
499: }
500: }
1.30 daniel 501: return(NULL);
502: }
503:
504: /**
1.22 daniel 505: * xmlGetDtdEntity:
506: * @doc: the document referencing the entity
507: * @name: the entity name
508: *
509: * Do an entity lookup in the Dtd entity hash table and
510: * returns the corresponding entity, if found.
511: *
1.24 daniel 512: * Returns A pointer to the entity structure or NULL if not found.
1.1 httpng 513: */
1.22 daniel 514: xmlEntityPtr
1.38 daniel 515: xmlGetDtdEntity(xmlDocPtr doc, const xmlChar *name) {
1.2 httpng 516: int i;
517: xmlEntityPtr cur;
518: xmlEntitiesTablePtr table;
519:
1.22 daniel 520: if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
521: table = (xmlEntitiesTablePtr) doc->extSubset->entities;
1.15 daniel 522: for (i = 0;i < table->nb_entities;i++) {
1.51 daniel 523: cur = table->table[i];
1.49 daniel 524: if ((cur->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
525: (cur->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
1.30 daniel 526: (!xmlStrcmp(cur->name, name))) return(cur);
1.15 daniel 527: }
528: }
1.7 veillard 529: return(NULL);
1.3 httpng 530: }
531:
1.22 daniel 532: /**
533: * xmlGetDocEntity:
534: * @doc: the document referencing the entity
535: * @name: the entity name
536: *
537: * Do an entity lookup in the document entity hash table and
538: * returns the corrsponding entity, otherwise a lookup is done
539: * in the predefined entities too.
540: *
1.24 daniel 541: * Returns A pointer to the entity structure or NULL if not found.
1.14 daniel 542: */
1.22 daniel 543: xmlEntityPtr
1.38 daniel 544: xmlGetDocEntity(xmlDocPtr doc, const xmlChar *name) {
1.14 daniel 545: int i;
1.16 daniel 546: xmlEntityPtr cur;
1.14 daniel 547: xmlEntitiesTablePtr table;
548:
1.22 daniel 549: if ((doc->intSubset != NULL) && (doc->intSubset->entities != NULL)) {
550: table = (xmlEntitiesTablePtr) doc->intSubset->entities;
1.16 daniel 551: for (i = 0;i < table->nb_entities;i++) {
1.51 daniel 552: cur = table->table[i];
1.49 daniel 553: if ((cur->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
554: (cur->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
1.30 daniel 555: (!xmlStrcmp(cur->name, name))) return(cur);
1.16 daniel 556: }
557: }
1.34 daniel 558: if ((doc->extSubset != NULL) && (doc->extSubset->entities != NULL)) {
559: table = (xmlEntitiesTablePtr) doc->extSubset->entities;
560: for (i = 0;i < table->nb_entities;i++) {
1.51 daniel 561: cur = table->table[i];
1.49 daniel 562: if ((cur->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
563: (cur->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
1.34 daniel 564: (!xmlStrcmp(cur->name, name))) return(cur);
565: }
566: }
1.15 daniel 567: if (xmlPredefinedEntities == NULL)
568: xmlInitializePredefinedEntities();
1.16 daniel 569: table = xmlPredefinedEntities;
570: for (i = 0;i < table->nb_entities;i++) {
1.51 daniel 571: cur = table->table[i];
1.49 daniel 572: if ((cur->etype != XML_INTERNAL_PARAMETER_ENTITY) &&
573: (cur->etype != XML_EXTERNAL_PARAMETER_ENTITY) &&
1.30 daniel 574: (!xmlStrcmp(cur->name, name))) return(cur);
1.14 daniel 575: }
576:
577: return(NULL);
1.1 httpng 578: }
579:
580: /*
1.21 daniel 581: * [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD]
582: * | [#x10000-#x10FFFF]
583: * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
584: */
585: #define IS_CHAR(c) \
586: (((c) == 0x09) || ((c) == 0x0a) || ((c) == 0x0d) || \
587: (((c) >= 0x20) && ((c) != 0xFFFE) && ((c) != 0xFFFF)))
588:
1.28 daniel 589: /*
590: * A buffer used for converting entities to their equivalent and back.
591: */
592: static int buffer_size = 0;
1.38 daniel 593: static xmlChar *buffer = NULL;
1.28 daniel 594:
1.44 daniel 595: int growBuffer(void) {
1.28 daniel 596: buffer_size *= 2;
1.38 daniel 597: buffer = (xmlChar *) xmlRealloc(buffer, buffer_size * sizeof(xmlChar));
1.28 daniel 598: if (buffer == NULL) {
599: perror("realloc failed");
1.44 daniel 600: return(-1);
1.28 daniel 601: }
1.44 daniel 602: return(0);
1.28 daniel 603: }
604:
605:
1.22 daniel 606: /**
607: * xmlEncodeEntities:
608: * @doc: the document containing the string
609: * @input: A string to convert to XML.
610: *
611: * Do a global encoding of a string, replacing the predefined entities
612: * and non ASCII values with their entities and CharRef counterparts.
613: *
1.33 daniel 614: * TODO: remove xmlEncodeEntities, once we are not afraid of breaking binary
615: * compatibility
1.28 daniel 616: *
617: * People must migrate their code to xmlEncodeEntitiesReentrant !
1.31 daniel 618: * This routine will issue a warning when encountered.
1.28 daniel 619: *
620: * Returns A newly allocated string with the substitution done.
621: */
1.38 daniel 622: const xmlChar *
623: xmlEncodeEntities(xmlDocPtr doc, const xmlChar *input) {
624: const xmlChar *cur = input;
625: xmlChar *out = buffer;
1.31 daniel 626: static int warning = 1;
1.39 daniel 627: int html = 0;
628:
1.31 daniel 629:
630: if (warning) {
631: fprintf(stderr, "Deprecated API xmlEncodeEntities() used\n");
632: fprintf(stderr, " change code to use xmlEncodeEntitiesReentrant()\n");
633: warning = 0;
634: }
1.28 daniel 635:
636: if (input == NULL) return(NULL);
1.39 daniel 637: if (doc != NULL)
638: html = (doc->type == XML_HTML_DOCUMENT_NODE);
639:
1.28 daniel 640: if (buffer == NULL) {
641: buffer_size = 1000;
1.38 daniel 642: buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
1.28 daniel 643: if (buffer == NULL) {
644: perror("malloc failed");
1.44 daniel 645: return(NULL);
1.28 daniel 646: }
647: out = buffer;
648: }
649: while (*cur != '\0') {
650: if (out - buffer > buffer_size - 100) {
651: int index = out - buffer;
652:
653: growBuffer();
654: out = &buffer[index];
655: }
656:
657: /*
658: * By default one have to encode at least '<', '>', '"' and '&' !
659: */
660: if (*cur == '<') {
661: *out++ = '&';
662: *out++ = 'l';
663: *out++ = 't';
664: *out++ = ';';
665: } else if (*cur == '>') {
666: *out++ = '&';
667: *out++ = 'g';
668: *out++ = 't';
669: *out++ = ';';
670: } else if (*cur == '&') {
671: *out++ = '&';
672: *out++ = 'a';
673: *out++ = 'm';
674: *out++ = 'p';
675: *out++ = ';';
676: } else if (*cur == '"') {
677: *out++ = '&';
678: *out++ = 'q';
679: *out++ = 'u';
680: *out++ = 'o';
681: *out++ = 't';
682: *out++ = ';';
1.39 daniel 683: } else if ((*cur == '\'') && (!html)) {
1.28 daniel 684: *out++ = '&';
685: *out++ = 'a';
686: *out++ = 'p';
687: *out++ = 'o';
688: *out++ = 's';
689: *out++ = ';';
690: } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
691: (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
692: /*
693: * default case, just copy !
694: */
695: *out++ = *cur;
696: #ifndef USE_UTF_8
1.38 daniel 697: } else if ((sizeof(xmlChar) == 1) && (*cur >= 0x80)) {
1.28 daniel 698: char buf[10], *ptr;
699: #ifdef HAVE_SNPRINTF
700: snprintf(buf, 9, "&#%d;", *cur);
701: #else
702: sprintf(buf, "&#%d;", *cur);
703: #endif
704: ptr = buf;
705: while (*ptr != 0) *out++ = *ptr++;
706: #endif
707: } else if (IS_CHAR(*cur)) {
708: char buf[10], *ptr;
709:
710: #ifdef HAVE_SNPRINTF
711: snprintf(buf, 9, "&#%d;", *cur);
712: #else
713: sprintf(buf, "&#%d;", *cur);
714: #endif
715: ptr = buf;
716: while (*ptr != 0) *out++ = *ptr++;
717: }
718: #if 0
719: else {
720: /*
721: * default case, this is not a valid char !
722: * Skip it...
723: */
724: fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur);
725: }
726: #endif
727: cur++;
728: }
729: *out++ = 0;
730: return(buffer);
731: }
732:
733: /*
734: * Macro used to grow the current buffer.
735: */
736: #define growBufferReentrant() { \
737: buffer_size *= 2; \
1.44 daniel 738: buffer = (xmlChar *) \
739: xmlRealloc(buffer, buffer_size * sizeof(xmlChar)); \
1.28 daniel 740: if (buffer == NULL) { \
741: perror("realloc failed"); \
1.44 daniel 742: return(NULL); \
1.28 daniel 743: } \
744: }
745:
746:
747: /**
748: * xmlEncodeEntitiesReentrant:
749: * @doc: the document containing the string
750: * @input: A string to convert to XML.
751: *
752: * Do a global encoding of a string, replacing the predefined entities
753: * and non ASCII values with their entities and CharRef counterparts.
754: * Contrary to xmlEncodeEntities, this routine is reentrant, and result
755: * must be deallocated.
756: *
757: * TODO !!!! Once moved to UTF-8 internal encoding, the encoding of non-ascii
758: * get erroneous.
759: *
1.24 daniel 760: * Returns A newly allocated string with the substitution done.
1.1 httpng 761: */
1.38 daniel 762: xmlChar *
763: xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input) {
764: const xmlChar *cur = input;
765: xmlChar *buffer = NULL;
766: xmlChar *out = NULL;
1.26 daniel 767: int buffer_size = 0;
1.39 daniel 768: int html = 0;
1.3 httpng 769:
1.19 daniel 770: if (input == NULL) return(NULL);
1.39 daniel 771: if (doc != NULL)
772: html = (doc->type == XML_HTML_DOCUMENT_NODE);
1.26 daniel 773:
774: /*
775: * allocate an translation buffer.
776: */
777: buffer_size = 1000;
1.38 daniel 778: buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
1.3 httpng 779: if (buffer == NULL) {
1.26 daniel 780: perror("malloc failed");
1.44 daniel 781: return(NULL);
1.3 httpng 782: }
1.26 daniel 783: out = buffer;
784:
1.6 veillard 785: while (*cur != '\0') {
786: if (out - buffer > buffer_size - 100) {
787: int index = out - buffer;
788:
1.28 daniel 789: growBufferReentrant();
1.6 veillard 790: out = &buffer[index];
791: }
792:
793: /*
1.7 veillard 794: * By default one have to encode at least '<', '>', '"' and '&' !
1.6 veillard 795: */
796: if (*cur == '<') {
797: *out++ = '&';
798: *out++ = 'l';
799: *out++ = 't';
800: *out++ = ';';
1.7 veillard 801: } else if (*cur == '>') {
802: *out++ = '&';
803: *out++ = 'g';
804: *out++ = 't';
805: *out++ = ';';
1.6 veillard 806: } else if (*cur == '&') {
807: *out++ = '&';
808: *out++ = 'a';
809: *out++ = 'm';
810: *out++ = 'p';
1.7 veillard 811: *out++ = ';';
812: } else if (*cur == '"') {
813: *out++ = '&';
814: *out++ = 'q';
815: *out++ = 'u';
816: *out++ = 'o';
817: *out++ = 't';
818: *out++ = ';';
1.53 daniel 819: #if 0
1.39 daniel 820: } else if ((*cur == '\'') && (!html)) {
1.7 veillard 821: *out++ = '&';
822: *out++ = 'a';
823: *out++ = 'p';
824: *out++ = 'o';
825: *out++ = 's';
1.6 veillard 826: *out++ = ';';
1.53 daniel 827: #endif
1.21 daniel 828: } else if (((*cur >= 0x20) && (*cur < 0x80)) ||
829: (*cur == '\n') || (*cur == '\r') || (*cur == '\t')) {
830: /*
831: * default case, just copy !
832: */
833: *out++ = *cur;
1.46 daniel 834: } else if (*cur >= 0x80) {
1.59 ! veillard 835: if ((doc->encoding != NULL) || (html)) {
1.46 daniel 836: /*
837: * TODO !!!
838: */
839: *out++ = *cur;
840: } else {
841: /*
842: * We assume we have UTF-8 input.
843: */
844: char buf[10], *ptr;
1.48 daniel 845: int val = 0, l = 1;
1.46 daniel 846:
847: if (*cur < 0xC0) {
848: fprintf(stderr,
849: "xmlEncodeEntitiesReentrant : input not UTF-8\n");
850: doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
851: #ifdef HAVE_SNPRINTF
852: snprintf(buf, 9, "&#%d;", *cur);
853: #else
854: sprintf(buf, "&#%d;", *cur);
855: #endif
856: ptr = buf;
857: while (*ptr != 0) *out++ = *ptr++;
858: continue;
859: } else if (*cur < 0xE0) {
860: val = (cur[0]) & 0x1F;
861: val <<= 6;
862: val |= (cur[1]) & 0x3F;
863: l = 2;
864: } else if (*cur < 0xF0) {
865: val = (cur[0]) & 0x0F;
866: val <<= 6;
867: val |= (cur[1]) & 0x3F;
868: val <<= 6;
869: val |= (cur[2]) & 0x3F;
870: l = 3;
871: } else if (*cur < 0xF8) {
872: val = (cur[0]) & 0x07;
873: val <<= 6;
874: val |= (cur[1]) & 0x3F;
875: val <<= 6;
876: val |= (cur[2]) & 0x3F;
877: val <<= 6;
878: val |= (cur[3]) & 0x3F;
879: l = 4;
880: }
881: if ((l == 1) || (!IS_CHAR(val))) {
882: fprintf(stderr,
883: "xmlEncodeEntitiesReentrant : char out of range\n");
884: doc->encoding = xmlStrdup(BAD_CAST "ISO-8859-1");
885: #ifdef HAVE_SNPRINTF
886: snprintf(buf, 9, "&#%d;", *cur);
887: #else
888: sprintf(buf, "&#%d;", *cur);
889: #endif
890: ptr = buf;
891: while (*ptr != 0) *out++ = *ptr++;
892: cur++;
893: continue;
894: }
895: /*
896: * We could do multiple things here. Just save as a char ref
897: */
898: #ifdef HAVE_SNPRINTF
1.50 daniel 899: snprintf(buf, 14, "&#x%X;", val);
1.46 daniel 900: #else
1.50 daniel 901: sprintf(buf, "&#x%X;", val);
1.46 daniel 902: #endif
1.50 daniel 903: buf[14] = 0;
1.47 daniel 904: ptr = buf;
905: while (*ptr != 0) *out++ = *ptr++;
906: cur += l;
907: continue;
1.45 daniel 908: }
1.21 daniel 909: } else if (IS_CHAR(*cur)) {
1.20 daniel 910: char buf[10], *ptr;
911:
912: #ifdef HAVE_SNPRINTF
913: snprintf(buf, 9, "&#%d;", *cur);
914: #else
915: sprintf(buf, "&#%d;", *cur);
916: #endif
917: ptr = buf;
918: while (*ptr != 0) *out++ = *ptr++;
1.21 daniel 919: }
920: #if 0
921: else {
1.6 veillard 922: /*
1.21 daniel 923: * default case, this is not a valid char !
924: * Skip it...
1.6 veillard 925: */
1.21 daniel 926: fprintf(stderr, "xmlEncodeEntities: invalid char %d\n", (int) *cur);
1.6 veillard 927: }
1.21 daniel 928: #endif
1.6 veillard 929: cur++;
930: }
931: *out++ = 0;
932: return(buffer);
1.2 httpng 933: }
934:
1.22 daniel 935: /**
1.57 daniel 936: * xmlEncodeSpecialChars:
937: * @doc: the document containing the string
938: * @input: A string to convert to XML.
939: *
940: * Do a global encoding of a string, replacing the predefined entities
941: * this routine is reentrant, and result must be deallocated.
942: *
943: * Returns A newly allocated string with the substitution done.
944: */
945: xmlChar *
946: xmlEncodeSpecialChars(xmlDocPtr doc, const xmlChar *input) {
947: const xmlChar *cur = input;
948: xmlChar *buffer = NULL;
949: xmlChar *out = NULL;
950: int buffer_size = 0;
951: int html = 0;
952:
953: if (input == NULL) return(NULL);
954: if (doc != NULL)
955: html = (doc->type == XML_HTML_DOCUMENT_NODE);
956:
957: /*
958: * allocate an translation buffer.
959: */
960: buffer_size = 1000;
961: buffer = (xmlChar *) xmlMalloc(buffer_size * sizeof(xmlChar));
962: if (buffer == NULL) {
963: perror("malloc failed");
964: return(NULL);
965: }
966: out = buffer;
967:
968: while (*cur != '\0') {
969: if (out - buffer > buffer_size - 10) {
970: int index = out - buffer;
971:
972: growBufferReentrant();
973: out = &buffer[index];
974: }
975:
976: /*
977: * By default one have to encode at least '<', '>', '"' and '&' !
978: */
979: if (*cur == '<') {
980: *out++ = '&';
981: *out++ = 'l';
982: *out++ = 't';
983: *out++ = ';';
984: } else if (*cur == '>') {
985: *out++ = '&';
986: *out++ = 'g';
987: *out++ = 't';
988: *out++ = ';';
989: } else if (*cur == '&') {
990: *out++ = '&';
991: *out++ = 'a';
992: *out++ = 'm';
993: *out++ = 'p';
994: *out++ = ';';
995: } else if (*cur == '"') {
996: *out++ = '&';
997: *out++ = 'q';
998: *out++ = 'u';
999: *out++ = 'o';
1000: *out++ = 't';
1001: *out++ = ';';
1002: } else {
1003: /*
1004: * Works because on UTF-8, all extended sequences cannot
1005: * result in bytes in the ASCII range.
1006: */
1007: *out++ = *cur;
1008: }
1009: cur++;
1010: }
1011: *out++ = 0;
1012: return(buffer);
1013: }
1014:
1015: /**
1.22 daniel 1016: * xmlCreateEntitiesTable:
1017: *
1018: * create and initialize an empty entities hash table.
1019: *
1.24 daniel 1020: * Returns the xmlEntitiesTablePtr just created or NULL in case of error.
1.2 httpng 1021: */
1.22 daniel 1022: xmlEntitiesTablePtr
1023: xmlCreateEntitiesTable(void) {
1.2 httpng 1024: xmlEntitiesTablePtr ret;
1.1 httpng 1025:
1.2 httpng 1026: ret = (xmlEntitiesTablePtr)
1.36 daniel 1027: xmlMalloc(sizeof(xmlEntitiesTable));
1.1 httpng 1028: if (ret == NULL) {
1.36 daniel 1029: fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failed\n",
1.28 daniel 1030: (long)sizeof(xmlEntitiesTable));
1.2 httpng 1031: return(NULL);
1032: }
1033: ret->max_entities = XML_MIN_ENTITIES_TABLE;
1034: ret->nb_entities = 0;
1.51 daniel 1035: ret->table = (xmlEntityPtr *)
1036: xmlMalloc(ret->max_entities * sizeof(xmlEntityPtr));
1.2 httpng 1037: if (ret == NULL) {
1.36 daniel 1038: fprintf(stderr, "xmlCreateEntitiesTable : xmlMalloc(%ld) failed\n",
1.51 daniel 1039: ret->max_entities * (long)sizeof(xmlEntityPtr));
1.36 daniel 1040: xmlFree(ret);
1.1 httpng 1041: return(NULL);
1042: }
1043: return(ret);
1044: }
1045:
1.22 daniel 1046: /**
1047: * xmlFreeEntitiesTable:
1048: * @table: An entity table
1049: *
1050: * Deallocate the memory used by an entities hash table.
1.1 httpng 1051: */
1.22 daniel 1052: void
1053: xmlFreeEntitiesTable(xmlEntitiesTablePtr table) {
1.1 httpng 1054: int i;
1055:
1056: if (table == NULL) return;
1057:
1.2 httpng 1058: for (i = 0;i < table->nb_entities;i++) {
1.51 daniel 1059: xmlFreeEntity(table->table[i]);
1.1 httpng 1060: }
1.36 daniel 1061: xmlFree(table->table);
1062: xmlFree(table);
1.1 httpng 1063: }
1064:
1.22 daniel 1065: /**
1066: * xmlCopyEntitiesTable:
1067: * @table: An entity table
1068: *
1069: * Build a copy of an entity table.
1070: *
1.24 daniel 1071: * Returns the new xmlEntitiesTablePtr or NULL in case of error.
1.22 daniel 1072: */
1073: xmlEntitiesTablePtr
1074: xmlCopyEntitiesTable(xmlEntitiesTablePtr table) {
1075: xmlEntitiesTablePtr ret;
1076: xmlEntityPtr cur, ent;
1077: int i;
1078:
1.36 daniel 1079: ret = (xmlEntitiesTablePtr) xmlMalloc(sizeof(xmlEntitiesTable));
1.22 daniel 1080: if (ret == NULL) {
1081: fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
1082: return(NULL);
1083: }
1.51 daniel 1084: ret->table = (xmlEntityPtr *) xmlMalloc(table->max_entities *
1085: sizeof(xmlEntityPtr));
1.22 daniel 1086: if (ret->table == NULL) {
1087: fprintf(stderr, "xmlCopyEntitiesTable: out of memory !\n");
1.36 daniel 1088: xmlFree(ret);
1.22 daniel 1089: return(NULL);
1090: }
1091: ret->max_entities = table->max_entities;
1092: ret->nb_entities = table->nb_entities;
1093: for (i = 0;i < ret->nb_entities;i++) {
1.51 daniel 1094: cur = (xmlEntityPtr) xmlMalloc(sizeof(xmlEntity));
1095: if (cur == NULL) {
1096: fprintf(stderr, "xmlCopyEntityTable: out of memory !\n");
1097: xmlFree(ret);
1098: xmlFree(ret->table);
1099: return(NULL);
1100: }
1101: memset(cur, 0, sizeof(xmlEntity));
1102: cur->type = XML_ELEMENT_DECL;
1103: ret->table[i] = cur;
1104: ent = table->table[i];
1105:
1.49 daniel 1106: cur->etype = ent->etype;
1.22 daniel 1107: if (ent->name != NULL)
1108: cur->name = xmlStrdup(ent->name);
1109: if (ent->ExternalID != NULL)
1110: cur->ExternalID = xmlStrdup(ent->ExternalID);
1111: if (ent->SystemID != NULL)
1112: cur->SystemID = xmlStrdup(ent->SystemID);
1113: if (ent->content != NULL)
1114: cur->content = xmlStrdup(ent->content);
1.27 daniel 1115: if (ent->orig != NULL)
1116: cur->orig = xmlStrdup(ent->orig);
1.22 daniel 1117: }
1118: return(ret);
1119: }
1120:
1121: /**
1.53 daniel 1122: * xmlDumpEntityDecl:
1123: * @buf: An XML buffer.
1124: * @ent: An entity table
1125: *
1126: * This will dump the content of the entity table as an XML DTD definition
1127: */
1128: void
1129: xmlDumpEntityDecl(xmlBufferPtr buf, xmlEntityPtr ent) {
1130: switch (ent->etype) {
1131: case XML_INTERNAL_GENERAL_ENTITY:
1132: xmlBufferWriteChar(buf, "<!ENTITY ");
1133: xmlBufferWriteCHAR(buf, ent->name);
1134: xmlBufferWriteChar(buf, " ");
1135: if (ent->orig != NULL)
1136: xmlBufferWriteQuotedString(buf, ent->orig);
1137: else
1138: xmlBufferWriteQuotedString(buf, ent->content);
1139: xmlBufferWriteChar(buf, ">\n");
1140: break;
1141: case XML_EXTERNAL_GENERAL_PARSED_ENTITY:
1142: xmlBufferWriteChar(buf, "<!ENTITY ");
1143: xmlBufferWriteCHAR(buf, ent->name);
1144: if (ent->ExternalID != NULL) {
1145: xmlBufferWriteChar(buf, " PUBLIC ");
1146: xmlBufferWriteQuotedString(buf, ent->ExternalID);
1147: xmlBufferWriteChar(buf, " ");
1148: xmlBufferWriteQuotedString(buf, ent->SystemID);
1149: } else {
1150: xmlBufferWriteChar(buf, " SYSTEM ");
1151: xmlBufferWriteQuotedString(buf, ent->SystemID);
1152: }
1153: xmlBufferWriteChar(buf, ">\n");
1154: break;
1155: case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY:
1156: xmlBufferWriteChar(buf, "<!ENTITY ");
1157: xmlBufferWriteCHAR(buf, ent->name);
1158: if (ent->ExternalID != NULL) {
1159: xmlBufferWriteChar(buf, " PUBLIC ");
1160: xmlBufferWriteQuotedString(buf, ent->ExternalID);
1161: xmlBufferWriteChar(buf, " ");
1162: xmlBufferWriteQuotedString(buf, ent->SystemID);
1163: } else {
1164: xmlBufferWriteChar(buf, " SYSTEM ");
1165: xmlBufferWriteQuotedString(buf, ent->SystemID);
1166: }
1167: if (ent->content != NULL) { /* Should be true ! */
1168: xmlBufferWriteChar(buf, " NDATA ");
1169: if (ent->orig != NULL)
1170: xmlBufferWriteCHAR(buf, ent->orig);
1171: else
1172: xmlBufferWriteCHAR(buf, ent->content);
1173: }
1174: xmlBufferWriteChar(buf, ">\n");
1175: break;
1176: case XML_INTERNAL_PARAMETER_ENTITY:
1177: xmlBufferWriteChar(buf, "<!ENTITY % ");
1178: xmlBufferWriteCHAR(buf, ent->name);
1179: xmlBufferWriteChar(buf, " ");
1180: if (ent->orig == NULL)
1181: xmlBufferWriteQuotedString(buf, ent->content);
1182: else
1183: xmlBufferWriteQuotedString(buf, ent->orig);
1184: xmlBufferWriteChar(buf, ">\n");
1185: break;
1186: case XML_EXTERNAL_PARAMETER_ENTITY:
1187: xmlBufferWriteChar(buf, "<!ENTITY % ");
1188: xmlBufferWriteCHAR(buf, ent->name);
1189: if (ent->ExternalID != NULL) {
1190: xmlBufferWriteChar(buf, " PUBLIC ");
1191: xmlBufferWriteQuotedString(buf, ent->ExternalID);
1192: xmlBufferWriteChar(buf, " ");
1193: xmlBufferWriteQuotedString(buf, ent->SystemID);
1194: } else {
1195: xmlBufferWriteChar(buf, " SYSTEM ");
1196: xmlBufferWriteQuotedString(buf, ent->SystemID);
1197: }
1198: xmlBufferWriteChar(buf, ">\n");
1199: break;
1200: default:
1201: fprintf(stderr,
1202: "xmlDumpEntitiesTable: internal: unknown type %d\n",
1203: ent->etype);
1204: }
1205: }
1206:
1207: /**
1.22 daniel 1208: * xmlDumpEntitiesTable:
1.25 daniel 1209: * @buf: An XML buffer.
1.22 daniel 1210: * @table: An entity table
1211: *
1212: * This will dump the content of the entity table as an XML DTD definition
1.13 daniel 1213: */
1.22 daniel 1214: void
1.25 daniel 1215: xmlDumpEntitiesTable(xmlBufferPtr buf, xmlEntitiesTablePtr table) {
1.14 daniel 1216: int i;
1217: xmlEntityPtr cur;
1218:
1219: if (table == NULL) return;
1220:
1221: for (i = 0;i < table->nb_entities;i++) {
1.51 daniel 1222: cur = table->table[i];
1.53 daniel 1223: xmlDumpEntityDecl(buf, cur);
1.14 daniel 1224: }
1.13 daniel 1225: }
Webmaster