#include <xalanc/XalanTransformer/XalanTransformer.hpp>
#include <xalanc/Include/PlatformDefinitions.hpp>

#include <xalanc/XercesParserLiaison/XercesParserLiaison.hpp>
#include <xalanc/XercesParserLiaison/XercesDOMSupport.hpp>
#include <xalanc/XalanTransformer/XercesDOMWrapperParsedSource.hpp>
#include <xalanc/XalanTransformer/XalanSourceTreeWrapperParsedSource.hpp>
#include <xalanc/Include/XalanMemMgrAutoPtr.hpp>
#include <xalanc/XercesParserLiaison/FormatterToXercesDOM.hpp>
#include <xalanc/XercesParserLiaison/XercesDocumentWrapper.hpp>

#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLException.hpp>
#include <xercesc/dom/DOMNode.hpp>
#include <xercesc/dom/DOMText.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/dom/DOMDocument.hpp>
#include <xercesc/validators/common/Grammar.hpp>
#include <xercesc/parsers/DOMBuilderImpl.hpp>
#include <xercesc/dom/DOMImplementation.hpp>
#include <xercesc/dom/DOMImplementationRegistry.hpp>

#include <stdio.h>
#include <stdlib.h>

#include <strstream>
#include <fstream>
#include <iostream>

XALAN_USING_XALAN(XalanCompiledStylesheet)
XALAN_USING_XALAN(XalanDOMString)
XALAN_USING_XALAN(XalanTransformer)
XALAN_USING_XALAN(XSLTInputSource)
XALAN_USING_XALAN(XSLTResultTarget)
XALAN_USING_XALAN(MemoryManagerType)
XALAN_USING_XALAN(XalanMemMgrAutoPtr)
XALAN_USING_XALAN(XalanMemMgrs)
XALAN_USING_XALAN(XercesDocumentWrapper)
XALAN_USING_XALAN(XalanNode)
XALAN_USING_STD(ostrstream)
XALAN_USING_XERCES(XMLPlatformUtils)
XALAN_USING_XALAN(XalanTransformer)

	
XERCES_CPP_NAMESPACE_USE


int main()
{
	try
	{
		// initialize Xerces
		XMLPlatformUtils::Initialize();
		// Initialize Xalan
		XalanTransformer::initialize();

		DOMImplementation* impl =  DOMImplementationRegistry::getDOMImplementation(XMLString::transcode("Core"));

		if (impl == NULL)
		{
			std::cout << "failed to create DOM implementation" << std::endl;
			return 1;
		}

		DOMDocument* doc = impl->createDocument(
				0,
				XMLString::transcode("foo"),
				0);

		DOMElement* rootElem = doc->getDocumentElement();

		DOMElement*  childElem = doc->createElement(XMLString::transcode("bar"));
		rootElem->appendChild(childElem);

		DOMText *textNode = doc->createTextNode(0);

		// this will make Xalan fail
//		childElem->appendChild(textNode);
		
		// Create a XalanTransformer.
		XalanTransformer theTransformer;
		const XSLTInputSource	theStylesheetInputSource("foo.xsl");

		// Let's compile the stylesheet and re-use it...
		const XalanCompiledStylesheet* theStylesheet = 0;

		if (theTransformer.compileStylesheet(theStylesheetInputSource, theStylesheet) != 0)
		{
			std::cout << "failed to compile stylesheet"
					 << theTransformer.getLastError()
					 << std::endl;
		}
		else
		{
			assert(theStylesheet != 0);

			ostrstream theOutputStream;
			const XSLTResultTarget theResultTarget(theOutputStream, XalanMemMgrs::getDefaultXercesMemMgr());

			XALAN_USING_XALAN(XercesParserLiaison)
			XALAN_USING_XALAN(XercesDOMSupport)
			XALAN_USING_XALAN(XercesDOMWrapperParsedSource)

			XercesDOMSupport theDOMSupport;
			XercesParserLiaison theParserLiaison(theDOMSupport);
			theParserLiaison.setIncludeIgnorableWhitespace (false);

			const XercesDOMWrapperParsedSource theWrapper(
						doc,
						theParserLiaison,
						theDOMSupport
						);


			int nResult = theTransformer.transform(
								theWrapper,
								theStylesheet,
								theResultTarget);

			if (nResult != 0)
			{
				std::cout << "failed to transform: " << theTransformer.getLastError() << std::endl;
			}
			else
			{
				// Null-terminate the data.
				theOutputStream << '\0';
				std::cout << theOutputStream.str() << std::endl;
			}
		}
		
		// Terminate Xalan...
		XalanTransformer::terminate();

		// Terminate Xerces...
		XMLPlatformUtils::Terminate();		
		return 0;
	}
	catch (const XMLException& toCatch)
	{
		return 1;
	}
}
