[Expat-discuss] Parsing External Entities

Carlos Pereira carlos at pehoe.civil.ist.utl.pt
Fri Jan 17 15:09:06 EST 2003


>> I have been using external entities in my code with Expat 1.95.2,
>> using XML_ExternalEntityParserCreate and XML_ParserFree etc. without
>> any problem. I have files that include other files which in turn
>> include other files, without any obvious nesting limit, and everything
>> works just fine, with this essentially recursive code.

>Did you use nested parameter entities a lot?

No, not really, I did it for the sake of elegance and completeness,
so I can write in the manual that users can use an unlimited number
of nested levels when including files, though they are discouraged
of actually doing it.

Although I wrote this code about one year, so some details
may be missing from my memory recollection, I think that
using External Entities in Expat is easy, as long as people
grasp a few notions, and this should be valid for every 
version of Expat:

When entering a new file (external entity), a
new parser must be allocated, without destroying 
the previous parsers; when leaving that file
the parser must be removed, forget about malloc
and such, you must use only the functions
provided by Expat only!

This is copy and paste from my own (recursive) code:

-----------------------------------------------
gml->parser = XML_ExternalEntityParserCreate (parser, context, NULL);
gml->valid = static_import (system_id, gml);
XML_ParserFree(gml->parser);
-----------------------------------------------

So if you have, say, 5 nested levels, you will have
this structure:

parser1 = XML_ExternalEntityParserCreate
parse_file1(parser1);
...
	parser2 = XML_ExternalEntityParserCreate
	parse_file2(parser2);
	...
		parser3 = XML_ExternalEntityParserCreate
		parse_file3(parser3);
		...
			parser4 = XML_ExternalEntityParserCreate
			parse_file4(parser4);
			...
				parser5 = XML_ExternalEntityParserCreate
				parse_file5(parser5);
				...
				XML_ParserFree(parser5);
			XML_ParserFree(parser4);
		XML_ParserFree(parser3);
	XML_ParserFree(parser2);
XML_ParserFree(parser1);

Of course, the only way to do this with elegance
and generality is to make the code recursive, so
there is one and only one function that creates and 
destroys parsers, that is called recursively, everytime
a new external entity is found by Expat, this way it is 
easy to provide an unlimited number of nested levels.

If someone actually wants to implement this and is still 
having trouble after this explanation, I offer to help.

Carlos




More information about the Expat-discuss mailing list