blob: 461d161cff8079eb27a29954231d3a2ca3ac27c3 [file] [log] [blame]
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xerces" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache\@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation, and was
* originally based on software copyright (c) 2001, International
* Business Machines, Inc., http://www.ibm.com . For more information
* on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
/*
* $Id$
* $Log$
* Revision 1.8 2002/02/20 20:30:11 peiyongz
* Make the code compilable on Solaris 2.6's CC
*
* Revision 1.7 2002/02/14 15:14:58 peiyongz
* getEnumString()
*
* Revision 1.6 2002/02/01 22:41:28 peiyongz
* sane_include
*
* Revision 1.5 2001/11/22 14:47:48 tng
* Use the phrase "Grammar" instead of "Validator" in EnumVal and SEnumVal Description.
*
* Revision 1.4 2001/11/21 22:09:49 peiyongz
* Copy Right date
*
* Revision 1.3 2001/11/21 19:05:23 peiyongz
* SEnumVal: GrammarType checked
*
*
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <xercesc/util/NameIdPool.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/framework/XMLValidator.hpp>
#include <xercesc/parsers/SAXParser.hpp>
#include <xercesc/validators/schema/SchemaValidator.hpp>
#include <xercesc/validators/common/ContentSpecNode.hpp>
#include <xercesc/validators/schema/SchemaSymbols.hpp>
#include <iostream.h>
#include <stdlib.h>
#include <string.h>
// ---------------------------------------------------------------------------
// Forward references
// ---------------------------------------------------------------------------
static void usage();
void process(char* const);
void processAttributes( XMLAttDefList& attList, bool margin = false );
void processDatatypeValidator( const DatatypeValidator*, bool margin = false
);
void processContentSpecNode( const ContentSpecNode* specNode, bool margin =
false );
// ---------------------------------------------------------------------------
// This is a simple class that lets us do easy (though not terribly efficient)
// trancoding of XMLCh data to local code page for display.
// ---------------------------------------------------------------------------
class StrX
{
public :
// -----------------------------------------------------------------------
// Constructors and Destructor
// -----------------------------------------------------------------------
StrX(const XMLCh* const toTranscode)
{
// Call the private transcoding method
fLocalForm = XMLString::transcode(toTranscode);
}
~StrX()
{
delete [] fLocalForm;
}
// -----------------------------------------------------------------------
// Getter methods
// -----------------------------------------------------------------------
const char* localForm() const
{
return fLocalForm;
}
private :
// -----------------------------------------------------------------------
// Private data members
//
// fLocalForm
// This is the local code page form of the string.
// -----------------------------------------------------------------------
char* fLocalForm;
};
inline ostream& operator<<(ostream& target, const StrX& toDump)
{
target << toDump.localForm();
return target;
}
// ---------------------------------------------------------------------------
// Local helper methods
// ---------------------------------------------------------------------------
static void usage()
{
cout << "\nUsage:\n"
" SEnumVal <XML file>\n\n"
"This program parses a file, then shows how to enumerate the\n"
"contents of the Schema Grammar. Essentially, shows how one can\n"
"access the Schema information stored in internal data structures.\n"
<< endl;
}
// ---------------------------------------------------------------------------
// Program entry point
// ---------------------------------------------------------------------------
int main(int argC, char* argV[])
{
// Initialize the XML4C system
try
{
XMLPlatformUtils::Initialize();
}
catch (const XMLException& toCatch)
{
cerr << "Error during initialization! Message:\n"
<< StrX(toCatch.getMessage()) << endl;
XMLPlatformUtils::Terminate();
return 1;
}
// Check command line and extract arguments.
// We only have one required parameter, which is the file to process
if ((argC != 2) ||
(*(argV[1]) == '-'))
{
usage();
XMLPlatformUtils::Terminate();
return 2;
}
try
{
process(argV[1]);
}
catch (const XMLException& e)
{
cerr << "\nError during parsing: '" << argV[1] << "'\n"
<< "Exception message is: \n"
<< StrX(e.getMessage()) << "\n" << endl;
XMLPlatformUtils::Terminate();
return 3;
}
XMLPlatformUtils::Terminate();
return 0;
}
void process(char* const xmlFile)
{
//
// Create a Schema validator to be used for our validation work. Then create
// a SAX parser object and pass it our validator. Then, according to what
// we were told on the command line, set it to validate or not. He owns
// the validator, so we have to allocate it.
//
SAXParser parser;
parser.setValidationScheme(SAXParser::Val_Always);
parser.setDoNamespaces(true);
parser.setDoSchema(true);
parser.parse(xmlFile);
if (parser.getErrorCount())
{
cout << "\nErrors occured, no output available\n" << endl;
return;
}
if (!parser.getValidator().handlesSchema())
{
cout << "\n Non schema document, no output available\n" << endl;
return;
}
if ( parser.getValidator().getGrammar()->getGrammarType() != Grammar::SchemaGrammarType)
{
cout << "\n Non schema grammar, no output available\n" << endl;
return;
}
//
// Now we will get an enumerator for the element pool from the validator
// and enumerate the elements, printing them as we go. For each element
// we get an enumerator for its attributes and print them also.
//
SchemaGrammar* grammar = (SchemaGrammar*) parser.getValidator().getGrammar();
RefHash3KeysIdPoolEnumerator<SchemaElementDecl> elemEnum = grammar->getElemEnumerator();
if (!elemEnum.hasMoreElements())
{
cout << "\nThe validator has no elements to display\n" << endl;
return;
}
while(elemEnum.hasMoreElements())
{
const SchemaElementDecl& curElem = elemEnum.nextElement();
// Name
cout << "Name:\t\t\t" << StrX(curElem.getFullName()) << "\n";
// Model Type
cout << "Model Type:\t\t";
switch( curElem.getModelType() )
{
case SchemaElementDecl::Empty: cout << "Empty"; break;
case SchemaElementDecl::Any: cout << "Any"; break;
case SchemaElementDecl::Mixed_Simple: cout << "Mixed_Simple"; break;
case SchemaElementDecl::Mixed_Complex: cout << "Mixed_Complex"; break;
case SchemaElementDecl::Children: cout << "Children"; break;
case SchemaElementDecl::Simple: cout << "Simple"; break;
default: cout << "Unknown"; break;
}
cout << "\n";
// Create Reason
cout << "Create Reason:\t";
switch( curElem.getCreateReason() )
{
case XMLElementDecl::NoReason: cout << "Empty"; break;
case XMLElementDecl::Declared: cout << "Declared"; break;
case XMLElementDecl::AttList: cout << "AttList"; break;
case XMLElementDecl::InContentModel: cout << "InContentModel"; break;
case XMLElementDecl::AsRootElem: cout << "AsRootElem"; break;
case XMLElementDecl::JustFaultIn: cout << "JustFaultIn"; break;
default: cout << "Unknown"; break;
}
cout << "\n";
// Content Spec Node
processContentSpecNode( curElem.getContentSpec() );
// Misc Flags
int mflags = curElem.getMiscFlags();
if( mflags !=0 )
{
cout << "Misc. Flags:\t";
}
if( mflags == SchemaSymbols::INFINITY )
{
cout << "Infinity ";
}
else
{
if ( mflags & SchemaSymbols::NILLABLE != 0 )
cout << "Nillable ";
if ( mflags & SchemaSymbols::ABSTRACT != 0 )
cout << "Abstract ";
if ( mflags & SchemaSymbols::FIXED != 0 )
cout << "Fixed ";
}
if( mflags !=0 )
{
cout << "\n";
}
// Substitution Name
XMLCh* subsGroup = curElem.getSubstitutionGroupName();
if( subsGroup )
{
cout << "Substitution Name:\t" << StrX(subsGroup) << "\n";
}
// Content Model
const XMLCh* fmtCntModel = curElem.getFormattedContentModel();
if( fmtCntModel != NULL )
{
cout << "Content Model:\t" << StrX(fmtCntModel) << "\n";
}
const ComplexTypeInfo* ctype = curElem.getComplexTypeInfo();
if( ctype != NULL)
{
cout << "ComplexType:\n";
cout << "\tTypeName:\t" << StrX(ctype->getTypeName()) << "\n";
ContentSpecNode* cSpecNode = ctype->getContentSpec();
processContentSpecNode(cSpecNode, true );
}
// Datatype
DatatypeValidator* dtValidator = curElem.getDatatypeValidator();
processDatatypeValidator( dtValidator );
// Get an enumerator for this guy's attributes if any
if ( curElem.hasAttDefs() )
{
processAttributes( curElem.getAttDefList() );
}
cout << "--------------------------------------------";
cout << endl;
}
return;
}
//---------------------------------------------------------------------
// Prints the Attribute's properties
//---------------------------------------------------------------------
void processAttributes( XMLAttDefList& attList, bool margin )
{
if ( attList.isEmpty() )
{
return;
}
if ( margin )
{
cout << "\t";
}
cout << "Attributes:\n";
while( attList.hasMoreElements() )
{
// Name
SchemaAttDef& curAttDef = (SchemaAttDef&)attList.nextElement();
cout << "\tName:\t\t\t" << StrX(curAttDef.getFullName()) << "\n";
// Type
cout << "\tType:\t\t\t";
cout << StrX(XMLAttDef::getAttTypeString(curAttDef.getType()));
cout << "\n";
// Default Type
cout << "\tDefault Type:\t";
cout << StrX(XMLAttDef::getDefAttTypeString(curAttDef.getDefaultType()));
cout << "\n";
// Value
if( curAttDef.getValue() )
{
cout << "\tValue:\t\t\t";
cout << StrX(curAttDef.getValue());
cout << "\n";
}
// Enum. values
if( curAttDef.getEnumeration() )
{
cout << "\tEnumeration:\t";
cout << StrX(curAttDef.getEnumeration());
cout << "\n";
}
const DatatypeValidator* dv = curAttDef.getDatatypeValidator();
processDatatypeValidator( dv, true );
cout << "\n";
}
}
void processDatatypeValidator( const DatatypeValidator* dtValidator, bool margin )
{
if( !dtValidator )
{
return;
}
if( margin )
{
cout << "\t";
}
cout << "Base Datatype:\t\t";
switch( dtValidator->getType() )
{
case DatatypeValidator::String: cout << "string"; break;
case DatatypeValidator::AnyURI: cout << "AnyURI"; break;
case DatatypeValidator::QName: cout << "QName"; break;
case DatatypeValidator::Name: cout << "Name"; break;
case DatatypeValidator::NCName: cout << "NCName"; break;
case DatatypeValidator::Boolean: cout << "Boolean"; break;
case DatatypeValidator::Float: cout << "Float"; break;
case DatatypeValidator::Double: cout << "Double"; break;
case DatatypeValidator::Decimal: cout << "Decimal"; break;
case DatatypeValidator::HexBinary: cout << "HexBinary"; break;
case DatatypeValidator::Base64Binary: cout << "Base64Binary";break;
case DatatypeValidator::Duration: cout << "Duration"; break;
case DatatypeValidator::DateTime: cout << "DateTime"; break;
case DatatypeValidator::Date: cout << "Date"; break;
case DatatypeValidator::Time: cout << "Time"; break;
case DatatypeValidator::MonthDay: cout << "MonthDay"; break;
case DatatypeValidator::YearMonth: cout << "YearMonth"; break;
case DatatypeValidator::Year: cout << "Year"; break;
case DatatypeValidator::Month: cout << "Month"; break;
case DatatypeValidator::Day: cout << "Day"; break;
case DatatypeValidator::ID: cout << "ID"; break;
case DatatypeValidator::IDREF: cout << "IDREF"; break;
case DatatypeValidator::ENTITY: cout << "ENTITY"; break;
case DatatypeValidator::NOTATION: cout << "NOTATION"; break;
case DatatypeValidator::List: cout << "List"; break;
case DatatypeValidator::Union: cout << "Union"; break;
case DatatypeValidator::AnySimpleType: cout << "AnySimpleType"; break;
}
cout << "\n";
// Facets
RefHashTableOf<KVStringPair>* facets = dtValidator->getFacets();
if( facets )
{
RefHashTableOfEnumerator<KVStringPair> enumFacets(facets);
if( enumFacets.hasMoreElements() )
{
cout << "Facets:\t\t\n";
}
while(enumFacets.hasMoreElements())
{
// Element's properties
const KVStringPair& curPair = enumFacets.nextElement();
cout << "\t" << StrX( curPair.getKey() ) << "="
<< StrX( curPair.getValue() ) << "\n";
}
}
// Enumerations
RefVectorOf<XMLCh>* enums = (RefVectorOf<XMLCh>*) dtValidator->getEnumString();
if (enums)
{
cout << "Enumeration:\t\t\n";
int enumLength = enums->size();
for ( int i = 0; i < enumLength; i++)
{
cout << "\t" << StrX( enums->elementAt(i)) << "\n";
}
}
}
void processContentSpecNode( const ContentSpecNode* cSpecNode, bool margin )
{
if( !cSpecNode )
{
return;
}
if( margin )
{
cout << "\t";
}
cout << "ContentType:\t";
switch( cSpecNode->getType() )
{
case ContentSpecNode::Leaf: cout << "Leaf"; break;
case ContentSpecNode::ZeroOrOne: cout << "ZeroOrOne"; break;
case ContentSpecNode::ZeroOrMore: cout << "ZeroOrMore"; break;
case ContentSpecNode::OneOrMore: cout << "OneOrMore"; break;
case ContentSpecNode::Choice: cout << "Choice"; break;
case ContentSpecNode::Sequence: cout << "Sequence"; break;
case ContentSpecNode::All: cout << "All"; break;
case ContentSpecNode::Any: cout << "Any"; break;
case ContentSpecNode::Any_Other: cout << "Any_Other"; break;
case ContentSpecNode::Any_NS: cout << "Any_NS"; break;
case ContentSpecNode::Any_Lax: cout << "Any_Lax"; break;
case ContentSpecNode::Any_Other_Lax: cout << "Any_Other_Lax"; break;
case ContentSpecNode::Any_NS_Lax: cout << "Any_NS_Lax"; break;
case ContentSpecNode::Any_Skip: cout << "Any_Skip"; break;
case ContentSpecNode::Any_Other_Skip: cout << "Any_Other_Skip"; break;
case ContentSpecNode::Any_NS_Skip: cout << "Any_NS_Skip"; break;
case ContentSpecNode::UnknownType: cout << "UnknownType"; break;
}
cout << "\n";
}