Enabled XML Schema-based insertion helpers and validation-as-you-type.

This commit is contained in:
Gerald Schmidt 2008-01-06 22:14:06 +00:00
parent 55d20854af
commit 4c4536cdb4
4 changed files with 447 additions and 283 deletions

View File

@ -1,17 +1,17 @@
/* /*
* Copyright 2005-2007 Gerald Schmidt. * Copyright 2005-2007 Gerald Schmidt.
* *
* This file is part of Xml Copy Editor. * This file is part of Xml Copy Editor.
* *
* Xml Copy Editor is free software; you can redistribute it and/or modify * Xml Copy Editor is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License. * the Free Software Foundation; version 2 of the License.
* *
* Xml Copy Editor is distributed in the hope that it will be useful, * Xml Copy Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Xml Copy Editor; if not, write to the Free Software * along with Xml Copy Editor; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
@ -25,6 +25,6 @@ std::string CatalogResolver::lookupPublicId (
const std::string& publicId, const std::string& publicId,
const std::string& catalogPath ) const std::string& catalogPath )
{ {
std::auto_ptr<WrapLibxml> libxml ( new WrapLibxml ( false, catalogPath ) ); std::auto_ptr<WrapLibxml> libxml ( new WrapLibxml ( false, catalogPath ) );
return libxml->lookupPublicId ( publicId ); return libxml->lookupPublicId ( publicId );
} }

View File

@ -1,17 +1,17 @@
/* /*
* Copyright 2005-2007 Gerald Schmidt. * Copyright 2005-2007 Gerald Schmidt.
* *
* This file is part of Xml Copy Editor. * This file is part of Xml Copy Editor.
* *
* Xml Copy Editor is free software; you can redistribute it and/or modify * Xml Copy Editor is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License. * the Free Software Foundation; version 2 of the License.
* *
* Xml Copy Editor is distributed in the hope that it will be useful, * Xml Copy Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Xml Copy Editor; if not, write to the Free Software * along with Xml Copy Editor; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

View File

@ -1,17 +1,17 @@
/* /*
* Copyright 2005-2007 Gerald Schmidt. * Copyright 2005-2007 Gerald Schmidt.
* *
* This file is part of Xml Copy Editor. * This file is part of Xml Copy Editor.
* *
* Xml Copy Editor is free software; you can redistribute it and/or modify * Xml Copy Editor is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License. * the Free Software Foundation; version 2 of the License.
* *
* Xml Copy Editor is distributed in the hope that it will be useful, * Xml Copy Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Xml Copy Editor; if not, write to the Free Software * along with Xml Copy Editor; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
@ -29,30 +29,45 @@
#include "catalogresolver.h" #include "catalogresolver.h"
#include "xmlschemaparser.h" #include "xmlschemaparser.h"
// Xerces-C req'd for Schema parsing
#define XERCES_TMPLSINC
#include <xercesc/util/NameIdPool.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/framework/XMLValidator.hpp>
#include <xercesc/parsers/SAXParser.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/validators/schema/SchemaValidator.hpp>
#include <xercesc/validators/common/ContentSpecNode.hpp>
#include <xercesc/validators/schema/SchemaSymbols.hpp>
using namespace xercesc;
XmlPromptGenerator::XmlPromptGenerator ( XmlPromptGenerator::XmlPromptGenerator (
const std::string& catalogPath, const std::string& catalogPath,
const std::string& basePath, const std::string& basePath,
const std::string& auxPath ) : d ( new PromptGeneratorData() ) const std::string& auxPath ) : d ( new PromptGeneratorData() )
{ {
XML_SetUserData ( p, d.get() ); XML_SetUserData ( p, d.get() );
d->p = p; d->p = p;
d->catalogPath = catalogPath; d->catalogPath = catalogPath;
d->auxPath = auxPath; d->auxPath = auxPath;
d->elementDeclRecurseLevel = 0; d->elementDeclRecurseLevel = 0;
d->rootElement = true; d->isRootElement = true;
d->dtdFound = false; d->grammarFound = false;
XML_SetParamEntityParsing ( p, XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE ); d->attributeValueCutoff = 12; // this prevents enums being stored in their thousands
XML_SetElementHandler ( p, starthandler, endhandler ); XML_SetParamEntityParsing ( p, XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE );
XML_SetDoctypeDeclHandler ( p, doctypedeclstarthandler, doctypedeclendhandler ); XML_SetElementHandler ( p, starthandler, endhandler );
XML_SetElementDeclHandler ( p, elementdeclhandler ); XML_SetDoctypeDeclHandler ( p, doctypedeclstarthandler, doctypedeclendhandler );
XML_SetAttlistDeclHandler ( p, attlistdeclhandler ); XML_SetElementDeclHandler ( p, elementdeclhandler );
XML_SetEntityDeclHandler ( p, entitydeclhandler ); XML_SetAttlistDeclHandler ( p, attlistdeclhandler );
XML_SetExternalEntityRefHandlerArg ( p, d.get() ); XML_SetEntityDeclHandler ( p, entitydeclhandler );
XML_SetExternalEntityRefHandler ( p, externalentityrefhandler ); XML_SetExternalEntityRefHandlerArg ( p, d.get() );
XML_SetBase ( p, basePath.c_str() ); XML_SetExternalEntityRefHandler ( p, externalentityrefhandler );
XML_SetBase ( p, basePath.c_str() );
if ( !auxPath.empty() ) if ( !auxPath.empty() )
XML_UseForeignDTD ( p, true ); XML_UseForeignDTD ( p, true );
} }
XmlPromptGenerator::~XmlPromptGenerator() XmlPromptGenerator::~XmlPromptGenerator()
@ -63,96 +78,93 @@ void XMLCALL XmlPromptGenerator::starthandler (
const XML_Char *el, const XML_Char *el,
const XML_Char **attr ) const XML_Char **attr )
{ {
PromptGeneratorData *d; PromptGeneratorData *d;
d = ( PromptGeneratorData * ) data; d = ( PromptGeneratorData * ) data;
d->push ( el ); if (d->isRootElement)
{
d->rootElement = el;
handleSchema ( d, el, attr );
d->isRootElement = false;
if ( ! (d->elementMap.empty() ) )//if ( d->elementMap.size() == 1) // must be 1 for success
{
d->grammarFound = true;
XML_StopParser ( d->p, false );
return;
}
}
std::string parent, element; d->push ( el );
parent = d->getParent();
element = el;
// update elementMap std::string parent, element;
if ( d->elementMap.find ( parent ) == d->elementMap.end() ) parent = d->getParent();
{ element = el;
std::set<std::string> childSet;
childSet.insert ( element );
d->elementMap.insert ( make_pair ( parent, childSet ) );
}
else
d->elementMap[parent].insert ( element );
std::string attributeName, attributeValue; // update elementMap
if ( d->elementMap.find ( parent ) == d->elementMap.end() )
{
std::set<std::string> childSet;
childSet.insert ( element );
d->elementMap.insert ( make_pair ( parent, childSet ) );
}
else
d->elementMap[parent].insert ( element );
// update attributeMap std::string attributeName, attributeValue;
// case 1: element unknown, no attributes
if ( ! ( *attr ) && d->attributeMap.find ( element ) == d->attributeMap.end() )
{
std::map<std::string, std::set<std::string> > currentAttributeMap;
d->attributeMap.insert ( make_pair ( element, currentAttributeMap ) );
}
for ( ; *attr; attr += 2 ) // update attributeMap
{ // case 1: element unknown, no attributes
attributeName = *attr; if ( ! ( *attr ) && d->attributeMap.find ( element ) == d->attributeMap.end() )
attributeValue = * ( attr + 1 ); {
std::map<std::string, std::set<std::string> > currentAttributeMap;
d->attributeMap.insert ( make_pair ( element, currentAttributeMap ) );
}
d->attributeMap[element][attributeName].insert ( attributeValue ); for ( ; *attr; attr += 2 )
{
attributeName = *attr;
attributeValue = * ( attr + 1 );
/* if (d->attributeMap[element][attributeName].size() < d->attributeValueCutoff)
// TBD: may not be xsi: check for http://www.w3.org/2001/XMLSchema-instance d->attributeMap[element][attributeName].insert ( attributeValue );
while (d->rootElement && strstr((const char *)attr, "xsi:noNamespaceSchemaLocation")) }
{
std::string schemaPath = PathResolver::run(attributeValue, d->auxPath);
std::string buffer;
if (!ReadFile::run(schemaPath, buffer))
break;
XmlSchemaParser xsp(d, true);
if (!xsp.parse(buffer))
break;
XML_StopParser(d->p, false);
return;
}
*/
}
d->rootElement = false;
} }
void XMLCALL XmlPromptGenerator::endhandler ( void *data, const XML_Char *el ) void XMLCALL XmlPromptGenerator::endhandler ( void *data, const XML_Char *el )
{ {
PromptGeneratorData *d; PromptGeneratorData *d;
d = ( PromptGeneratorData * ) data; d = ( PromptGeneratorData * ) data;
d->pop(); d->pop();
} }
bool XmlPromptGenerator::getDtdFound() bool XmlPromptGenerator::getGrammarFound()
{ {
return d->dtdFound; return d->grammarFound;
} }
void XmlPromptGenerator::getAttributeMap ( void XmlPromptGenerator::getAttributeMap (
std::map<std::string, std::map<std::string, std::set<std::string> > > std::map<std::string, std::map<std::string, std::set<std::string> > >
&attributeMap ) &attributeMap )
{ {
attributeMap = d->attributeMap; attributeMap = d->attributeMap;
} }
void XmlPromptGenerator::getRequiredAttributeMap ( void XmlPromptGenerator::getRequiredAttributeMap (
std::map<std::string, std::set<std::string> >& requiredAttributeMap ) std::map<std::string, std::set<std::string> >& requiredAttributeMap )
{ {
requiredAttributeMap = d->requiredAttributeMap; requiredAttributeMap = d->requiredAttributeMap;
} }
void XmlPromptGenerator::getElementMap ( void XmlPromptGenerator::getElementMap (
std::map<std::string, std::set<std::string> > &elementMap ) std::map<std::string, std::set<std::string> > &elementMap )
{ {
elementMap = d->elementMap; elementMap = d->elementMap;
} }
void XmlPromptGenerator::getEntitySet ( void XmlPromptGenerator::getEntitySet (
std::set<std::string> &entitySet ) std::set<std::string> &entitySet )
{ {
entitySet = d->entitySet; entitySet = d->entitySet;
} }
// handlers for DOCTYPE handling // handlers for DOCTYPE handling
@ -164,19 +176,19 @@ void XMLCALL XmlPromptGenerator::doctypedeclstarthandler (
const XML_Char *pubid, const XML_Char *pubid,
int has_internal_subset ) int has_internal_subset )
{ {
PromptGeneratorData *d; PromptGeneratorData *d;
d = ( PromptGeneratorData * ) data; d = ( PromptGeneratorData * ) data;
} }
void XMLCALL XmlPromptGenerator::doctypedeclendhandler ( void *data ) void XMLCALL XmlPromptGenerator::doctypedeclendhandler ( void *data )
{ {
PromptGeneratorData *d; PromptGeneratorData *d;
d = ( PromptGeneratorData * ) data; d = ( PromptGeneratorData * ) data;
if ( !d->elementMap.empty() ) if ( !d->elementMap.empty() )
{ {
d->dtdFound = true; d->grammarFound = true;
XML_StopParser ( d->p, false ); XML_StopParser ( d->p, false ); // experimental
} }
} }
void XMLCALL XmlPromptGenerator::elementdeclhandler ( void XMLCALL XmlPromptGenerator::elementdeclhandler (
@ -184,33 +196,33 @@ void XMLCALL XmlPromptGenerator::elementdeclhandler (
const XML_Char *name, const XML_Char *name,
XML_Content *model ) XML_Content *model )
{ {
PromptGeneratorData *d; PromptGeneratorData *d;
d = ( PromptGeneratorData * ) data; d = ( PromptGeneratorData * ) data;
d->elementDeclRecurseLevel += 1; d->elementDeclRecurseLevel += 1;
std::string myElement = name; std::string myElement = name;
unsigned num = model->numchildren; unsigned num = model->numchildren;
for ( unsigned i = 0; i < num; i++ ) for ( unsigned i = 0; i < num; i++ )
{ {
XML_Content myContent = model->children[i]; XML_Content myContent = model->children[i];
XML_Char *myName = myContent.name; XML_Char *myName = myContent.name;
if ( myName ) if ( myName )
d->elementMap[myElement].insert ( ( const char * ) myName ); d->elementMap[myElement].insert ( ( const char * ) myName );
else else
{ {
// recurse // recurse
XmlPromptGenerator::elementdeclhandler ( ( void * ) d, name, &myContent ); XmlPromptGenerator::elementdeclhandler ( ( void * ) d, name, &myContent );
} }
} }
d->elementDeclRecurseLevel -= 1; d->elementDeclRecurseLevel -= 1;
// only one call to XML_FreeContentModel per content tree // only one call to XML_FreeContentModel per content tree
if ( d->elementDeclRecurseLevel == 0 ) if ( d->elementDeclRecurseLevel == 0 )
{ {
XML_FreeContentModel ( d->p, model ); XML_FreeContentModel ( d->p, model );
} }
} }
void XMLCALL XmlPromptGenerator::attlistdeclhandler ( void XMLCALL XmlPromptGenerator::attlistdeclhandler (
@ -221,36 +233,36 @@ void XMLCALL XmlPromptGenerator::attlistdeclhandler (
const XML_Char *dflt, const XML_Char *dflt,
int isrequired ) int isrequired )
{ {
PromptGeneratorData *d; PromptGeneratorData *d;
d = ( PromptGeneratorData * ) data; d = ( PromptGeneratorData * ) data;
std::set<std::string> attributeValues; std::set<std::string> attributeValues;
if ( *att_type == '(' ) // change to exclude _known_ identifiers? if ( *att_type == '(' ) // change to exclude _known_ identifiers?
{ {
size_t len; size_t len;
char *s, *word; char *s, *word;
s = ( char * ) att_type; s = ( char * ) att_type;
while ( ( word = GetWord::run ( &s, &len ) ) != NULL ) while ( ( word = GetWord::run ( &s, &len ) ) != NULL )
{ {
std::string currentValue ( word, len ); std::string currentValue ( word, len );
attributeValues.insert ( currentValue ); attributeValues.insert ( currentValue );
} }
} }
if ( attributeValues.empty() ) if ( attributeValues.empty() )
{ {
d->attributeMap[elname][attname].insert ( "" ); d->attributeMap[elname][attname].insert ( "" );
return; return;
} }
std::set<std::string>::iterator it; std::set<std::string>::iterator it;
for ( it = attributeValues.begin(); it != attributeValues.end(); it++ ) for ( it = attributeValues.begin(); it != attributeValues.end(); it++ )
d->attributeMap[elname][attname].insert ( *it ); d->attributeMap[elname][attname].insert ( *it );
if ( isrequired ) if ( isrequired )
{ {
d->requiredAttributeMap[elname].insert ( attname ); d->requiredAttributeMap[elname].insert ( attname );
} }
} }
int XMLCALL XmlPromptGenerator::externalentityrefhandler ( int XMLCALL XmlPromptGenerator::externalentityrefhandler (
@ -260,65 +272,70 @@ int XMLCALL XmlPromptGenerator::externalentityrefhandler (
const XML_Char *systemId, const XML_Char *systemId,
const XML_Char *publicId ) const XML_Char *publicId )
{ {
PromptGeneratorData *d; PromptGeneratorData *d;
d = ( PromptGeneratorData * ) p; // arg is set to user data in c'tor d = ( PromptGeneratorData * ) p; // arg is set to user data in c'tor
std::string buffer; std::string buffer;
// auxPath req'd? // auxPath req'd?
if ( !systemId && !publicId ) if ( !systemId && !publicId )
{ {
ReadFile::run ( d->auxPath, buffer ); ReadFile::run ( d->auxPath, buffer );
if ( buffer.empty() ) if ( buffer.empty() )
{ {
return false; return false;
} }
std::string encoding = XmlEncodingHandler::get ( buffer ); std::string encoding = XmlEncodingHandler::get ( buffer );
XML_Parser dtdParser = XML_ExternalEntityParserCreate ( d->p, context, encoding.c_str() ); XML_Parser dtdParser = XML_ExternalEntityParserCreate ( d->p, context, encoding.c_str() );
if ( !dtdParser ) if ( !dtdParser )
return false; return false;
XML_SetBase ( dtdParser, d->auxPath.c_str() ); XML_SetBase ( dtdParser, d->auxPath.c_str() );
return XML_Parse ( dtdParser, buffer.c_str(), buffer.size(), true ); return XML_Parse ( dtdParser, buffer.c_str(), buffer.size(), true );
} }
std::string stdPublicId; std::string stdPublicId;
if ( publicId ) if ( publicId )
stdPublicId = publicId; stdPublicId = publicId;
std::string stdSystemId = CatalogResolver::lookupPublicId ( stdPublicId, d->catalogPath ); std::string stdSystemId = CatalogResolver::lookupPublicId ( stdPublicId, d->catalogPath );
if ( stdSystemId.empty() && systemId )
stdSystemId = systemId; if ( !stdSystemId.empty() )
{
Replace::run ( stdSystemId, "file://", "", false );
Replace::run ( stdSystemId, "%20", " ", false );
}
else
{
if (systemId )
stdSystemId = systemId;
if ( base )
{
std::string test = PathResolver::run ( stdSystemId, base );
if ( !test.empty() )
{
stdSystemId = test;
}
}
}
if ( !stdSystemId.empty() )
{
ReadFile::run ( stdSystemId, buffer );
}
Replace::run ( stdSystemId, "file:///", "", false ); std::string encoding = XmlEncodingHandler::get ( buffer );
Replace::run ( stdSystemId, "%20", " ", false ); XML_Parser dtdParser = XML_ExternalEntityParserCreate ( d->p, context, encoding.c_str() );
if ( !dtdParser )
return false;
if ( base ) wxString wideName, wideDir;
{ wideName = wxString ( stdSystemId.c_str(), wxConvUTF8, stdSystemId.size() );
std::string test = PathResolver::run ( stdSystemId, base ); wxFileName fn ( wideName );
if ( !test.empty() ) wideDir = fn.GetPath();
{ XML_SetBase ( dtdParser, wideName.mb_str ( wxConvUTF8 ) );
stdSystemId = test;
}
}
if ( !stdSystemId.empty() ) return XML_Parse ( dtdParser, buffer.c_str(), buffer.size(), true );
{
ReadFile::run ( stdSystemId, buffer );
}
std::string encoding = XmlEncodingHandler::get ( buffer );
XML_Parser dtdParser = XML_ExternalEntityParserCreate ( d->p, context, encoding.c_str() );//"UTF-8");
if ( !dtdParser )
return false;
wxString wideName, wideDir;
wideName = wxString ( stdSystemId.c_str(), wxConvUTF8, stdSystemId.size() );
wxFileName fn ( wideName );
wideDir = fn.GetPath();
XML_SetBase ( dtdParser, wideName.mb_str ( wxConvUTF8 ) );
return XML_Parse ( dtdParser, buffer.c_str(), buffer.size(), true );
} }
void XMLCALL XmlPromptGenerator::entitydeclhandler ( void XMLCALL XmlPromptGenerator::entitydeclhandler (
@ -332,16 +349,158 @@ void XMLCALL XmlPromptGenerator::entitydeclhandler (
const XML_Char *publicId, const XML_Char *publicId,
const XML_Char *notationName ) const XML_Char *notationName )
{ {
PromptGeneratorData *d; PromptGeneratorData *d;
d = ( PromptGeneratorData * ) data; // arg is set to user data in c'tor d = ( PromptGeneratorData * ) data; // arg is set to user data in c'tor
if ( if (
entityName && entityName &&
!is_parameter_entity && !is_parameter_entity &&
!systemId && !systemId &&
!publicId && !publicId &&
!notationName ) !notationName )
{ {
d->entitySet.insert ( entityName ); d->entitySet.insert ( entityName );
} }
} }
void XmlPromptGenerator::handleSchema (
PromptGeneratorData *d,
const XML_Char *el,
const XML_Char **attr )
{
// first check for XML Schema association
XML_Char **schemaAttr = ( XML_Char ** ) attr; // now redundant; could use attr
std::string path;
for ( ; d->isRootElement && *schemaAttr; schemaAttr += 2 )
{
// no namespace
if ( !strcmp ( ( const char * ) *schemaAttr, "xsi:noNamespaceSchemaLocation" ) )
{
path = ( const char * ) * ( schemaAttr + 1 );
break;
}
// with namespace -- check if this works
else if ( !strcmp ( ( const char * ) *schemaAttr, "xsi:schemaLocation" ) )
{
char *searchIterator;
for ( searchIterator = ( char * ) * ( schemaAttr + 1 ); *searchIterator && *searchIterator != ' ' && *searchIterator != '\t' && *searchIterator != '\n'; searchIterator++ )
;
if ( *searchIterator )
{
path = ( const char * ) ( searchIterator + 1 );
break;
}
}
}
if ( path.empty() )
{
return;
}
std::string schemaPath = PathResolver::run ( path, d->auxPath );
try
{
XMLPlatformUtils::Initialize();
}
catch ( const XMLException& toCatch )
{
XMLPlatformUtils::Terminate();
return;
}
XercesDOMParser *parser = new XercesDOMParser();
parser->setDoNamespaces ( true );
parser->setDoSchema ( true );
parser->setValidationSchemaFullChecking ( true );
Grammar *rootGrammar = parser->loadGrammar ( schemaPath.c_str(), Grammar::SchemaGrammarType );
if ( !rootGrammar )
{
delete parser;
return;
}
SchemaGrammar* grammar = ( SchemaGrammar* ) rootGrammar;
RefHash3KeysIdPoolEnumerator<SchemaElementDecl> elemEnum = grammar->getElemEnumerator();
if ( !elemEnum.hasMoreElements() )
{
delete grammar;
delete parser;
return;
}
while ( elemEnum.hasMoreElements() )
{
const SchemaElementDecl& curElem = elemEnum.nextElement();
std::string element;
std::set<std::string> children;
const QName *qnm = curElem.getElementName();
if ( qnm )
{
element = XMLString::transcode ( qnm->getRawName() ); // this includes any prefix:localname combinations
}
if ( element.empty() )
continue;
const XMLCh* fmtCntModel = curElem.getFormattedContentModel();
if ( fmtCntModel != NULL ) // tbd: this does not yet pick up prefix:localname combinations
{
size_t len;
char *s, *word;
s = ( char * ) XMLString::transcode ( fmtCntModel );
while ( ( word = GetWord::run ( &s, &len ) ) != NULL )
{
std::string currentValue ( word, len );
if ( currentValue.size() )
children.insert ( currentValue );
}
}
if ( !children.empty() )
d->elementMap.insert ( make_pair ( element, children ) );
// fetch attributes
if ( curElem.hasAttDefs() && ! ( curElem.getAttDefList().isEmpty() ) )
{
std::map<std::string, std::set<std::string> > attributeMap;
XMLAttDefList& attIter = curElem.getAttDefList();
for ( unsigned int i = 0; i < attIter.getAttDefCount(); i++ )
{
std::string attribute, attributeValue;
std::set<std::string> attributeValueSet;
XMLAttDef& attr = attIter.getAttDef ( i );
XMLAttDef::DefAttTypes ty = attr.getDefaultType();
if ( ty == XMLAttDef::Prohibited )
continue;
SchemaAttDef *pAttr = ( SchemaAttDef * ) &attr;
const QName *qnm = pAttr->getAttName();
if ( qnm )
{
attribute = XMLString::transcode ( qnm->getRawName() );
}
if ( attribute.empty() )
continue;
// Value
if ( pAttr->getValue() )
{
attributeValue = XMLString::transcode ( pAttr->getValue() );
attributeValueSet.insert ( attributeValue );
attributeMap.insert ( make_pair ( attribute, attributeValueSet ) );
}
}
if ( !attributeMap.empty() )
d->attributeMap.insert( make_pair ( element, attributeMap ) );
}
}
}

View File

@ -1,17 +1,17 @@
/* /*
* Copyright 2005-2007 Gerald Schmidt. * Copyright 2005-2007 Gerald Schmidt.
* *
* This file is part of Xml Copy Editor. * This file is part of Xml Copy Editor.
* *
* Xml Copy Editor is free software; you can redistribute it and/or modify * Xml Copy Editor is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License. * the Free Software Foundation; version 2 of the License.
* *
* Xml Copy Editor is distributed in the hope that it will be useful, * Xml Copy Editor is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Xml Copy Editor; if not, write to the Free Software * along with Xml Copy Editor; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
@ -28,78 +28,83 @@
struct PromptGeneratorData : public ParserData struct PromptGeneratorData : public ParserData
{ {
std::map<std::string, std::map<std::string, std::set<std::string> > > std::map<std::string, std::map<std::string, std::set<std::string> > >
attributeMap; attributeMap;
std::map<std::string, std::set<std::string> > elementMap; std::map<std::string, std::set<std::string> > elementMap;
std::map<std::string, std::set<std::string> > requiredAttributeMap; std::map<std::string, std::set<std::string> > requiredAttributeMap;
std::set<std::string> entitySet; std::set<std::string> entitySet;
std::string catalogPath, auxPath; std::string catalogPath, auxPath, rootElement;
int elementDeclRecurseLevel; int elementDeclRecurseLevel;
bool rootElement, dtdFound; bool isRootElement, grammarFound;
XML_Parser p; unsigned attributeValueCutoff;
XML_Parser p;
}; };
class XmlPromptGenerator : public WrapExpat class XmlPromptGenerator : public WrapExpat
{ {
public: public:
XmlPromptGenerator ( XmlPromptGenerator (
const std::string& catalogPath = "", const std::string& catalogPath = "",
const std::string& basePath = "", const std::string& basePath = "",
const std::string& auxPath = "" ); const std::string& auxPath = "" );
virtual ~XmlPromptGenerator(); virtual ~XmlPromptGenerator();
void getAttributeMap ( void getAttributeMap (
std::map<std::string, std::map<std::string, std::set<std::string> > > std::map<std::string, std::map<std::string, std::set<std::string> > >
&attributeMap ); &attributeMap );
void getRequiredAttributeMap ( void getRequiredAttributeMap (
std::map<std::string, std::set<std::string> > &requiredAttributeMap ); std::map<std::string, std::set<std::string> > &requiredAttributeMap );
void getElementMap ( void getElementMap (
std::map<std::string, std::set<std::string> > &elementMap ); std::map<std::string, std::set<std::string> > &elementMap );
void getEntitySet ( void getEntitySet (
std::set<std::string> &entitySet ); std::set<std::string> &entitySet );
bool getDtdFound(); bool getGrammarFound();
private: private:
std::auto_ptr<PromptGeneratorData> d; std::auto_ptr<PromptGeneratorData> d;
static void XMLCALL starthandler ( static void XMLCALL starthandler (
void *data, void *data,
const XML_Char *el, const XML_Char *el,
const XML_Char **attr ); const XML_Char **attr );
static void XMLCALL endhandler ( static void XMLCALL endhandler (
void *data, void *data,
const XML_Char *el ); const XML_Char *el );
static void XMLCALL doctypedeclstarthandler ( static void XMLCALL doctypedeclstarthandler (
void *userData, void *userData,
const XML_Char *doctypeName, const XML_Char *doctypeName,
const XML_Char *sysid, const XML_Char *sysid,
const XML_Char *pubid, const XML_Char *pubid,
int has_internal_subset ); int has_internal_subset );
static void XMLCALL doctypedeclendhandler ( void *userData ); static void XMLCALL doctypedeclendhandler ( void *userData );
static void XMLCALL elementdeclhandler ( static void XMLCALL elementdeclhandler (
void *userData, void *userData,
const XML_Char *name, const XML_Char *name,
XML_Content *model ); XML_Content *model );
static void XMLCALL attlistdeclhandler ( static void XMLCALL attlistdeclhandler (
void *userData, void *userData,
const XML_Char *elname, const XML_Char *elname,
const XML_Char *attname, const XML_Char *attname,
const XML_Char *att_type, const XML_Char *att_type,
const XML_Char *dflt, const XML_Char *dflt,
int isrequired ); int isrequired );
static int XMLCALL externalentityrefhandler ( static int XMLCALL externalentityrefhandler (
XML_Parser p, XML_Parser p,
const XML_Char *context, const XML_Char *context,
const XML_Char *base, const XML_Char *base,
const XML_Char *systemId, const XML_Char *systemId,
const XML_Char *publicId ); const XML_Char *publicId );
static void XMLCALL entitydeclhandler ( static void XMLCALL entitydeclhandler (
void *userData, void *userData,
const XML_Char *entityName, const XML_Char *entityName,
int is_parameter_entity, int is_parameter_entity,
const XML_Char *value, const XML_Char *value,
int value_length, int value_length,
const XML_Char *base, const XML_Char *base,
const XML_Char *systemId, const XML_Char *systemId,
const XML_Char *publicId, const XML_Char *publicId,
const XML_Char *notationName ); const XML_Char *notationName );
static void handleSchema (
PromptGeneratorData *d,
const XML_Char *el,
const XML_Char **attr );
}; };
#endif #endif