Xerces-C SAX2 loadGrammar DTD

D

delphin.lecucq

Hello,

I want to load a grammar which doesnt not come with a DOCTYPE
declaration,

I tried with those lines, and it doesn't work

parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, false)

// Load grammar and cache it
parser->loadGrammar(/path/to/my/file.dtd", Grammar::DTDGrammarType,
true);
// enable grammar reuse
parser->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true);

Actually, If the <! DOCTYPE validation SYSTEM "file.dtd" > declaration
is present, it does the validation with the file in the current path,
not the one I loaded in cache.
if the <! DOCTYPE ... > is not there, it does not validate.

for example, it would be nice if it were possible to override a DOCTYPE
declaration

Thank You,
Delphin
 
B

Boris Kolpackov

Hi Delphin,

Hello,

I want to load a grammar which doesnt not come with a DOCTYPE
declaration,

I tried with those lines, and it doesn't work

parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, false)

What happens if you also add these?

parser->setFeature(XMLUni::fgXercesDynamic, false);
parser->setFeature(XMLUni::fgXercesSchema, true);
parser->setFeature(XMLUni::fgXercesSchemaFullChecking, true);

// Load grammar and cache it
parser->loadGrammar(/path/to/my/file.dtd", Grammar::DTDGrammarType, true);
// enable grammar reuse
parser->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true);

Actually, If the <! DOCTYPE validation SYSTEM "file.dtd" > declaration
is present, it does the validation with the file in the current path,
not the one I loaded in cache.
if the <! DOCTYPE ... > is not there, it does not validate.

for example, it would be nice if it were possible to override a DOCTYPE
declaration

My understanding is that the loadGrammar works as a proxy to entity
resolver. In other words, when the parser sees

<! DOCTYPE validation SYSTEM "file.dtd" >

it normally calls entity resolver to locate file.dtd but before that it
consults the grammar cache to see if this grammar was already loaded.
So I think the reason why if does not work is because without the
above DOCTYPE there is nothing in the document that specifies against
which schema we should validate (note that nothing prevents you from
caching several unrelated schemas). In case of XML Schema, there is
the fgXercesSchemaExternalSchemaLocation property that allows you
to specify schemas for namespaces and thus trigger validation if
a document refers to one of those namespaces. In case of DTD, I don't
see any similar mechanism. You may also find the following article
interesting:

http://www-128.ibm.com/developerworks/webservices/library/x-xsdxerc.html

hth,
-boris
 
D

delphin.lecucq

Hi Boris!

My understanding is that the loadGrammar works as a proxy to entity
resolver. In other words, when the parser sees

it normally calls entity resolver to locate file.dtd but before that it
consults the grammar cache to see if this grammar was already loaded.
So I think the reason why if does not work is because without the
above DOCTYPE there is nothing in the document that specifies against
which schema we should validate (note that nothing prevents you from
caching several unrelated schemas). In case of XML Schema, there is
the fgXercesSchemaExternalSchemaLocation property that allows you
to specify schemas for namespaces and thus trigger validation if
a document refers to one of those namespaces. In case of DTD, I don't
see any similar mechanism. You may also find the following article
interesting:

hth,
-boris
--
Boris Kolpackov
Code Synthesis Tools CC
http://www.codesynthesis.com
Open-Source, Cross-Platform C++ XML Data Binding

Thank you for your help, the article was interesting, but I wanted to
use DTD rather XSD because it is more simple and it is sufficient for
my project.
I finaly choosed to pass the DTD file name in the XML file this way :

<! DOCTYPE rootElement SYSTEM "relativeFileName.dtd" >

I have overloaded MyHandler::resolveEntity to return a
LocalFileInputSource using the application specific basePath and the
relativeFileName given in the XML Document.

//dtdPath is a member of MySAX2Handler that I init before to parse
void MySAX2Handler::setDTDPath(const char* dtdPath_) { dtdPath =
dtdPath_;}

InputSource* MySAX2Handler::resolveEntity(
const XMLCh *const publicId, const XMLCh *const systemId) {
XMLCh* transcoded = XMLString::transcode(dtdPath);
InputSource* inSrc = new LocalFileInputSource(transcoded,
systemId,
XMLPlatformUtils::fgMemoryManager);
XMLString::release(&transcoded);
return inSrc;
}

This way it works, but it does not seem to be the perfect solution.

Delphin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,002
Messages
2,570,258
Members
46,857
Latest member
ArleenWill

Latest Threads

Top