2 * entities.c : implementation for the XML entities handling
4 * See Copyright for the status of this software.
16 #include <libxml/xmlmemory.h>
17 #include <libxml/hash.h>
18 #include <libxml/entities.h>
19 #include <libxml/parser.h>
20 #include <libxml/parserInternals.h>
21 #include <libxml/xmlerror.h>
22 #include <libxml/globals.h>
23 #include <libxml/dict.h>
28 * The XML predefined entities.
31 static xmlEntity xmlEntityLt
= {
32 NULL
, XML_ENTITY_DECL
, BAD_CAST
"lt",
33 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
34 BAD_CAST
"<", BAD_CAST
"<", 1,
35 XML_INTERNAL_PREDEFINED_ENTITY
,
36 NULL
, NULL
, NULL
, NULL
, 0, 1
38 static xmlEntity xmlEntityGt
= {
39 NULL
, XML_ENTITY_DECL
, BAD_CAST
"gt",
40 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
41 BAD_CAST
">", BAD_CAST
">", 1,
42 XML_INTERNAL_PREDEFINED_ENTITY
,
43 NULL
, NULL
, NULL
, NULL
, 0, 1
45 static xmlEntity xmlEntityAmp
= {
46 NULL
, XML_ENTITY_DECL
, BAD_CAST
"amp",
47 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
48 BAD_CAST
"&", BAD_CAST
"&", 1,
49 XML_INTERNAL_PREDEFINED_ENTITY
,
50 NULL
, NULL
, NULL
, NULL
, 0, 1
52 static xmlEntity xmlEntityQuot
= {
53 NULL
, XML_ENTITY_DECL
, BAD_CAST
"quot",
54 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
55 BAD_CAST
"\"", BAD_CAST
"\"", 1,
56 XML_INTERNAL_PREDEFINED_ENTITY
,
57 NULL
, NULL
, NULL
, NULL
, 0, 1
59 static xmlEntity xmlEntityApos
= {
60 NULL
, XML_ENTITY_DECL
, BAD_CAST
"apos",
61 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
62 BAD_CAST
"'", BAD_CAST
"'", 1,
63 XML_INTERNAL_PREDEFINED_ENTITY
,
64 NULL
, NULL
, NULL
, NULL
, 0, 1
68 * xmlEntitiesErrMemory:
69 * @extra: extra informations
71 * Handle an out of memory condition
74 xmlEntitiesErrMemory(const char *extra
)
76 __xmlSimpleError(XML_FROM_TREE
, XML_ERR_NO_MEMORY
, NULL
, NULL
, extra
);
81 * @code: the error code
84 * Handle an out of memory condition
87 xmlEntitiesErr(xmlParserErrors code
, const char *msg
)
89 __xmlSimpleError(XML_FROM_TREE
, code
, NULL
, msg
, NULL
);
93 * xmlFreeEntity : clean-up an entity record.
96 xmlFreeEntity(xmlEntityPtr entity
)
98 xmlDictPtr dict
= NULL
;
103 if (entity
->doc
!= NULL
)
104 dict
= entity
->doc
->dict
;
107 if ((entity
->children
) && (entity
->owner
== 1) &&
108 (entity
== (xmlEntityPtr
) entity
->children
->parent
))
109 xmlFreeNodeList(entity
->children
);
111 if ((entity
->name
!= NULL
) && (!xmlDictOwns(dict
, entity
->name
)))
112 xmlFree((char *) entity
->name
);
113 if ((entity
->ExternalID
!= NULL
) &&
114 (!xmlDictOwns(dict
, entity
->ExternalID
)))
115 xmlFree((char *) entity
->ExternalID
);
116 if ((entity
->SystemID
!= NULL
) &&
117 (!xmlDictOwns(dict
, entity
->SystemID
)))
118 xmlFree((char *) entity
->SystemID
);
119 if ((entity
->URI
!= NULL
) && (!xmlDictOwns(dict
, entity
->URI
)))
120 xmlFree((char *) entity
->URI
);
121 if ((entity
->content
!= NULL
)
122 && (!xmlDictOwns(dict
, entity
->content
)))
123 xmlFree((char *) entity
->content
);
124 if ((entity
->orig
!= NULL
) && (!xmlDictOwns(dict
, entity
->orig
)))
125 xmlFree((char *) entity
->orig
);
127 if (entity
->name
!= NULL
)
128 xmlFree((char *) entity
->name
);
129 if (entity
->ExternalID
!= NULL
)
130 xmlFree((char *) entity
->ExternalID
);
131 if (entity
->SystemID
!= NULL
)
132 xmlFree((char *) entity
->SystemID
);
133 if (entity
->URI
!= NULL
)
134 xmlFree((char *) entity
->URI
);
135 if (entity
->content
!= NULL
)
136 xmlFree((char *) entity
->content
);
137 if (entity
->orig
!= NULL
)
138 xmlFree((char *) entity
->orig
);
146 * internal routine doing the entity node strutures allocations
149 xmlCreateEntity(xmlDictPtr dict
, const xmlChar
*name
, int type
,
150 const xmlChar
*ExternalID
, const xmlChar
*SystemID
,
151 const xmlChar
*content
) {
154 ret
= (xmlEntityPtr
) xmlMalloc(sizeof(xmlEntity
));
156 xmlEntitiesErrMemory("xmlCreateEntity: malloc failed");
159 memset(ret
, 0, sizeof(xmlEntity
));
160 ret
->type
= XML_ENTITY_DECL
;
164 * fill the structure.
166 ret
->etype
= (xmlEntityType
) type
;
168 ret
->name
= xmlStrdup(name
);
169 if (ExternalID
!= NULL
)
170 ret
->ExternalID
= xmlStrdup(ExternalID
);
171 if (SystemID
!= NULL
)
172 ret
->SystemID
= xmlStrdup(SystemID
);
174 ret
->name
= xmlDictLookup(dict
, name
, -1);
175 if (ExternalID
!= NULL
)
176 ret
->ExternalID
= xmlDictLookup(dict
, ExternalID
, -1);
177 if (SystemID
!= NULL
)
178 ret
->SystemID
= xmlDictLookup(dict
, SystemID
, -1);
180 if (content
!= NULL
) {
181 ret
->length
= xmlStrlen(content
);
182 if ((dict
!= NULL
) && (ret
->length
< 5))
183 ret
->content
= (xmlChar
*)
184 xmlDictLookup(dict
, content
, ret
->length
);
186 ret
->content
= xmlStrndup(content
, ret
->length
);
191 ret
->URI
= NULL
; /* to be computed by the layer knowing
192 the defining entity */
200 * xmlAddEntity : register a new entity for an entities table.
203 xmlAddEntity(xmlDtdPtr dtd
, const xmlChar
*name
, int type
,
204 const xmlChar
*ExternalID
, const xmlChar
*SystemID
,
205 const xmlChar
*content
) {
206 xmlDictPtr dict
= NULL
;
207 xmlEntitiesTablePtr table
= NULL
;
214 if (dtd
->doc
!= NULL
)
215 dict
= dtd
->doc
->dict
;
218 case XML_INTERNAL_GENERAL_ENTITY
:
219 case XML_EXTERNAL_GENERAL_PARSED_ENTITY
:
220 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY
:
221 if (dtd
->entities
== NULL
)
222 dtd
->entities
= xmlHashCreateDict(0, dict
);
223 table
= dtd
->entities
;
225 case XML_INTERNAL_PARAMETER_ENTITY
:
226 case XML_EXTERNAL_PARAMETER_ENTITY
:
227 if (dtd
->pentities
== NULL
)
228 dtd
->pentities
= xmlHashCreateDict(0, dict
);
229 table
= dtd
->pentities
;
231 case XML_INTERNAL_PREDEFINED_ENTITY
:
236 ret
= xmlCreateEntity(dict
, name
, type
, ExternalID
, SystemID
, content
);
241 if (xmlHashAddEntry(table
, name
, ret
)) {
243 * entity was already defined at another level.
252 * xmlGetPredefinedEntity:
253 * @name: the entity name
255 * Check whether this name is an predefined entity.
257 * Returns NULL if not, otherwise the entity
260 xmlGetPredefinedEntity(const xmlChar
*name
) {
261 if (name
== NULL
) return(NULL
);
264 if (xmlStrEqual(name
, BAD_CAST
"lt"))
265 return(&xmlEntityLt
);
268 if (xmlStrEqual(name
, BAD_CAST
"gt"))
269 return(&xmlEntityGt
);
272 if (xmlStrEqual(name
, BAD_CAST
"amp"))
273 return(&xmlEntityAmp
);
274 if (xmlStrEqual(name
, BAD_CAST
"apos"))
275 return(&xmlEntityApos
);
278 if (xmlStrEqual(name
, BAD_CAST
"quot"))
279 return(&xmlEntityQuot
);
290 * @name: the entity name
291 * @type: the entity type XML_xxx_yyy_ENTITY
292 * @ExternalID: the entity external ID if available
293 * @SystemID: the entity system ID if available
294 * @content: the entity content
296 * Register a new entity for this document DTD external subset.
298 * Returns a pointer to the entity or NULL in case of error
301 xmlAddDtdEntity(xmlDocPtr doc
, const xmlChar
*name
, int type
,
302 const xmlChar
*ExternalID
, const xmlChar
*SystemID
,
303 const xmlChar
*content
) {
308 xmlEntitiesErr(XML_DTD_NO_DOC
,
309 "xmlAddDtdEntity: document is NULL");
312 if (doc
->extSubset
== NULL
) {
313 xmlEntitiesErr(XML_DTD_NO_DTD
,
314 "xmlAddDtdEntity: document without external subset");
317 dtd
= doc
->extSubset
;
318 ret
= xmlAddEntity(dtd
, name
, type
, ExternalID
, SystemID
, content
);
319 if (ret
== NULL
) return(NULL
);
326 if (dtd
->last
== NULL
) {
327 dtd
->children
= dtd
->last
= (xmlNodePtr
) ret
;
329 dtd
->last
->next
= (xmlNodePtr
) ret
;
330 ret
->prev
= dtd
->last
;
331 dtd
->last
= (xmlNodePtr
) ret
;
339 * @name: the entity name
340 * @type: the entity type XML_xxx_yyy_ENTITY
341 * @ExternalID: the entity external ID if available
342 * @SystemID: the entity system ID if available
343 * @content: the entity content
345 * Register a new entity for this document.
347 * Returns a pointer to the entity or NULL in case of error
350 xmlAddDocEntity(xmlDocPtr doc
, const xmlChar
*name
, int type
,
351 const xmlChar
*ExternalID
, const xmlChar
*SystemID
,
352 const xmlChar
*content
) {
357 xmlEntitiesErr(XML_DTD_NO_DOC
,
358 "xmlAddDocEntity: document is NULL");
361 if (doc
->intSubset
== NULL
) {
362 xmlEntitiesErr(XML_DTD_NO_DTD
,
363 "xmlAddDocEntity: document without internal subset");
366 dtd
= doc
->intSubset
;
367 ret
= xmlAddEntity(dtd
, name
, type
, ExternalID
, SystemID
, content
);
368 if (ret
== NULL
) return(NULL
);
375 if (dtd
->last
== NULL
) {
376 dtd
->children
= dtd
->last
= (xmlNodePtr
) ret
;
378 dtd
->last
->next
= (xmlNodePtr
) ret
;
379 ret
->prev
= dtd
->last
;
380 dtd
->last
= (xmlNodePtr
) ret
;
388 * @name: the entity name
389 * @type: the entity type XML_xxx_yyy_ENTITY
390 * @ExternalID: the entity external ID if available
391 * @SystemID: the entity system ID if available
392 * @content: the entity content
394 * Create a new entity, this differs from xmlAddDocEntity() that if
395 * the document is NULL or has no internal subset defined, then an
396 * unlinked entity structure will be returned, it is then the responsability
397 * of the caller to link it to the document later or free it when not needed
400 * Returns a pointer to the entity or NULL in case of error
403 xmlNewEntity(xmlDocPtr doc
, const xmlChar
*name
, int type
,
404 const xmlChar
*ExternalID
, const xmlChar
*SystemID
,
405 const xmlChar
*content
) {
409 if ((doc
!= NULL
) && (doc
->intSubset
!= NULL
)) {
410 return(xmlAddDocEntity(doc
, name
, type
, ExternalID
, SystemID
, content
));
416 ret
= xmlCreateEntity(dict
, name
, type
, ExternalID
, SystemID
, content
);
424 * xmlGetEntityFromTable:
425 * @table: an entity table
426 * @name: the entity name
427 * @parameter: look for parameter entities
429 * Do an entity lookup in the table.
430 * returns the corresponding parameter entity, if found.
432 * Returns A pointer to the entity structure or NULL if not found.
435 xmlGetEntityFromTable(xmlEntitiesTablePtr table
, const xmlChar
*name
) {
436 return((xmlEntityPtr
) xmlHashLookup(table
, name
));
440 * xmlGetParameterEntity:
441 * @doc: the document referencing the entity
442 * @name: the entity name
444 * Do an entity lookup in the internal and external subsets and
445 * returns the corresponding parameter entity, if found.
447 * Returns A pointer to the entity structure or NULL if not found.
450 xmlGetParameterEntity(xmlDocPtr doc
, const xmlChar
*name
) {
451 xmlEntitiesTablePtr table
;
456 if ((doc
->intSubset
!= NULL
) && (doc
->intSubset
->pentities
!= NULL
)) {
457 table
= (xmlEntitiesTablePtr
) doc
->intSubset
->pentities
;
458 ret
= xmlGetEntityFromTable(table
, name
);
462 if ((doc
->extSubset
!= NULL
) && (doc
->extSubset
->pentities
!= NULL
)) {
463 table
= (xmlEntitiesTablePtr
) doc
->extSubset
->pentities
;
464 return(xmlGetEntityFromTable(table
, name
));
471 * @doc: the document referencing the entity
472 * @name: the entity name
474 * Do an entity lookup in the DTD entity hash table and
475 * returns the corresponding entity, if found.
476 * Note: the first argument is the document node, not the DTD node.
478 * Returns A pointer to the entity structure or NULL if not found.
481 xmlGetDtdEntity(xmlDocPtr doc
, const xmlChar
*name
) {
482 xmlEntitiesTablePtr table
;
486 if ((doc
->extSubset
!= NULL
) && (doc
->extSubset
->entities
!= NULL
)) {
487 table
= (xmlEntitiesTablePtr
) doc
->extSubset
->entities
;
488 return(xmlGetEntityFromTable(table
, name
));
495 * @doc: the document referencing the entity
496 * @name: the entity name
498 * Do an entity lookup in the document entity hash table and
499 * returns the corresponding entity, otherwise a lookup is done
500 * in the predefined entities too.
502 * Returns A pointer to the entity structure or NULL if not found.
505 xmlGetDocEntity(const xmlDoc
*doc
, const xmlChar
*name
) {
507 xmlEntitiesTablePtr table
;
510 if ((doc
->intSubset
!= NULL
) && (doc
->intSubset
->entities
!= NULL
)) {
511 table
= (xmlEntitiesTablePtr
) doc
->intSubset
->entities
;
512 cur
= xmlGetEntityFromTable(table
, name
);
516 if (doc
->standalone
!= 1) {
517 if ((doc
->extSubset
!= NULL
) &&
518 (doc
->extSubset
->entities
!= NULL
)) {
519 table
= (xmlEntitiesTablePtr
) doc
->extSubset
->entities
;
520 cur
= xmlGetEntityFromTable(table
, name
);
526 return(xmlGetPredefinedEntity(name
));
530 * Macro used to grow the current buffer.
532 #define growBufferReentrant() { \
534 size_t new_size = buffer_size * 2; \
535 if (new_size < buffer_size) goto mem_error; \
536 tmp = (xmlChar *) xmlRealloc(buffer, new_size); \
537 if (tmp == NULL) goto mem_error; \
539 buffer_size = new_size; \
543 * xmlEncodeEntitiesInternal:
544 * @doc: the document containing the string
545 * @input: A string to convert to XML.
546 * @attr: are we handling an atrbute value
548 * Do a global encoding of a string, replacing the predefined entities
549 * and non ASCII values with their entities and CharRef counterparts.
550 * Contrary to xmlEncodeEntities, this routine is reentrant, and result
551 * must be deallocated.
553 * Returns A newly allocated string with the substitution done.
556 xmlEncodeEntitiesInternal(xmlDocPtr doc
, const xmlChar
*input
, int attr
) {
557 const xmlChar
*cur
= input
;
558 xmlChar
*buffer
= NULL
;
560 size_t buffer_size
= 0;
563 if (input
== NULL
) return(NULL
);
565 html
= (doc
->type
== XML_HTML_DOCUMENT_NODE
);
568 * allocate an translation buffer.
571 buffer
= (xmlChar
*) xmlMalloc(buffer_size
* sizeof(xmlChar
));
572 if (buffer
== NULL
) {
573 xmlEntitiesErrMemory("xmlEncodeEntities: malloc failed");
578 while (*cur
!= '\0') {
579 size_t indx
= out
- buffer
;
580 if (indx
+ 100 > buffer_size
) {
582 growBufferReentrant();
587 * By default one have to encode at least '<', '>', '"' and '&' !
593 * Special handling of server side include in HTML attributes
596 (cur
[1] == '!') && (cur
[2] == '-') && (cur
[3] == '-') &&
597 ((end
= xmlStrstr(cur
, BAD_CAST
"-->")) != NULL
)) {
601 if (indx
+ 100 > buffer_size
) {
602 growBufferReentrant();
615 } else if (*cur
== '>') {
620 } else if (*cur
== '&') {
622 * Special handling of &{...} construct from HTML 4, see
623 * http://www.w3.org/TR/html401/appendix/notes.html#h-B.7.1
625 if (html
&& attr
&& (cur
[1] == '{') &&
626 (strchr((const char *) cur
, '}'))) {
627 while (*cur
!= '}') {
630 if (indx
+ 100 > buffer_size
) {
631 growBufferReentrant();
643 } else if (((*cur
>= 0x20) && (*cur
< 0x80)) ||
644 (*cur
== '\n') || (*cur
== '\t') || ((html
) && (*cur
== '\r'))) {
646 * default case, just copy !
649 } else if (*cur
>= 0x80) {
650 if (((doc
!= NULL
) && (doc
->encoding
!= NULL
)) || (html
)) {
652 * Bjørn Reese <br@sseusa.com> provided the patch
654 xc = (*cur & 0x3F) << 6;
656 xc += *(++cur) & 0x3F;
663 * We assume we have UTF-8 input.
669 xmlEntitiesErr(XML_CHECK_NOT_UTF8
,
670 "xmlEncodeEntities: input not UTF-8");
672 doc
->encoding
= xmlStrdup(BAD_CAST
"ISO-8859-1");
673 snprintf(buf
, sizeof(buf
), "&#%d;", *cur
);
674 buf
[sizeof(buf
) - 1] = 0;
676 while (*ptr
!= 0) *out
++ = *ptr
++;
679 } else if (*cur
< 0xE0) {
680 val
= (cur
[0]) & 0x1F;
682 val
|= (cur
[1]) & 0x3F;
684 } else if (*cur
< 0xF0) {
685 val
= (cur
[0]) & 0x0F;
687 val
|= (cur
[1]) & 0x3F;
689 val
|= (cur
[2]) & 0x3F;
691 } else if (*cur
< 0xF8) {
692 val
= (cur
[0]) & 0x07;
694 val
|= (cur
[1]) & 0x3F;
696 val
|= (cur
[2]) & 0x3F;
698 val
|= (cur
[3]) & 0x3F;
701 if ((l
== 1) || (!IS_CHAR(val
))) {
702 xmlEntitiesErr(XML_ERR_INVALID_CHAR
,
703 "xmlEncodeEntities: char out of range\n");
705 doc
->encoding
= xmlStrdup(BAD_CAST
"ISO-8859-1");
706 snprintf(buf
, sizeof(buf
), "&#%d;", *cur
);
707 buf
[sizeof(buf
) - 1] = 0;
709 while (*ptr
!= 0) *out
++ = *ptr
++;
714 * We could do multiple things here. Just save as a char ref
716 snprintf(buf
, sizeof(buf
), "&#x%X;", val
);
717 buf
[sizeof(buf
) - 1] = 0;
719 while (*ptr
!= 0) *out
++ = *ptr
++;
723 } else if (IS_BYTE_CHAR(*cur
)) {
726 snprintf(buf
, sizeof(buf
), "&#%d;", *cur
);
727 buf
[sizeof(buf
) - 1] = 0;
729 while (*ptr
!= 0) *out
++ = *ptr
++;
737 xmlEntitiesErrMemory("xmlEncodeEntities: realloc failed");
743 * xmlEncodeAttributeEntities:
744 * @doc: the document containing the string
745 * @input: A string to convert to XML.
747 * Do a global encoding of a string, replacing the predefined entities
748 * and non ASCII values with their entities and CharRef counterparts for
751 * Returns A newly allocated string with the substitution done.
754 xmlEncodeAttributeEntities(xmlDocPtr doc
, const xmlChar
*input
) {
755 return xmlEncodeEntitiesInternal(doc
, input
, 1);
759 * xmlEncodeEntitiesReentrant:
760 * @doc: the document containing the string
761 * @input: A string to convert to XML.
763 * Do a global encoding of a string, replacing the predefined entities
764 * and non ASCII values with their entities and CharRef counterparts.
765 * Contrary to xmlEncodeEntities, this routine is reentrant, and result
766 * must be deallocated.
768 * Returns A newly allocated string with the substitution done.
771 xmlEncodeEntitiesReentrant(xmlDocPtr doc
, const xmlChar
*input
) {
772 return xmlEncodeEntitiesInternal(doc
, input
, 0);
776 * xmlEncodeSpecialChars:
777 * @doc: the document containing the string
778 * @input: A string to convert to XML.
780 * Do a global encoding of a string, replacing the predefined entities
781 * this routine is reentrant, and result must be deallocated.
783 * Returns A newly allocated string with the substitution done.
786 xmlEncodeSpecialChars(const xmlDoc
*doc ATTRIBUTE_UNUSED
, const xmlChar
*input
) {
787 const xmlChar
*cur
= input
;
788 xmlChar
*buffer
= NULL
;
790 size_t buffer_size
= 0;
791 if (input
== NULL
) return(NULL
);
794 * allocate an translation buffer.
797 buffer
= (xmlChar
*) xmlMalloc(buffer_size
* sizeof(xmlChar
));
798 if (buffer
== NULL
) {
799 xmlEntitiesErrMemory("xmlEncodeSpecialChars: malloc failed");
804 while (*cur
!= '\0') {
805 size_t indx
= out
- buffer
;
806 if (indx
+ 10 > buffer_size
) {
808 growBufferReentrant();
813 * By default one have to encode at least '<', '>', '"' and '&' !
820 } else if (*cur
== '>') {
825 } else if (*cur
== '&') {
831 } else if (*cur
== '"') {
838 } else if (*cur
== '\r') {
846 * Works because on UTF-8, all extended sequences cannot
847 * result in bytes in the ASCII range.
857 xmlEntitiesErrMemory("xmlEncodeSpecialChars: realloc failed");
863 * xmlCreateEntitiesTable:
865 * create and initialize an empty entities hash table.
866 * This really doesn't make sense and should be deprecated
868 * Returns the xmlEntitiesTablePtr just created or NULL in case of error.
871 xmlCreateEntitiesTable(void) {
872 return((xmlEntitiesTablePtr
) xmlHashCreate(0));
876 * xmlFreeEntityWrapper:
880 * Deallocate the memory used by an entities in the hash table.
883 xmlFreeEntityWrapper(xmlEntityPtr entity
,
884 const xmlChar
*name ATTRIBUTE_UNUSED
) {
886 xmlFreeEntity(entity
);
890 * xmlFreeEntitiesTable:
891 * @table: An entity table
893 * Deallocate the memory used by an entities hash table.
896 xmlFreeEntitiesTable(xmlEntitiesTablePtr table
) {
897 xmlHashFree(table
, (xmlHashDeallocator
) xmlFreeEntityWrapper
);
900 #ifdef LIBXML_TREE_ENABLED
905 * Build a copy of an entity
907 * Returns the new xmlEntitiesPtr or NULL in case of error.
910 xmlCopyEntity(xmlEntityPtr ent
) {
913 cur
= (xmlEntityPtr
) xmlMalloc(sizeof(xmlEntity
));
915 xmlEntitiesErrMemory("xmlCopyEntity:: malloc failed");
918 memset(cur
, 0, sizeof(xmlEntity
));
919 cur
->type
= XML_ENTITY_DECL
;
921 cur
->etype
= ent
->etype
;
922 if (ent
->name
!= NULL
)
923 cur
->name
= xmlStrdup(ent
->name
);
924 if (ent
->ExternalID
!= NULL
)
925 cur
->ExternalID
= xmlStrdup(ent
->ExternalID
);
926 if (ent
->SystemID
!= NULL
)
927 cur
->SystemID
= xmlStrdup(ent
->SystemID
);
928 if (ent
->content
!= NULL
)
929 cur
->content
= xmlStrdup(ent
->content
);
930 if (ent
->orig
!= NULL
)
931 cur
->orig
= xmlStrdup(ent
->orig
);
932 if (ent
->URI
!= NULL
)
933 cur
->URI
= xmlStrdup(ent
->URI
);
938 * xmlCopyEntitiesTable:
939 * @table: An entity table
941 * Build a copy of an entity table.
943 * Returns the new xmlEntitiesTablePtr or NULL in case of error.
946 xmlCopyEntitiesTable(xmlEntitiesTablePtr table
) {
947 return(xmlHashCopy(table
, (xmlHashCopier
) xmlCopyEntity
));
949 #endif /* LIBXML_TREE_ENABLED */
951 #ifdef LIBXML_OUTPUT_ENABLED
954 * xmlDumpEntityContent:
955 * @buf: An XML buffer.
956 * @content: The entity content.
958 * This will dump the quoted string value, taking care of the special
959 * treatment required by %
962 xmlDumpEntityContent(xmlBufferPtr buf
, const xmlChar
*content
) {
963 if (buf
->alloc
== XML_BUFFER_ALLOC_IMMUTABLE
) return;
964 if (xmlStrchr(content
, '%')) {
965 const xmlChar
* base
, *cur
;
967 xmlBufferCCat(buf
, "\"");
968 base
= cur
= content
;
972 xmlBufferAdd(buf
, base
, cur
- base
);
973 xmlBufferAdd(buf
, BAD_CAST
""", 6);
976 } else if (*cur
== '%') {
978 xmlBufferAdd(buf
, base
, cur
- base
);
979 xmlBufferAdd(buf
, BAD_CAST
"%", 6);
987 xmlBufferAdd(buf
, base
, cur
- base
);
988 xmlBufferCCat(buf
, "\"");
990 xmlBufferWriteQuotedString(buf
, content
);
996 * @buf: An XML buffer.
997 * @ent: An entity table
999 * This will dump the content of the entity table as an XML DTD definition
1002 xmlDumpEntityDecl(xmlBufferPtr buf
, xmlEntityPtr ent
) {
1003 if ((buf
== NULL
) || (ent
== NULL
)) return;
1004 switch (ent
->etype
) {
1005 case XML_INTERNAL_GENERAL_ENTITY
:
1006 xmlBufferWriteChar(buf
, "<!ENTITY ");
1007 xmlBufferWriteCHAR(buf
, ent
->name
);
1008 xmlBufferWriteChar(buf
, " ");
1009 if (ent
->orig
!= NULL
)
1010 xmlBufferWriteQuotedString(buf
, ent
->orig
);
1012 xmlDumpEntityContent(buf
, ent
->content
);
1013 xmlBufferWriteChar(buf
, ">\n");
1015 case XML_EXTERNAL_GENERAL_PARSED_ENTITY
:
1016 xmlBufferWriteChar(buf
, "<!ENTITY ");
1017 xmlBufferWriteCHAR(buf
, ent
->name
);
1018 if (ent
->ExternalID
!= NULL
) {
1019 xmlBufferWriteChar(buf
, " PUBLIC ");
1020 xmlBufferWriteQuotedString(buf
, ent
->ExternalID
);
1021 xmlBufferWriteChar(buf
, " ");
1022 xmlBufferWriteQuotedString(buf
, ent
->SystemID
);
1024 xmlBufferWriteChar(buf
, " SYSTEM ");
1025 xmlBufferWriteQuotedString(buf
, ent
->SystemID
);
1027 xmlBufferWriteChar(buf
, ">\n");
1029 case XML_EXTERNAL_GENERAL_UNPARSED_ENTITY
:
1030 xmlBufferWriteChar(buf
, "<!ENTITY ");
1031 xmlBufferWriteCHAR(buf
, ent
->name
);
1032 if (ent
->ExternalID
!= NULL
) {
1033 xmlBufferWriteChar(buf
, " PUBLIC ");
1034 xmlBufferWriteQuotedString(buf
, ent
->ExternalID
);
1035 xmlBufferWriteChar(buf
, " ");
1036 xmlBufferWriteQuotedString(buf
, ent
->SystemID
);
1038 xmlBufferWriteChar(buf
, " SYSTEM ");
1039 xmlBufferWriteQuotedString(buf
, ent
->SystemID
);
1041 if (ent
->content
!= NULL
) { /* Should be true ! */
1042 xmlBufferWriteChar(buf
, " NDATA ");
1043 if (ent
->orig
!= NULL
)
1044 xmlBufferWriteCHAR(buf
, ent
->orig
);
1046 xmlBufferWriteCHAR(buf
, ent
->content
);
1048 xmlBufferWriteChar(buf
, ">\n");
1050 case XML_INTERNAL_PARAMETER_ENTITY
:
1051 xmlBufferWriteChar(buf
, "<!ENTITY % ");
1052 xmlBufferWriteCHAR(buf
, ent
->name
);
1053 xmlBufferWriteChar(buf
, " ");
1054 if (ent
->orig
== NULL
)
1055 xmlDumpEntityContent(buf
, ent
->content
);
1057 xmlBufferWriteQuotedString(buf
, ent
->orig
);
1058 xmlBufferWriteChar(buf
, ">\n");
1060 case XML_EXTERNAL_PARAMETER_ENTITY
:
1061 xmlBufferWriteChar(buf
, "<!ENTITY % ");
1062 xmlBufferWriteCHAR(buf
, ent
->name
);
1063 if (ent
->ExternalID
!= NULL
) {
1064 xmlBufferWriteChar(buf
, " PUBLIC ");
1065 xmlBufferWriteQuotedString(buf
, ent
->ExternalID
);
1066 xmlBufferWriteChar(buf
, " ");
1067 xmlBufferWriteQuotedString(buf
, ent
->SystemID
);
1069 xmlBufferWriteChar(buf
, " SYSTEM ");
1070 xmlBufferWriteQuotedString(buf
, ent
->SystemID
);
1072 xmlBufferWriteChar(buf
, ">\n");
1075 xmlEntitiesErr(XML_DTD_UNKNOWN_ENTITY
,
1076 "xmlDumpEntitiesDecl: internal: unknown type entity type");
1081 * xmlDumpEntityDeclScan:
1082 * @ent: An entity table
1083 * @buf: An XML buffer.
1085 * When using the hash table scan function, arguments need to be reversed
1088 xmlDumpEntityDeclScan(xmlEntityPtr ent
, xmlBufferPtr buf
) {
1089 xmlDumpEntityDecl(buf
, ent
);
1093 * xmlDumpEntitiesTable:
1094 * @buf: An XML buffer.
1095 * @table: An entity table
1097 * This will dump the content of the entity table as an XML DTD definition
1100 xmlDumpEntitiesTable(xmlBufferPtr buf
, xmlEntitiesTablePtr table
) {
1101 xmlHashScan(table
, (xmlHashScanner
)xmlDumpEntityDeclScan
, buf
);
1103 #endif /* LIBXML_OUTPUT_ENABLED */
1104 #define bottom_entities
1105 #include "elfgcchack.h"