blob: 09dc0509e4424db76f2edd03c245651299abe446 [file] [log] [blame]
/*
* (C) Copyright IBM Corp. 1999 All rights reserved.
*
* US Government Users Restricted Rights Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*
* The program is provided "as is" without any warranty express or
* implied, including the warranty of non-infringement and the implied
* warranties of merchantibility and fitness for a particular purpose.
* IBM will not be liable for any damages suffered by you as a result
* of using the Program. In no event will IBM be liable for any
* special, indirect or consequential damages or lost profits even if
* IBM has been advised of the possibility of their occurrence. IBM
* will not be liable for any third party claims against you.
*/
/**
* @version Revision: %M% %I% %W% %Q%
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#include <util/NameIdPool.hpp>
#include <util/PlatformUtils.hpp>
#include <framework/XMLValidator.hpp>
#include <parsers/SAXParser.hpp>
#include <validators/DTD/DTDValidator.hpp>
#include <iostream.h>
#include <stdlib.h>
#include <string.h>
// ---------------------------------------------------------------------------
// Forward references
// ---------------------------------------------------------------------------
static void usage();
// ---------------------------------------------------------------------------
// 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, const unsigned int len = 0) :
fLocalForm(0)
{
// Call the private transcoding method
transcode(toTranscode, len);
}
~StrX()
{
delete [] fLocalForm;
}
// -----------------------------------------------------------------------
// Getter methods
// -----------------------------------------------------------------------
const char* localForm() const
{
return fLocalForm;
}
private :
// -----------------------------------------------------------------------
// Private helper methods
// -----------------------------------------------------------------------
void transcode (const XMLCh* const toTranscode, const unsigned int len);
// -----------------------------------------------------------------------
// 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;
}
// ---------------------------------------------------------------------------
// Program entry point
// ---------------------------------------------------------------------------
int main(int argc, char* args[])
{
// Initialize the XML4C system
try
{
XMLPlatformUtils::Initialize();
}
catch (const XMLException& toCatch)
{
cerr << "Error during initialization! Message:\n"
<< StrX(toCatch.getMessage()) << endl;
return 1;
}
// We only have one required parameter, which is the file to process
if (argc < 2)
{
usage();
return -1;
}
const char* xmlFile = args[1];
bool doValidation = false;
// Check for some special cases values of the parameter
if (!strncmp(xmlFile, "-?", 2))
{
usage();
return 0;
}
else if (!strncmp(xmlFile, "-v", 2))
{
doValidation = true;
if (argc < 3)
{
usage();
return -1;
}
xmlFile = args[2];
}
else if (xmlFile[0] == '-')
{
usage();
return -1;
}
//
// Create a DTD 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.
//
DTDValidator* valToUse = new DTDValidator;
SAXParser parser(valToUse);
parser.setDoValidation(doValidation);
//
// Get the starting time and kick off the parse of the indicated
// file. Catch any exceptions that might propogate out of it.
//
try
{
parser.parse(xmlFile);
}
catch (const XMLException& e)
{
cerr << "\nError during parsing: '" << xmlFile << "'\n"
<< "Exception message is: \n"
<< StrX(e.getMessage()) << "\n" << endl;
return -1;
}
//
// 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.
//
NameIdPoolEnumerator<DTDElementDecl> elemEnum = valToUse->getElemEnumerator();
if (elemEnum.hasMoreElements())
{
cout << "\nELEMENTS:\n----------------------------\n";
while(elemEnum.hasMoreElements())
{
const DTDElementDecl& curElem = elemEnum.nextElement();
cout << " Name: " << StrX(curElem.getFullName()) << "\n";
cout << " Content Model: "
<< StrX(curElem.getFormattedContentModel(*valToUse))
<< "\n";
// Get an enumerator for this guy's attributes if any
if (curElem.hasAttDefs())
{
cout << " Attributes:\n";
XMLAttDefList& attList = curElem.getAttDefList();
while (attList.hasMoreElements())
{
const XMLAttDef& curAttDef = attList.nextElement();
cout << " Name:" << StrX(curAttDef.getFullName())
<< ", Type: ";
// Get the type and display it
const XMLAttDef::AttTypes type = curAttDef.getType();
switch(type)
{
case XMLAttDef::CData :
cout << "CDATA";
break;
case XMLAttDef::ID :
cout << "ID";
break;
case XMLAttDef::IDRef :
case XMLAttDef::IDRefs :
cout << "IDREF(S)";
break;
case XMLAttDef::Entity :
case XMLAttDef::Entities :
cout << "ENTITY(IES)";
break;
case XMLAttDef::NmToken :
case XMLAttDef::NmTokens :
cout << "NMTOKEN(S)";
break;
case XMLAttDef::Notation :
cout << "NOTATION";
break;
case XMLAttDef::Enumeration :
cout << "ENUMERATION";
break;
}
cout << "\n";
}
}
cout << endl;
}
}
else
{
cout << "The validator has no elements to display\n" << endl;
}
return 0;
}
// ---------------------------------------------------------------------------
// Local helper methods
// ---------------------------------------------------------------------------
static void usage()
{
cout << "\nUsage:\n"
" EnumVal [-v] <XML file>\n"
" -v Do a validating parse. Defaults to non-validating.\n"
"This program parses a file, then shows how to enumerate the"
"contents of the validator pools\n" << endl;
}
// ---------------------------------------------------------------------------
// StrX: Private helper methods
// ---------------------------------------------------------------------------
void StrX::transcode(const XMLCh* const toTranscode, const unsigned int len)
{
// Short circuit if its a null pointer
if (!toTranscode)
{
fLocalForm = new char[1];
fLocalForm[0] = 0;
return;
}
// See if our XMLCh and wchar_t as the same on this platform
const bool isSameSize = (sizeof(XMLCh) == sizeof(wchar_t));
//
// Get the actual number of chars. If the passed len is zero, its null
// terminated. Else we have to use the len.
//
wchar_t realLen = (wchar_t)len;
if (!realLen)
{
//
// We cannot just assume we can use wcslen() because we don't know
// if our XMLCh is the same as wchar_t on this platform.
//
const XMLCh* tmpPtr = toTranscode;
while (*(tmpPtr++))
realLen++;
}
//
// If either the passed length was non-zero or our char sizes are not
// same, we have to use a temp buffer. Since this is common in these
// samples, we just do it anyway.
//
wchar_t* tmpSource = new wchar_t[realLen + 1];
if (isSameSize)
{
memcpy(tmpSource, toTranscode, realLen * sizeof(wchar_t));
}
else
{
for (unsigned int index = 0; index < realLen; index++)
tmpSource[index] = (wchar_t)toTranscode[index];
}
tmpSource[realLen] = 0;
// See now many chars we need to transcode this guy
const unsigned int targetLen = ::wcstombs(0, tmpSource, 0);
// Allocate out storage member
fLocalForm = new char[targetLen + 1];
//
// And transcode our temp source buffer to the local buffer. Cap it
// off since the converter won't do it (because the null is beyond
// where the target will fill up.)
//
::wcstombs(fLocalForm, tmpSource, targetLen);
fLocalForm[targetLen] = 0;
// Don't forget to delete our temp buffer
delete [] tmpSource;
}