In the SAX specification, EntityResolver is the interface used by the
parser to translate a reference to an external file into an actual
stream of bytes. The reference could be an external entity defined in
the DTD, but also the declaration of an external DTD or of an XMLSchema
referenced by the stream of bytes that the parser is currently processing.
If an entity resolver is not in place, there is a default behaviour that
kicks in to try to find out such file: take the path of the current
entity, and concatenate it with the name of the entity. If the current
entity doesn't have a name (e.g. if you are parsing a stream of bytes
you provided, instead of using a file as source), the current directory
is used.
So, if you see a different behaviour between two programs the options are:
1) schema validation is turned off -> this avoids trying to load an xml
schema that is referenced
2) the schema file is by chance in the same directory of the file being
parsed, or in the current directory
3) the schema you are referencing doesn't have a suggested location, and
the URL of the namespace is the location where the schema is made available
Alberto
Il 23/05/13 17:52, Kelly Beard ha scritto:
Ideally what I think I want to do is get rid of needing the thing in the
first place. I don't use DTDs, I don't use any custom entities,. therefore
I should not need this whole EntityResolver mess. Anyway, I do have a
program that I wrote that validates an XML against a schema and prints out
what it is doing via the callbacks. This program doesn't require me
loading any EntityResolver object into the parser, so what is really
different about it vs. the other code? Here is the basic steps I do in it
to set up the SAX2 parser. It is only marginally different than what I do
in my production programs:
try {
XMLPlatformUtils::Initialize();
}
catch (const XMLException& toCatch) {
char* message = XMLString::transcode(toCatch.getMessage());
cerr << "Error during initialization! :\n";
cerr << "Exception message is: \n" << message << "\n";
XMLString::release(&message);
return 1;
}
SAX2XMLReader* parser = XMLReaderFactory::createXMLReader();
parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
parser->setFeature(XMLUni::fgXercesDynamic, true);
parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, true); // optional
parser->setFeature(XMLUni::fgXercesValidationErrorAsFatal, true);
parser->setValidationConstraintFatal(true);
parser->setExitOnFirstFatalError(true);
MySAX2Handler* defaultHandler = new MySAX2Handler();
parser->setContentHandler(defaultHandler);
parser->setErrorHandler(defaultHandler);
I can post this whole program as an attachment if anyone is interested.
On Wed, May 22, 2013 at 4:06 PM, Kelly Beard <kenverybigl...@gmail.com>wrote:
I don't understand entities and why I need to extend class EntityResolver.
Based on the documentation, it seems like I don't need to go through this
step. When I read about entities, I see the usual &apos, &, ", et
al. I don't have any custom entities.
I have an XML document, call it authNotify. I use an XSD (authNotify.xsd)
& SAX2 to validate this document. If I don't call setEntityResolver() in
my code, the parser bombs with a message like the following:
Warning at file , line=0, column=0, An exception occurred!
Type:RuntimeException, Message:Warning: The primary document entity could
not be opened. Id=/tmp/authNotify.xsd
So, based on my understanding of how to set up SAX2, my basic flow is to
do something like so:
XMLPlatformUtils::Initialize();
parser = XMLReaderFactory::createXMLReader();
parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
parser->setFeature(XMLUni::fgXercesDynamic, true);
parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
parser->setFeature(XMLUni::fgXercesValidationErrorAsFatal, false);
defaultHandler = new AuthNotifyHandler();
AuthNotifyResolver *authResolver = new AuthNotifyResolver();
parser->setContentHandler(defaultHandler);
parser->setErrorHandler(defaultHandler);
parser->setEntityResolver(authResolver);
Where AuthNotifyHandler is derived from DefaultHandler and
AuthNotifyResolver is derived from EntityResolver.
When resolveEntity() is called, the parameters publicID and systemID are
both set to authNotify.xsd. In the traditional compareString(), if I
change the comparison to return 0, all heck breaks loose.
I don't know if I'm doing something wrong in the parser set-up, or if
something is wrong elsewhere.
So, lost here. Any help?
--
Kelly Beard