2009-11-06 18:06:12 +01:00
|
|
|
/*
|
|
|
|
* Copyright 2005-2007 Gerald Schmidt.
|
|
|
|
*
|
|
|
|
* This file is part of Xml Copy Editor.
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
* the Free Software Foundation; version 2 of the License.
|
|
|
|
*
|
|
|
|
* Xml Copy Editor is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with Xml Copy Editor; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "wraplibxml.h"
|
|
|
|
#include <sstream>
|
|
|
|
#include <stdexcept>
|
|
|
|
|
|
|
|
#ifdef ATTRIBUTE_PRINTF
|
|
|
|
#undef ATTRIBUTE_PRINTF
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <wx/wx.h>
|
2012-08-30 16:37:01 +02:00
|
|
|
#include <wx/filesys.h>
|
|
|
|
#include <wx/uri.h>
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
#ifdef __WXMSW__ // Libxml supports utf8 file name on windows
|
|
|
|
#define CONV(url) ( ( const char * ) ( url ).utf8_str() )
|
|
|
|
#else
|
|
|
|
#define CONV(url) ( ( const char * ) ( url ).mb_str ( wxConvLocal ) )
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2013-10-27 15:10:08 +01:00
|
|
|
static xmlCatalogPtr catalog = NULL;
|
|
|
|
|
2012-08-30 16:37:01 +02:00
|
|
|
class Initializer
|
2012-08-15 14:45:24 +02:00
|
|
|
{
|
2012-08-30 16:37:01 +02:00
|
|
|
public:
|
2013-10-19 02:44:17 +02:00
|
|
|
Initializer ( const wxString &catalogPath ) throw ()
|
2012-08-15 14:45:24 +02:00
|
|
|
{
|
2012-08-30 16:37:01 +02:00
|
|
|
xmlSetGenericErrorFunc ( xmlGenericErrorContext,
|
|
|
|
&Initializer::OnXmlGenericError );
|
2012-08-15 14:45:24 +02:00
|
|
|
|
2012-08-30 16:37:01 +02:00
|
|
|
LIBXML_TEST_VERSION
|
2012-08-15 14:45:24 +02:00
|
|
|
|
2012-08-30 16:37:01 +02:00
|
|
|
xmlInitializeCatalog();
|
2013-11-06 12:43:04 +01:00
|
|
|
xmlLoadCatalog ( catalogPath.mb_str() );
|
2013-10-27 15:10:08 +01:00
|
|
|
::catalog = xmlLoadACatalog ( catalogPath.mb_str() );
|
2012-08-30 16:37:01 +02:00
|
|
|
|
|
|
|
initGenericErrorDefaultFunc ( NULL );
|
|
|
|
}
|
|
|
|
|
|
|
|
~Initializer ()
|
|
|
|
{
|
2013-10-27 15:10:08 +01:00
|
|
|
xmlFreeCatalog ( ::catalog );
|
|
|
|
::catalog = NULL;
|
|
|
|
|
2012-08-30 16:37:01 +02:00
|
|
|
xsltCleanupGlobals();
|
|
|
|
xmlCatalogCleanup();
|
|
|
|
xmlCleanupParser();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void XMLCDECL OnXmlGenericError (void *ctx, const char *msg, ...) throw()
|
|
|
|
{
|
|
|
|
va_list args;
|
2012-08-15 14:45:24 +02:00
|
|
|
|
2012-08-30 16:37:01 +02:00
|
|
|
size_t size = 128;
|
|
|
|
std::string buffer;
|
|
|
|
int chars;
|
|
|
|
for (;;)
|
2012-08-15 14:45:24 +02:00
|
|
|
{
|
2012-08-30 16:37:01 +02:00
|
|
|
buffer.resize ( size );
|
|
|
|
if ( buffer.size() < size )
|
|
|
|
throw std::runtime_error ( "Out of memory" );
|
2012-08-15 14:45:24 +02:00
|
|
|
|
2012-08-30 16:37:01 +02:00
|
|
|
va_start(args, msg);
|
|
|
|
chars = vsnprintf( (char *) buffer.c_str(), size, msg, args);
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
if ( chars >= 0 && ( size_t ) chars < size )
|
2012-08-15 14:45:24 +02:00
|
|
|
{
|
2012-08-30 16:37:01 +02:00
|
|
|
buffer.resize ( chars );
|
|
|
|
throw std::runtime_error ( buffer );
|
2012-08-15 14:45:24 +02:00
|
|
|
}
|
2012-08-30 16:37:01 +02:00
|
|
|
if ( chars >= 0 )
|
|
|
|
size = chars + 1;
|
|
|
|
else
|
|
|
|
throw std::runtime_error (
|
|
|
|
std::string ( "Can't format message: " ) + msg );
|
2012-08-15 14:45:24 +02:00
|
|
|
}
|
2012-08-30 16:37:01 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-10-19 02:44:17 +02:00
|
|
|
void WrapLibxml::Init ( const wxString &catalogPath ) throw()
|
2012-08-30 16:37:01 +02:00
|
|
|
{
|
|
|
|
static Initializer dummy ( catalogPath );
|
2012-08-15 14:45:24 +02:00
|
|
|
}
|
|
|
|
|
2012-08-30 16:37:01 +02:00
|
|
|
WrapLibxml::WrapLibxml ( bool netAccessParameter )
|
|
|
|
: netAccess ( netAccessParameter )
|
2009-11-06 18:06:12 +01:00
|
|
|
{
|
2012-08-15 14:45:24 +02:00
|
|
|
WrapLibxml::Init();
|
2009-11-06 18:06:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
WrapLibxml::~WrapLibxml()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
bool WrapLibxml::validate ( const std::string& utf8DocBuf,
|
|
|
|
const wxString &docUrl )
|
2009-11-06 18:06:12 +01:00
|
|
|
{
|
|
|
|
output = "";
|
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
xmlParserCtxtPtr ctxt = NULL;
|
|
|
|
xmlDocPtr docPtr = NULL;
|
2009-11-06 18:06:12 +01:00
|
|
|
|
|
|
|
ctxt = xmlNewParserCtxt();
|
|
|
|
if ( ctxt == NULL )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
int flags = XML_PARSE_DTDVALID;
|
|
|
|
if ( !netAccess )
|
|
|
|
flags |= XML_PARSE_NONET;
|
|
|
|
docPtr = xmlCtxtReadMemory ( ctxt, utf8DocBuf.c_str(), utf8DocBuf.length(),
|
|
|
|
CONV ( docUrl ), "UTF-8", flags);
|
2013-11-12 17:30:07 +01:00
|
|
|
|
|
|
|
bool returnValue = docPtr != NULL && ctxt->valid != 0;
|
2009-11-06 18:06:12 +01:00
|
|
|
|
|
|
|
xmlFreeDoc ( docPtr );
|
|
|
|
xmlFreeParserCtxt ( ctxt );
|
|
|
|
|
|
|
|
return returnValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool WrapLibxml::validateRelaxNG (
|
2013-12-15 15:19:08 +01:00
|
|
|
const wxString &schemaFileName,
|
|
|
|
const std::string &utf8DocBuf,
|
|
|
|
const wxString &docUrl )
|
2009-11-06 18:06:12 +01:00
|
|
|
{
|
|
|
|
output = "";
|
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
bool returnValue = false;
|
|
|
|
xmlParserCtxtPtr ctxt = NULL;
|
|
|
|
xmlDocPtr docPtr = NULL;
|
|
|
|
xmlRelaxNGValidCtxtPtr ctxtPtr = NULL;
|
|
|
|
xmlRelaxNGParserCtxtPtr rngParserCtxt = NULL;
|
|
|
|
xmlRelaxNGPtr schemaPtr = NULL;
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
do {
|
|
|
|
rngParserCtxt = xmlRelaxNGNewParserCtxt ( CONV ( schemaFileName ) );
|
|
|
|
if ( rngParserCtxt == NULL )
|
|
|
|
return false;
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
schemaPtr = xmlRelaxNGParse ( rngParserCtxt );
|
|
|
|
if ( schemaPtr == NULL )
|
|
|
|
break;
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
ctxtPtr = xmlRelaxNGNewValidCtxt ( schemaPtr );
|
|
|
|
if ( ctxtPtr == NULL )
|
|
|
|
break;
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
ctxt = xmlNewParserCtxt();
|
|
|
|
if ( ctxt == NULL )
|
|
|
|
break;
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
int flags = XML_PARSE_DTDVALID;
|
|
|
|
if ( !netAccess )
|
|
|
|
flags |= XML_PARSE_NONET;
|
|
|
|
docPtr = xmlCtxtReadMemory ( ctxt, utf8DocBuf.c_str(),
|
|
|
|
utf8DocBuf.length(), CONV ( docUrl ), "UTF-8", flags );
|
|
|
|
if ( docPtr == NULL )
|
|
|
|
break;
|
|
|
|
|
|
|
|
int err = xmlRelaxNGValidateDoc ( ctxtPtr, docPtr );
|
|
|
|
returnValue = ( err ) ? false : true;
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
} while ( false );
|
2009-11-06 18:06:12 +01:00
|
|
|
|
|
|
|
xmlFreeDoc ( docPtr );
|
2013-12-15 15:19:08 +01:00
|
|
|
xmlFreeParserCtxt ( ctxt );
|
2009-11-06 18:06:12 +01:00
|
|
|
xmlRelaxNGFreeValidCtxt ( ctxtPtr );
|
2013-12-15 15:19:08 +01:00
|
|
|
xmlRelaxNGFree ( schemaPtr );
|
|
|
|
|
2009-11-06 18:06:12 +01:00
|
|
|
return returnValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool WrapLibxml::validateW3CSchema (
|
2013-12-15 15:19:08 +01:00
|
|
|
const wxString &schemaFileName,
|
|
|
|
const std::string &utf8DocBuf,
|
|
|
|
const wxString &docUrl )
|
2009-11-06 18:06:12 +01:00
|
|
|
{
|
|
|
|
output = "";
|
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
bool returnValue = false;
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
xmlParserCtxtPtr ctxt = NULL;
|
|
|
|
xmlDocPtr docPtr = NULL;
|
|
|
|
xmlSchemaValidCtxtPtr ctxtPtr = NULL;
|
|
|
|
xmlSchemaParserCtxtPtr rngParserCtxt = NULL;
|
|
|
|
xmlSchemaPtr schemaPtr = NULL;
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
do {
|
|
|
|
rngParserCtxt = xmlSchemaNewParserCtxt ( CONV ( schemaFileName ) );
|
|
|
|
if ( rngParserCtxt == NULL )
|
|
|
|
return false;
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
schemaPtr = xmlSchemaParse ( rngParserCtxt );
|
|
|
|
if ( schemaPtr == NULL )
|
|
|
|
break;
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
ctxtPtr = xmlSchemaNewValidCtxt ( schemaPtr );
|
|
|
|
if ( ctxtPtr == NULL )
|
|
|
|
break;
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
ctxt = xmlNewParserCtxt();
|
|
|
|
if ( ctxt == NULL )
|
|
|
|
break;
|
|
|
|
|
|
|
|
int flags = XML_PARSE_DTDLOAD;
|
|
|
|
if ( !netAccess )
|
|
|
|
flags |= XML_PARSE_NONET;
|
|
|
|
docPtr = xmlCtxtReadMemory ( ctxt, utf8DocBuf.c_str(),
|
|
|
|
utf8DocBuf.length(), CONV ( docUrl ), "UTF-8", flags );
|
|
|
|
if ( docPtr == NULL )
|
|
|
|
break;
|
|
|
|
|
|
|
|
int res = xmlSchemaValidateDoc ( ctxtPtr, docPtr );
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
returnValue = ( res ) ? false : true;
|
|
|
|
|
|
|
|
} while ( false );
|
2009-11-06 18:06:12 +01:00
|
|
|
|
|
|
|
xmlFreeDoc ( docPtr );
|
2013-12-15 15:19:08 +01:00
|
|
|
xmlFreeParserCtxt ( ctxt );
|
2009-11-06 18:06:12 +01:00
|
|
|
xmlSchemaFree ( schemaPtr );
|
|
|
|
xmlSchemaFreeValidCtxt ( ctxtPtr );
|
2013-12-15 15:19:08 +01:00
|
|
|
|
2009-11-06 18:06:12 +01:00
|
|
|
return returnValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool WrapLibxml::parse (
|
2013-12-15 15:19:08 +01:00
|
|
|
const std::string& utf8DocBuf,
|
|
|
|
const wxString &docUrl,
|
|
|
|
bool indent,
|
|
|
|
bool resolveEntities )
|
|
|
|
{
|
|
|
|
return parse ( utf8DocBuf.c_str(), utf8DocBuf.length(), docUrl,
|
|
|
|
indent, resolveEntities );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool WrapLibxml::parse (
|
|
|
|
const wxString &docUrl,
|
|
|
|
bool indent,
|
|
|
|
bool resolveEntities )
|
|
|
|
{
|
|
|
|
return parse ( NULL, 0, docUrl, indent, resolveEntities );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool WrapLibxml::parse (
|
|
|
|
const char *utf8DocBuf,
|
|
|
|
size_t utf8DocBufSize,
|
|
|
|
const wxString &docUrl,
|
2009-11-06 18:06:12 +01:00
|
|
|
bool indent,
|
|
|
|
bool resolveEntities )
|
|
|
|
{
|
|
|
|
output = "";
|
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
xmlParserCtxtPtr ctxt = NULL;
|
|
|
|
xmlDocPtr docPtr = NULL;
|
2009-11-06 18:06:12 +01:00
|
|
|
|
|
|
|
ctxt = xmlNewParserCtxt();
|
|
|
|
if ( ctxt == NULL )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int flags = XML_PARSE_DTDLOAD;
|
|
|
|
if ( resolveEntities )
|
|
|
|
flags |= XML_PARSE_NOENT;
|
|
|
|
if ( !netAccess )
|
|
|
|
flags |= XML_PARSE_NONET;
|
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
if ( utf8DocBuf != NULL)
|
|
|
|
docPtr = xmlCtxtReadMemory ( ctxt, utf8DocBuf, utf8DocBufSize,
|
|
|
|
CONV ( docUrl ), "UTF-8", flags );
|
|
|
|
else
|
|
|
|
docPtr = xmlCtxtReadFile ( ctxt, CONV ( docUrl ), NULL, flags );
|
2009-11-06 18:06:12 +01:00
|
|
|
if ( docPtr == NULL )
|
|
|
|
{
|
|
|
|
xmlFreeParserCtxt ( ctxt );
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-08-10 14:42:59 +02:00
|
|
|
xmlKeepBlanksDefault ( indent ? 0 : 1 );
|
2009-11-06 18:06:12 +01:00
|
|
|
|
|
|
|
xmlChar *buf = NULL;
|
|
|
|
int size;
|
|
|
|
|
|
|
|
// tbd: link output encoding to input encoding?
|
|
|
|
xmlDocDumpFormatMemoryEnc (
|
|
|
|
docPtr,
|
|
|
|
&buf,
|
|
|
|
&size,
|
|
|
|
"UTF-8",
|
|
|
|
indent );
|
|
|
|
|
|
|
|
if ( buf )
|
|
|
|
{
|
|
|
|
output.append ( ( const char * ) buf );
|
|
|
|
free ( buf );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool returnValue = ( !ctxt->errNo ) ? true : false;
|
|
|
|
|
|
|
|
xmlFreeDoc ( docPtr );
|
|
|
|
xmlFreeParserCtxt ( ctxt );
|
|
|
|
|
|
|
|
return returnValue;
|
|
|
|
}
|
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
bool WrapLibxml::xpath ( const wxString &xpath, const std::string &utf8DocBuf,
|
|
|
|
const wxString &docUrl )
|
2009-11-06 18:06:12 +01:00
|
|
|
{
|
|
|
|
output = "";
|
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
xmlParserCtxtPtr ctxt = NULL;
|
|
|
|
xmlDocPtr docPtr = NULL;
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2012-08-10 14:42:59 +02:00
|
|
|
xmlKeepBlanksDefault ( 0 );
|
|
|
|
|
2009-11-06 18:06:12 +01:00
|
|
|
ctxt = xmlNewParserCtxt();
|
|
|
|
if ( ctxt == NULL )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
docPtr = xmlCtxtReadMemory (
|
2009-11-06 18:06:12 +01:00
|
|
|
ctxt,
|
2013-12-15 15:19:08 +01:00
|
|
|
utf8DocBuf.c_str(),
|
|
|
|
utf8DocBuf.length(),
|
|
|
|
CONV ( docUrl ),
|
2013-12-14 14:30:23 +01:00
|
|
|
"UTF-8",
|
2009-11-06 18:06:12 +01:00
|
|
|
//(netAccess) ? XML_PARSE_DTDLOAD | XML_PARSE_NOENT : XML_PARSE_DTDLOAD | XML_PARSE_NONET | XML_PARSE_NOENT
|
|
|
|
XML_PARSE_NOENT | XML_PARSE_NONET | XML_PARSE_NSCLEAN
|
|
|
|
);
|
|
|
|
|
|
|
|
if ( docPtr == NULL )
|
|
|
|
{
|
|
|
|
xmlFreeParserCtxt ( ctxt );
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
xmlXPathContextPtr context = NULL;
|
|
|
|
xmlXPathObjectPtr result = NULL;
|
|
|
|
xmlNodeSetPtr nodeset = NULL;
|
2009-11-06 18:06:12 +01:00
|
|
|
|
|
|
|
context = xmlXPathNewContext ( docPtr );
|
|
|
|
if ( !context )
|
|
|
|
{
|
|
|
|
xmlFreeDoc ( docPtr );
|
|
|
|
xmlFreeParserCtxt ( ctxt );
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// enable namespace prefixes
|
|
|
|
xmlXPathRegisterNs ( context, ( xmlChar * ) "xhtml", ( xmlChar * ) "http://www.w3.org/1999/xhtml" );
|
|
|
|
// add others as necessary!
|
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
result = xmlXPathEvalExpression (
|
|
|
|
// Since the encoding of the buffer is UTF-8
|
|
|
|
( const xmlChar * ) ( const char * ) xpath.utf8_str (),
|
|
|
|
context );
|
2009-11-06 18:06:12 +01:00
|
|
|
|
|
|
|
bool xpathIsValid = ( result ) ? true : false;
|
|
|
|
|
|
|
|
while ( result != NULL )
|
|
|
|
{
|
|
|
|
if ( xmlXPathNodeSetIsEmpty ( result->nodesetval ) )
|
|
|
|
break;
|
2012-08-10 14:42:59 +02:00
|
|
|
xmlBufferPtr bufferPtr = xmlBufferCreate();
|
|
|
|
if ( bufferPtr == NULL )
|
|
|
|
break;
|
2009-11-06 18:06:12 +01:00
|
|
|
nodeset = result->nodesetval;
|
|
|
|
for ( int i = 0; i < nodeset->nodeNr; i++ )
|
|
|
|
{
|
|
|
|
xmlNodePtr node = nodeset->nodeTab[i];
|
2012-08-10 14:42:59 +02:00
|
|
|
if ( !node )
|
2009-11-06 18:06:12 +01:00
|
|
|
break;
|
|
|
|
xmlNodeDump ( bufferPtr, NULL, node, 0, 1 );
|
|
|
|
|
2012-08-10 14:42:59 +02:00
|
|
|
output += ( const char * ) xmlBufferContent ( bufferPtr );
|
2009-11-06 18:06:12 +01:00
|
|
|
output += '\n';
|
2013-07-20 20:07:39 +02:00
|
|
|
xmlBufferEmpty ( bufferPtr );
|
2009-11-06 18:06:12 +01:00
|
|
|
}
|
2012-08-10 14:42:59 +02:00
|
|
|
xmlBufferFree ( bufferPtr );
|
2009-11-06 18:06:12 +01:00
|
|
|
break;
|
|
|
|
}
|
2013-12-15 15:19:08 +01:00
|
|
|
|
|
|
|
xmlXPathFreeObject ( result );
|
2009-11-06 18:06:12 +01:00
|
|
|
xmlXPathFreeContext ( context );
|
|
|
|
xmlFreeDoc ( docPtr );
|
|
|
|
xmlFreeParserCtxt ( ctxt );
|
|
|
|
|
|
|
|
return xpathIsValid;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool WrapLibxml::xslt (
|
2013-12-15 15:19:08 +01:00
|
|
|
const wxString &styleFileName,
|
|
|
|
const std::string &utf8DocBuf,
|
|
|
|
const wxString &docUrl
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return xslt ( styleFileName, utf8DocBuf.c_str(), utf8DocBuf.length(),
|
|
|
|
docUrl );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool WrapLibxml::xslt (
|
|
|
|
const wxString &styleFileName,
|
|
|
|
const wxString &docUrl
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return xslt ( styleFileName, NULL, 0, docUrl );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool WrapLibxml::xslt (
|
|
|
|
const wxString &styleFileName,
|
|
|
|
const char *utf8DocBuf,
|
|
|
|
size_t utf8DocBufSize,
|
|
|
|
const wxString &docUrl
|
2009-11-06 18:06:12 +01:00
|
|
|
)
|
|
|
|
{
|
|
|
|
output = "";
|
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
bool ret = false;
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
xsltStylesheetPtr cur = NULL;
|
|
|
|
xmlParserCtxtPtr ctxt = NULL;
|
|
|
|
xmlDocPtr doc = NULL, res = NULL;
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
do {
|
|
|
|
cur = xsltParseStylesheetFile ( ( const xmlChar * )
|
|
|
|
CONV ( styleFileName ) );
|
|
|
|
if ( !cur )
|
|
|
|
{
|
|
|
|
nonParserError = "Cannot parse stylesheet";
|
|
|
|
return false;
|
|
|
|
}
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
ctxt = xmlNewParserCtxt();
|
|
|
|
if ( !ctxt )
|
|
|
|
{
|
|
|
|
nonParserError = _("Cannot create parser context");
|
|
|
|
break;
|
|
|
|
}
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
int flags = XML_PARSE_NOENT | XML_PARSE_DTDLOAD;
|
|
|
|
if ( !netAccess )
|
|
|
|
flags |= XML_PARSE_NONET;
|
|
|
|
if ( utf8DocBuf != NULL )
|
|
|
|
doc = xmlCtxtReadMemory ( ctxt, utf8DocBuf, utf8DocBufSize,
|
|
|
|
CONV ( docUrl ), "UTF-8", flags );
|
|
|
|
else
|
|
|
|
doc = xmlCtxtReadFile ( ctxt, CONV ( docUrl ), NULL, flags );
|
|
|
|
if ( !doc )
|
|
|
|
{
|
|
|
|
nonParserError = "Cannot parse file";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ensure entity warnings are treated as errors
|
|
|
|
if ( !getLastError().empty() )
|
|
|
|
break;
|
|
|
|
|
|
|
|
res = xsltApplyStylesheet ( cur, doc, NULL );
|
|
|
|
if ( !res )
|
|
|
|
{
|
|
|
|
nonParserError = "Cannot apply stylesheet";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
xmlChar *buf = NULL;
|
|
|
|
int size;
|
|
|
|
xmlDocDumpFormatMemoryEnc ( res, &buf, &size, "UTF-8", 1 );
|
|
|
|
if ( buf )
|
|
|
|
{
|
|
|
|
output.append ( ( char * ) buf, size );
|
|
|
|
xmlFree ( buf );
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = true;
|
|
|
|
|
|
|
|
} while ( false );
|
2009-11-06 18:06:12 +01:00
|
|
|
|
|
|
|
xmlFreeDoc ( doc );
|
2013-12-15 15:19:08 +01:00
|
|
|
xmlFreeParserCtxt ( ctxt );
|
2013-12-15 15:21:31 +01:00
|
|
|
xmlFreeDoc ( res );
|
2013-12-15 15:19:08 +01:00
|
|
|
xsltFreeStylesheet ( cur );
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
return ret;
|
2009-11-06 18:06:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool WrapLibxml::bufferWellFormed ( const std::string& buffer )
|
|
|
|
{
|
|
|
|
xmlParserCtxtPtr ctxt = xmlNewParserCtxt();
|
|
|
|
if ( !ctxt )
|
|
|
|
return false;
|
|
|
|
|
2013-12-15 15:19:08 +01:00
|
|
|
int flags = XML_PARSE_DTDLOAD;
|
|
|
|
if ( !netAccess )
|
|
|
|
flags |= XML_PARSE_NONET;
|
|
|
|
xmlDocPtr docPtr = xmlCtxtReadMemory ( ctxt, buffer.c_str(), buffer.size(),
|
|
|
|
"", "UTF-8", flags );
|
2009-11-06 18:06:12 +01:00
|
|
|
bool returnValue = ( docPtr ) ? true : false;
|
|
|
|
|
|
|
|
xmlFreeDoc ( docPtr );
|
|
|
|
xmlFreeParserCtxt ( ctxt );
|
|
|
|
|
|
|
|
return returnValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
int WrapLibxml::saveEncoding (
|
2013-12-16 04:45:20 +01:00
|
|
|
const std::string &utf8Buffer,
|
|
|
|
const wxString &fileNameSource,
|
|
|
|
const wxString &fileNameDestination,
|
|
|
|
wxMemoryBuffer *outputBuffer,
|
|
|
|
const wxString &encoding )
|
2009-11-06 18:06:12 +01:00
|
|
|
{
|
2013-12-16 04:45:20 +01:00
|
|
|
return saveEncoding ( utf8Buffer.c_str(), utf8Buffer.length(),
|
|
|
|
fileNameSource, fileNameDestination, outputBuffer, encoding );
|
|
|
|
}
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-12-16 04:45:20 +01:00
|
|
|
int WrapLibxml::saveEncoding (
|
|
|
|
const wxString &fileNameSource,
|
|
|
|
const wxString &fileNameDestination,
|
|
|
|
const wxString &encoding )
|
|
|
|
{
|
|
|
|
return saveEncoding ( NULL, 0, fileNameSource, fileNameDestination,
|
|
|
|
NULL, encoding );
|
2009-11-06 18:06:12 +01:00
|
|
|
}
|
|
|
|
|
2013-12-16 04:45:20 +01:00
|
|
|
int WrapLibxml::saveEncoding (
|
|
|
|
const char *utf8Buffer,
|
|
|
|
size_t utf8BufferSize,
|
|
|
|
const wxString &fileNameSource,
|
|
|
|
const wxString &fileNameDestination,
|
|
|
|
wxMemoryBuffer *outputBuffer,
|
|
|
|
const wxString &encoding )
|
2009-11-06 18:06:12 +01:00
|
|
|
{
|
|
|
|
xmlParserCtxtPtr ctxt = xmlNewParserCtxt();
|
|
|
|
if ( !ctxt )
|
|
|
|
return -1;
|
|
|
|
|
2013-12-16 04:45:20 +01:00
|
|
|
xmlDocPtr docPtr;
|
|
|
|
int flags = XML_PARSE_DTDLOAD | XML_PARSE_PEDANTIC /*| XML_PARSE_DTDVALID*/;//XML_PARSE_NONET//XML_PARSE_DTDLOAD//0//(netAccess) ? XML_PARSE_DTDLOAD | XML_PARSE_NOENT : XML_PARSE_DTDLOAD | XML_PARSE_NONET | XML_PARSE_NOENT//0
|
|
|
|
if ( !netAccess )
|
|
|
|
flags |= XML_PARSE_NONET;
|
|
|
|
if ( utf8Buffer != NULL )
|
|
|
|
docPtr = xmlCtxtReadMemory ( ctxt, utf8Buffer, utf8BufferSize,
|
|
|
|
CONV ( fileNameSource ), "UTF-8", flags );
|
|
|
|
else
|
|
|
|
docPtr = xmlCtxtReadFile ( ctxt, fileNameSource.c_str(), NULL, flags );
|
2009-11-06 18:06:12 +01:00
|
|
|
if ( !docPtr )
|
|
|
|
{
|
|
|
|
xmlFreeParserCtxt ( ctxt );
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-12-16 04:45:20 +01:00
|
|
|
int result;
|
|
|
|
if ( outputBuffer == NULL )
|
|
|
|
{
|
|
|
|
result = xmlSaveFileEnc (
|
|
|
|
CONV ( fileNameDestination ),
|
|
|
|
docPtr,
|
|
|
|
encoding.utf8_str() );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
xmlChar *buffer;
|
|
|
|
xmlDocDumpMemoryEnc ( docPtr, &buffer, &result,
|
|
|
|
encoding.utf8_str() );
|
|
|
|
outputBuffer->AppendData ( buffer, result );
|
|
|
|
xmlFree ( buffer );
|
|
|
|
}
|
2009-11-06 18:06:12 +01:00
|
|
|
|
|
|
|
xmlFreeDoc ( docPtr );
|
|
|
|
xmlFreeParserCtxt ( ctxt );
|
2013-12-15 15:21:31 +01:00
|
|
|
|
2009-11-06 18:06:12 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2013-12-15 15:21:31 +01:00
|
|
|
wxString WrapLibxml::getLastError()
|
2009-11-06 18:06:12 +01:00
|
|
|
{
|
|
|
|
xmlErrorPtr err = xmlGetLastError();
|
|
|
|
|
|
|
|
if ( !err )
|
2013-12-15 15:19:08 +01:00
|
|
|
return nonParserError;
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-12-15 15:21:31 +01:00
|
|
|
wxString error ( err->message, wxConvLocal );
|
2009-11-06 18:06:12 +01:00
|
|
|
if ( err->int2 )
|
2013-12-15 15:21:31 +01:00
|
|
|
return wxString::Format ( _("Error at line %d, column %d: %s"),
|
|
|
|
err->line, err->int2, error.c_str() );
|
|
|
|
|
|
|
|
return wxString::Format ( _("Error at line %d: %s"),
|
|
|
|
err->line, error.c_str() );
|
2009-11-06 18:06:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
std::pair<int, int> WrapLibxml::getErrorPosition()
|
|
|
|
{
|
|
|
|
xmlErrorPtr err = xmlGetLastError();
|
|
|
|
if ( !err )
|
|
|
|
return std::make_pair ( 1, 1 );
|
|
|
|
|
|
|
|
return std::make_pair (
|
|
|
|
err->line,
|
|
|
|
err->int2 );
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string WrapLibxml::getOutput()
|
|
|
|
{
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
2013-10-26 15:15:42 +02:00
|
|
|
wxString WrapLibxml::catalogResolve
|
|
|
|
( const wxString &publicId
|
|
|
|
, const wxString &systemId
|
|
|
|
)
|
2009-11-06 18:06:12 +01:00
|
|
|
{
|
2013-10-27 15:10:08 +01:00
|
|
|
// According to 7.1.2. Resolution of External Identifiers
|
|
|
|
// from http://www.oasis-open.org/committees/entity/spec-2001-08-06.html,
|
|
|
|
// our catalog may not be used if the system catalog, which is specified
|
|
|
|
// in a delegateSystem entry, is out of date, such as the catalog for
|
|
|
|
// resolving public ID "-//OASIS//DTD DocBook XML V5.0//EN"
|
|
|
|
char *s = ( char * ) xmlACatalogResolve ( ::catalog,
|
|
|
|
( const xmlChar * ) ( const char *) publicId.utf8_str(),
|
|
|
|
( const xmlChar * ) ( const char *) systemId.utf8_str() );
|
|
|
|
if ( s == NULL )
|
2013-11-06 12:43:04 +01:00
|
|
|
{
|
|
|
|
#ifndef __WXMSW__
|
2013-10-27 15:10:08 +01:00
|
|
|
s = ( char * ) xmlCatalogResolve (
|
|
|
|
( const xmlChar * ) ( const char *) publicId.utf8_str(),
|
|
|
|
( const xmlChar * ) ( const char *) systemId.utf8_str() );
|
2013-11-06 12:43:04 +01:00
|
|
|
if ( s == NULL )
|
2013-10-27 15:10:08 +01:00
|
|
|
#endif
|
2013-11-06 12:43:04 +01:00
|
|
|
return wxEmptyString;
|
|
|
|
}
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2012-08-30 16:37:01 +02:00
|
|
|
wxString url ( s, wxConvUTF8 );
|
2013-10-26 15:15:42 +02:00
|
|
|
xmlFree ( s );
|
|
|
|
|
2012-08-30 16:37:01 +02:00
|
|
|
wxFileName file = wxFileSystem::URLToFileName ( url );
|
|
|
|
if ( file.IsFileReadable() )
|
2013-10-26 15:15:42 +02:00
|
|
|
return file.GetFullPath();
|
2009-11-06 18:06:12 +01:00
|
|
|
|
2013-10-26 15:15:42 +02:00
|
|
|
return url;
|
2009-11-06 18:06:12 +01:00
|
|
|
}
|