Fixed a problem when dealing with "xsi:schemaLocation"

This commit is contained in:
Zane U. Ji 2014-06-02 20:09:16 +08:00
parent c61ceec6d0
commit 3993927d66
2 changed files with 99 additions and 90 deletions

View File

@ -18,6 +18,7 @@
*/
#include <wx/wx.h>
#include <wx/tokenzr.h>
#include <stdexcept>
#include "xmlpromptgenerator.h"
#include "xmlencodinghandler.h"
@ -285,21 +286,14 @@ void XMLCALL XmlPromptGenerator::attlistdeclhandler (
XML_StopParser ( d->p, false );
}
int XMLCALL XmlPromptGenerator::externalentityrefhandler (
XML_Parser p,
const XML_Char *context,
const XML_Char *base,
const XML_Char *systemId,
const XML_Char *publicId )
int XmlPromptGenerator::parseGrammar
( PromptGeneratorData *d
, const wxString &publicId
, const wxString &systemId
, const wxString &baseFileName
, Grammar::GrammarType type
)
{
// arg is set to user data in c'tor
XmlPromptGenerator *pThis = ( XmlPromptGenerator * ) p;
PromptGeneratorData *d = pThis->d.get();
// Either EXPAT or Xerces-C++ is capable of parsing DTDs. The advantage
// of Xerces-C++ is that it can access DTDs that are on the internet.
#if !PREFER_EXPAT_TO_XERCES_C
XercesDOMParser parser;
parser.setDoNamespaces ( true );
parser.setDoSchema ( true );
@ -310,23 +304,20 @@ int XMLCALL XmlPromptGenerator::externalentityrefhandler (
parser.setErrorHandler ( &handler );
parser.setEntityResolver ( &catalogResolver );
wxString widePublicId = wxString::FromUTF8 ( publicId );
wxString wideSystemId = wxString::FromUTF8 ( systemId );
Grammar *rootGrammar;
try {
std::auto_ptr<InputSource> source ( WrapXerces::resolveEntity
( widePublicId , wideSystemId , d->basePath ) );
( publicId , systemId , baseFileName ) );
if ( !source.get() )
{
wxLogError ( _T("Cann't open '%s'"), wideSystemId.c_str() );
wxLogError ( _T("Cann't open '%s'"), systemId.c_str() );
return XML_STATUS_ERROR;
}
if ( pThis->TestDestroy() )
if ( TestDestroy() )
return XML_STATUS_ERROR;
rootGrammar = parser.loadGrammar ( *source, Grammar::DTDGrammarType );
rootGrammar = parser.loadGrammar ( *source, type );
if ( !rootGrammar )
return XML_STATUS_ERROR;
}
@ -349,30 +340,81 @@ int XMLCALL XmlPromptGenerator::externalentityrefhandler (
}
catch (...)
{
wxLogError ( _T ( "Failed to load: %s %s"), widePublicId.c_str()
, wideSystemId.c_str() );
wxLogError ( _T ( "Failed to load: %s %s"), publicId.c_str()
, systemId.c_str() );
return XML_STATUS_ERROR;
}
wxASSERT ( rootGrammar->getGrammarType() == type );
if ( type == Grammar::DTDGrammarType )
{
DTDGrammar* grammar = ( DTDGrammar* ) rootGrammar;
NameIdPoolEnumerator<DTDElementDecl> elemEnum = grammar->getElemEnumerator();
NameIdPoolEnumerator<DTDElementDecl> elemEnum
= grammar->getElemEnumerator();
SubstitutionMap substitutions;
while ( elemEnum.hasMoreElements() && !pThis->TestDestroy() )
while ( elemEnum.hasMoreElements() && !TestDestroy() )
{
const DTDElementDecl& curElem = elemEnum.nextElement();
pThis->buildElementPrompt ( d, &curElem, substitutions );
buildElementPrompt ( d, &curElem, substitutions );
}
NameIdPoolEnumerator<DTDEntityDecl>
entityEnum = grammar->getEntityEnumerator();
while ( entityEnum.hasMoreElements() && !pThis->TestDestroy() )
while ( entityEnum.hasMoreElements() && !TestDestroy() )
{
const DTDEntityDecl &entity = entityEnum.nextElement();
d->entitySet.insert ( WrapXerces::toString ( entity.getName() ) );
}
}
else
{
wxASSERT ( type == Grammar::SchemaGrammarType );
return pThis->TestDestroy() ? XML_STATUS_ERROR : XML_STATUS_OK;
SchemaGrammar* grammar = ( SchemaGrammar* ) rootGrammar;
RefHash3KeysIdPoolEnumerator<SchemaElementDecl> elemEnum = grammar->getElemEnumerator();
if ( !elemEnum.hasMoreElements() )
{
return XML_STATUS_ERROR;
}
SubstitutionMap substitutions;
buildSubstitutionMap ( substitutions, *grammar );
while ( elemEnum.hasMoreElements() && !TestDestroy() )
{
const SchemaElementDecl& curElem = elemEnum.nextElement();
buildElementPrompt ( d, &curElem, substitutions );
}
}
return TestDestroy() ? XML_STATUS_ERROR : XML_STATUS_OK;
}
int XMLCALL XmlPromptGenerator::externalentityrefhandler (
XML_Parser p,
const XML_Char *context,
const XML_Char *base,
const XML_Char *systemId,
const XML_Char *publicId )
{
// arg is set to user data in c'tor
XmlPromptGenerator *pThis = ( XmlPromptGenerator * ) p;
PromptGeneratorData *d = pThis->d.get();
// Either EXPAT or Xerces-C++ is capable of parsing DTDs. The advantage
// of Xerces-C++ is that it can access DTDs that are on the internet.
#if !PREFER_EXPAT_TO_XERCES_C
return pThis->parseGrammar
( d
, wxString::FromUTF8 ( publicId )
, wxString::FromUTF8 ( systemId )
, d->basePath
, Grammar::DTDGrammarType
);
#else // !PREFER_EXPAT_TO_XERCES_C
@ -476,75 +518,36 @@ void XmlPromptGenerator::handleSchema (
{
if ( !d->isRootElement )
return;
wxString publicId, systemId;
// first check for XML Schema association
const char **schemaAttr = ( const char ** ) attr; // now redundant; could use attr
wxString path;
for ( ; *schemaAttr; schemaAttr += 2 )
{
// no namespace
if ( !strcmp ( *schemaAttr, "xsi:noNamespaceSchemaLocation" ) )
{
path = wxString ( schemaAttr[1], wxConvUTF8 );
systemId = wxString ( schemaAttr[1], wxConvUTF8 );
break;
}
// with namespace -- check if this works
else if ( !strcmp ( *schemaAttr, "xsi:schemaLocation" ) )
{
const char *searchIterator = * ( schemaAttr + 1 );
while ( *searchIterator && *searchIterator != ' ' && *searchIterator != '\t' && *searchIterator != '\n' )
searchIterator++;
if ( *searchIterator )
{
path = wxString ( searchIterator + 1, wxConvUTF8 );
break;
}
}
}
if ( path.empty() )
{
wxStringTokenizer tokens ( wxString ( schemaAttr[1], wxConvUTF8 ) );
size_t count = tokens.CountTokens();
if ( count < 2 )
return;
// TODO: Support multiple schemas
publicId = tokens.GetNextToken();
systemId = tokens.GetNextToken();
}
}
wxString schemaPath = PathResolver::run ( path, ( d->auxPath.empty() ) ? d->basePath : d->auxPath);
std::auto_ptr<XercesDOMParser> parser ( new XercesDOMParser() );
parser->setDoNamespaces ( true );
parser->setDoSchema ( true );
parser->setValidationSchemaFullChecking ( true );
if ( TestDestroy() )
{
XML_StopParser ( d->p, false );
int ret = parseGrammar ( d, publicId, systemId, d->basePath
, Grammar::SchemaGrammarType );
if ( ret != XML_STATUS_OK )
return;
}
Grammar *rootGrammar = parser->loadGrammar
( ( const XMLCh * ) WrapXerces::toString ( schemaPath ).GetData()
, Grammar::SchemaGrammarType
);
if ( !rootGrammar )
{
return;
}
SchemaGrammar* grammar = ( SchemaGrammar* ) rootGrammar;
RefHash3KeysIdPoolEnumerator<SchemaElementDecl> elemEnum = grammar->getElemEnumerator();
if ( !elemEnum.hasMoreElements() )
{
return;
}
SubstitutionMap substitutions;
buildSubstitutionMap ( substitutions, *grammar );
while ( elemEnum.hasMoreElements() && !TestDestroy() )
{
const SchemaElementDecl& curElem = elemEnum.nextElement();
buildElementPrompt ( d, &curElem, substitutions );
}
d->grammarFound = true;
XML_StopParser ( d->p, false );

View File

@ -131,6 +131,12 @@ class XmlPromptGenerator : public WrapExpat, public wxThread
const XML_Char *att_type,
const XML_Char *dflt,
int isrequired );
int parseGrammar (
PromptGeneratorData *d,
const wxString &publicId,
const wxString &systemId,
const wxString &baseFileName,
xercesc::Grammar::GrammarType type );
static int XMLCALL externalentityrefhandler (
XML_Parser p,
const XML_Char *context,