EverWrath/deps/acelite/ace/XML_Utils/XML_Helper.tpp
Francesco Borzì 3a43e8c415 feat(Core): enable C++17 (#2234)
Co-authored-by: Winfidonarleyan <dowlandtop@yandex.com>
2019-09-02 13:54:10 +07:00

345 lines
10 KiB
C++

#include "XML_Helper.h"
#include "ace/Auto_Ptr.h"
#include "ace/Log_Msg.h"
#include "ace/Log_Category.h"
#include "xercesc/util/XMLUniDefs.hpp"
#include "xercesc/dom/DOM.hpp"
#include "XML_Error_Handler.h"
#include "XML_Schema_Resolver.h"
#include "xercesc/framework/LocalFileFormatTarget.hpp"
#include "xercesc/dom/DOM.hpp"
#include "XercesString.h"
#if XERCES_VERSION_MAJOR == 3
#include "xercesc/dom/DOMLSSerializer.hpp"
#endif
namespace XML
{
using xercesc::XMLException;
using xercesc::XMLString;
using xercesc::DOMImplementation;
using xercesc::DOMImplementationRegistry;
// using xercesc::DOMBuilder;
using xercesc::DOMImplementationLS;
using xercesc::XMLUni;
using xercesc::DOMDocument;
using xercesc::DOMException;
using xercesc::DOMDocumentType;
using xercesc::XercesDOMParser;
/*
template <typename Resolver, typename Error>
XML_Helper<Resolver, Error>::XML_Helper (void)
: initialized_ (false)
{
this->init_parser ();
}
*/
// TODO this is stub implementation
template <typename Resolver, typename Error>
XML_Helper<Resolver, Error>::XML_Helper (Resolver *resolver, Error *eh)
: initialized_ (false),
resolver_ (resolver),
release_resolver_(false),
e_handler_ (eh),
release_e_handler_ (false)
{
this->init_parser ();
}
template <typename Resolver, typename Error>
XML_Helper<Resolver, Error>::~XML_Helper (void)
{
this->terminate_parser ();
}
template <typename Resolver, typename Error>
bool
XML_Helper<Resolver, Error>::is_initialized (void) const
{
return this->initialized_ == true;
}
template <typename Resolver, typename Error>
void
XML_Helper<Resolver, Error>::init_parser (void)
{
if (this->initialized_)
return;
// CIAO_DEBUG ((LM_TRACE, CLINFO
//"XML_Helper<>::is_initialized - Initializing the Xerces runtime \n"));
// Initialize the Xerces run-time
try
{
if (!resolver_)
{
resolver_ = new Resolver ();
release_resolver_ = true;
}
if (!e_handler_)
{
e_handler_ = new Error ();
release_e_handler_ = true;
}
xercesc::XMLPlatformUtils::Initialize();
}
catch (const XMLException& e)
{
char* message =
XMLString::transcode (e.getMessage());
ACE_Auto_Basic_Array_Ptr<char> cleanup_message (message);
throw;
}
catch (...)
{
ACELIB_DEBUG ((LM_DEBUG, "(%P|%t) Some other exception, returning\n"));
return;
}
// Instantiate the DOM parser.
static const XMLCh gLS[] = { xercesc::chLatin_L,
xercesc::chLatin_S,
xercesc::chNull };
// Get an implementation of the Load-Store (LS) interface
// and cache it for later use
impl_ =
DOMImplementationRegistry::getDOMImplementation(gLS);
this->initialized_ = true;
return;
}
template <typename Resolver, typename Error>
XERCES_CPP_NAMESPACE::DOMDocument *
XML_Helper<Resolver, Error>::create_dom (const ACE_TCHAR *root,
const ACE_TCHAR *ns,
DOMDocumentType *doctype) const
{
if (root == 0 || ns == 0)
return 0;
return this->impl_->createDocument (XStr (ns),
XStr (root),
doctype);
}
template <typename Resolver, typename Error>
XERCES_CPP_NAMESPACE::DOMDocumentType *
XML_Helper<Resolver, Error>::create_doctype (const ACE_TCHAR *qn,
const ACE_TCHAR *pid,
const ACE_TCHAR *sid) const
{
return this->impl_->createDocumentType (XStr (qn),
XStr (pid),
XStr (sid));
}
template <typename Resolver, typename Error>
XERCES_CPP_NAMESPACE::DOMDocument *
XML_Helper<Resolver, Error>::create_dom (const ACE_TCHAR *url) const
{
if (url == 0)
return 0;
try
{
if (this->parser_.get () == 0)
this->parser_.reset ((new xercesc::XercesDOMParser ()));
// Perform Namespace processing.
this->parser_->setDoNamespaces (true);
// Discard comment nodes in the document
this->parser_->setCreateCommentNodes (false);
// Disable datatype normalization. The XML 1.0 attribute value
// normalization always occurs though.
// this->parser_->setFeature (XMLUni::fgDOMDatatypeNormalization, true);
// Do not create EntityReference nodes in the DOM tree. No
// EntityReference nodes will be created, only the nodes
// corresponding to their fully expanded sustitution text will be
// created.
this->parser_->setCreateEntityReferenceNodes (false);
// Perform Validation
this->parser_->setValidationScheme (xercesc::AbstractDOMParser::Val_Always);
// Do not include ignorable whitespace in the DOM tree.
this->parser_->setIncludeIgnorableWhitespace (false);
// Enable the parser's schema support.
this->parser_->setDoSchema (true);
// Enable full schema constraint checking, including checking which
// may be time-consuming or memory intensive. Currently, particle
// unique attribution constraint checking and particle derivation
// restriction checking are controlled by this option.
this->parser_->setValidationSchemaFullChecking (true);
// The parser will treat validation error as fatal and will exit.
this->parser_->setValidationConstraintFatal (true);
this->parser_->setErrorHandler (e_handler_);
this->parser_->setEntityResolver (resolver_);
this->parser_->parse (ACE_TEXT_ALWAYS_CHAR (url));
if (e_handler_ && e_handler_->getErrors ())
return 0;
return this->parser_->getDocument ();
}
catch (const DOMException& e)
{
const unsigned int maxChars = 2047;
XMLCh errText[maxChars + 1];
if (DOMImplementation::loadDOMExceptionMsg (e.code,
errText,
maxChars))
{
char* message =
XMLString::transcode (errText);
ACE_Auto_Basic_Array_Ptr<char> cleanup_message (message);
}
return 0;
}
catch (const XMLException& e)
{
char* message = XMLString::transcode (e.getMessage());
ACE_Auto_Basic_Array_Ptr<char> cleanup_message (message);
throw 0;
}
catch (...)
{
ACELIB_DEBUG ((LM_DEBUG, "(%P|%t) Caught an unknown exception\n"));
throw;
}
return 0;
}
template <typename Resolver, typename Error>
void
XML_Helper<Resolver, Error>::terminate_parser (void)
{
if (!this->initialized_)
return;
try
{
if (release_resolver_ && resolver_)
{
delete resolver_;
resolver_ = 0;
}
if (release_e_handler_ && e_handler_)
{
delete e_handler_;
e_handler_ = 0;
}
this->parser_.reset (0);
this->impl_ = 0;
xercesc::XMLPlatformUtils::Terminate();
}
catch (const XMLException& e)
{
char* message =
XMLString::transcode (e.getMessage());
ACE_Auto_Basic_Array_Ptr<char> cleanup_message (message);
throw;
}
this->initialized_ = false;
return;
}
template <typename Resolver, typename Error>
Resolver &
XML_Helper<Resolver, Error>::get_resolver (void)
{
if (!this->resolver_)
throw std::exception ();
return *this->resolver_;
}
template <typename Resolver, typename Error>
Error &
XML_Helper<Resolver, Error>::get_error_handler (void)
{
if (!this->e_handler_)
throw std::exception ();
return *this->e_handler_;
}
template <typename Resolver, typename Error>
bool
XML_Helper<Resolver, Error>::write_DOM (XERCES_CPP_NAMESPACE::DOMDocument *doc,
const ACE_TCHAR *file) const
{
try
{
bool retn;
#if XERCES_VERSION_MAJOR == 3
XERCES_CPP_NAMESPACE::DOMLSSerializer *serializer (impl_->createLSSerializer ());
XERCES_CPP_NAMESPACE::DOMConfiguration *ser_config (serializer->getDomConfig ());
XERCES_CPP_NAMESPACE::DOMLSOutput *output (impl_->createLSOutput ());
if (ser_config->canSetParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true))
ser_config->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, true);
XMLFormatTarget *format_target = new XERCES_CPP_NAMESPACE::LocalFileFormatTarget (ACE_TEXT_ALWAYS_CHAR (file));
output->setByteStream (format_target);
retn = serializer->write (doc, output);
output->release ();
serializer->release ();
return retn;
#else
std::unique_ptr <XERCES_CPP_NAMESPACE::DOMWriter> writer (impl_->createDOMWriter());
if (writer->canSetFeature (XMLUni::fgDOMWRTFormatPrettyPrint,
true))
writer->setFeature (XMLUni::fgDOMWRTFormatPrettyPrint, true);
std::unique_ptr <xercesc::XMLFormatTarget> ft (new xercesc::LocalFileFormatTarget(ACE_TEXT_ALWAYS_CHAR (file)));
retn = writer->writeNode(ft.get (), *doc);
return retn;
#endif
}
catch (const xercesc::XMLException &e)
{
char* message = XMLString::transcode (e.getMessage());
ACE_Auto_Basic_Array_Ptr<char> cleanup_message (message);
char* name = XMLString::transcode (e.getType());
ACE_Auto_Basic_Array_Ptr<char> cleanup_name (name);
ACELIB_ERROR ((LM_ERROR, "Caught exception while serializing DOM to file.\n"
"Name: %C\n"
"Message: %C\n"
"SrcFile: %C\n"
"SrcLine: %C\n",
name,
message,
e.getSrcFile (),
e.getSrcLine ()));
return false;
}
}
}