Commit 3718b844 authored by Christophe de Vienne's avatar Christophe de Vienne Committed by Christophe de Vienne

Integrated dtdvalidator patch proposed by Guillaume Arreckx. Modified a

2004-05-28  Christophe de Vienne <cdevienne@netcourrier>

	* configure.in, examples/Makefile.am, examples/dtdvalidation/Makefile.am,
	examples/dtdvalidation/example.dtd, examples/dtdvalidation/main.cc,
	libxml++/Makefile.am, libxml++/dtd.[h|cc], libxml++/io/Makefile.am,
	libxml++/io/istreamparserinputbuffer.[h|cc],
	libxml++/io/parserinputbuffer.[h|cc],
	libxml++/libxml++.h, libxml++/validators/Makefile.am,
	libxml++/validators/dtdvalidator.[h|cc]
	libxml++/validators/validator.[h|cc]:
	Integrated dtdvalidator patch proposed by Guillaume Arreckx.
	Modified a bit the patch:
	- renamed *.cpp -> *.cc
	- fixed a few comments which where copy/paste from other files
	- replaced std::string with Glib::ustring
	- Added Dtd::cobj, since the patch rely on it.
	- added a validaty_error as suggested by jon
parent 47b34e0d
2004-05-28 Christophe de Vienne <cdevienne@netcourrier>
* configure.in, examples/Makefile.am, examples/dtdvalidation/Makefile.am,
examples/dtdvalidation/example.dtd, examples/dtdvalidation/main.cc,
libxml++/Makefile.am, libxml++/dtd.[h|cc], libxml++/io/Makefile.am,
libxml++/io/istreamparserinputbuffer.[h|cc],
libxml++/io/parserinputbuffer.[h|cc],
libxml++/libxml++.h, libxml++/validators/Makefile.am,
libxml++/validators/dtdvalidator.[h|cc]
libxml++/validators/validator.[h|cc]:
Integrated dtdvalidator patch proposed by Guillaume Arreckx.
Modified a bit the patch:
- renamed *.cpp -> *.cc
- fixed a few comments which where copy/paste from other files
- replaced std::string with Glib::ustring
- Added Dtd::cobj, since the patch rely on it.
- added a validaty_error as suggested by jon
2004-04-26 Christophe de VIENNE <cdevienne@netcourrier.com>
* libxml++/nodes/contentnode.cc: Fixed set_content which used xmlNodeAddContent
......
2.7.0:
* Added Validator and DtdValidator (Guillaume Arreckx)
2004-05-05 2.6.1:
* Fixed an issue (#141824) with Glib::ustring.
......
......@@ -53,6 +53,7 @@ AC_OUTPUT(
libxml++/exceptions/Makefile
libxml++/nodes/Makefile
libxml++/io/Makefile
libxml++/validators/Makefile
docs/Makefile
docs/reference/Makefile
......@@ -70,6 +71,7 @@ AC_OUTPUT(
examples/sax_exception/Makefile
examples/import_node/Makefile
examples/textreader/Makefile
examples/dtdvalidation/Makefile
win32_msvc6/Makefile
win32_msvc6/examples/Makefile
......
SUBDIRS = dom_build dom_parser dom_parse_entities dom_read_write dom_xpath \
sax_parser sax_parser_entities sax_exception sax_parser_build_dom \
import_node textreader
import_node textreader dtdvalidation
EXTRA_DIST = README Makefile.am_fragment
include $(top_srcdir)/examples/Makefile.am_fragment
#Build the executable, but don't install it.
noinst_PROGRAMS = example
#List of source files needed to build the executable:
example_SOURCES = main.cc
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
DTD for libxml++ example.
-->
<!ELEMENT example (examplechild)+ >
<!ELEMENT examplechild (child_of_child)+ >
<!ATTLIST examplechild
id CDATA #REQUIRED
>
<!ELEMENT child_of_child EMPTY >
// -*- C++ -*-
/* main.cc
*
* Copyright (C) 2002 The libxml++ development team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <libxml++/libxml++.h>
#include <iostream>
int main(int argc, char* argv[])
{
Glib::ustring dtdfilepath;
if(argc > 1)
dtdfilepath = argv[1]; //Allow the user to specify a different dtd file to use.
else
dtdfilepath = "example.dtd";
xmlpp::Document document;
xmlpp::Element* nodeRoot = document.create_root_node("incorrect");
try
{
xmlpp::DtdValidator validator( dtdfilepath );
try {
validator.validate( &document );
std::cout << "Validation successfull" << std::endl;
}
catch( const xmlpp::validity_error& )
{
std::cout << "Error validating the document" << std::endl;
}
xmlpp::Element* nodeRoot = document.create_root_node("example");
xmlpp::Element * child = document.get_root_node()->add_child("examplechild");
child->set_attribute("id", "an_id");
child->add_child("child_of_child");
try
{
xmlpp::DtdValidator validator( dtdfilepath );
validator.validate( &document );
std::cout << "Validation successfull" << std::endl;
}
catch( const xmlpp::validity_error& )
{
std::cout << "Error validating the document" << std::endl;
}
}
catch( const xmlpp::parse_error& )
{
std::cerr << "Error parsing the dtd" << std::endl;
}
}
SUBDIRS = parsers exceptions nodes io
SUBDIRS = parsers exceptions nodes io validators
INCLUDES = -I$(top_srcdir) @LIBXML_CFLAGS@
......@@ -11,6 +11,7 @@ lib_LTLIBRARIES = libxml++-2.6.la
libxml___2_6_la_LDFLAGS = -version-info $(GENERIC_LIBRARY_VERSION)
libxml___2_6_la_LIBADD = @LIBXML_LIBS@ \
parsers/libparsers.la \
validators/libvalidators.la \
exceptions/libexceptions.la \
nodes/libnodes.la \
io/libio.la
......
......@@ -36,4 +36,14 @@ Glib::ustring Dtd::get_system_id() const
return (char*)impl_->SystemID;
}
_xmlDtd* Dtd::cobj()
{
return impl_;
}
const _xmlDtd* Dtd::cobj() const
{
return impl_;
}
} //namespace xmlpp
......@@ -33,6 +33,11 @@ public:
Glib::ustring get_external_id() const;
Glib::ustring get_system_id() const;
/** Access the underlying libxml implementation. */
_xmlDtd* cobj();
/** Access the underlying libxml implementation. */
const _xmlDtd* cobj() const;
private:
_xmlDtd* impl_;
};
......
INCLUDES = -I$(top_srcdir) @LIBXML_CFLAGS@
h_sources_public = outputbuffer.h ostreamoutputbuffer.h
h_sources_public = \
istreamparserinputbuffer.h \
outputbuffer.h \
ostreamoutputbuffer.h \
parserinputbuffer.h
h_sources_private =
cc_sources = outputbuffer.cc ostreamoutputbuffer.cc
cc_sources = \
istreamparserinputbuffer.cc \
outputbuffer.cc \
ostreamoutputbuffer.cc \
parserinputbuffer.cc
cc_sources_private =
noinst_LTLIBRARIES = libio.la
......
/* istreamparserinputbuffer
* this file is part of libxml++
*
* copyright (C) 2003 by libxml++ developer's team
*
* this file is covered by the GNU Lesser General Public License,
* which should be included with libxml++ as the file COPYING.
*/
#include <libxml++/io/istreamparserinputbuffer.h>
namespace xmlpp
{
IStreamParserInputBuffer::IStreamParserInputBuffer(
std::istream & input)
: ParserInputBuffer(), input_(input)
{
}
IStreamParserInputBuffer::~IStreamParserInputBuffer()
{
}
int IStreamParserInputBuffer::do_read(
char * buffer,
int len)
{
int l=0;
if(input_)
{
// This is the correct statement - but gcc 2.95.3 lacks this method
//l = input_.readsome(buffer, len);
input_.read(buffer, len);
l = input_.gcount();
}
return l;
}
bool IStreamParserInputBuffer::do_close()
{
return input_;
}
};
/* inputstreamparserinputbuffer.h
* this file is part of libxml++
*
* copyright (C) 2003 by libxml++ developer's team
*
* this file is covered by the GNU Lesser General Public License,
* which should be included with libxml++ as the file COPYING.
*/
#ifndef __LIBXMLPP_ISTREAMPARSEROUTPUTBUFFER_H
#define __LIBXMLPP_ISTREAMPARSEROUTPUTBUFFER_H
#include <libxml++/io/parserinputbuffer.h>
#include <istream>
namespace xmlpp
{
class IStreamParserInputBuffer: public ParserInputBuffer
{
public:
/**
* @param input The istream datas will be read from
*/
IStreamParserInputBuffer(std::istream& input);
virtual ~IStreamParserInputBuffer();
private:
virtual int do_read(char * buffer, int len);
virtual bool do_close();
std::istream& input_;
};
};
#endif
/* document.h
* this file is part of libxml++
*
* copyright (C) 2003 by libxml++ developer's team
*
* this file is covered by the GNU Lesser General Public License,
* which should be included with libxml++ as the file COPYING.
*/
#include <libxml++/io/parserinputbuffer.h>
#include <libxml++/exceptions/internal_error.h>
#include <libxml/xmlIO.h>
namespace xmlpp
{
struct ParserInputBufferCallback
{
static int on_read(void * context, char * buffer, int len)
{
ParserInputBuffer * tmp = static_cast<ParserInputBuffer*>(context);
return tmp->do_read(buffer, len);
}
static int on_close(void * context)
{
ParserInputBuffer * tmp = static_cast<ParserInputBuffer*>(context);
return tmp->do_close();
}
};
ParserInputBuffer::ParserInputBuffer()
{
impl_ = xmlParserInputBufferCreateIO(
&ParserInputBufferCallback::on_read,
&ParserInputBufferCallback::on_close,
static_cast<void*>(this),
XML_CHAR_ENCODING_NONE);
if(impl_ == NULL)
{
throw internal_error("Cannot initialise underlying xmlParserInputBuffer");
}
}
ParserInputBuffer::~ParserInputBuffer()
{
}
bool ParserInputBuffer::on_close()
{
bool result = do_close();
// the underlying structure is being freed by libxml, the pointer will soon be
// invalid.
impl_ = 0;
return result;
}
int ParserInputBuffer::on_read(
char * buffer,
int len)
{
return do_read(buffer, len);
}
bool ParserInputBuffer::do_close()
{
return true;
}
_xmlParserInputBuffer* ParserInputBuffer::cobj()
{
return impl_;
}
const _xmlParserInputBuffer* ParserInputBuffer::cobj() const
{
return impl_;
}
};
/* parserinputbuffer.h
* this file is part of libxml++
*
* copyright (C) 2003 by libxml++ developer's team
*
* this file is covered by the GNU Lesser General Public License,
* which should be included with libxml++ as the file COPYING.
*/
#ifndef __LIBXMLPP_PARSERINPUTBUFFER_H
#define __LIBXMLPP_PARSERINPUTBUFFER_H
#include <string>
#include <libxml++/noncopyable.h>
extern "C"
{
struct _xmlParserInputBuffer;
};
namespace xmlpp
{
struct ParserInputBufferCallback;
/** Base class for xmlParserInputBuffer wrapper
*
* It can be herited to create a new output buffer.
* A child class has to override do_write, and eventually
* do_close if some actions are required before buffer closing.
*/
class ParserInputBuffer: public NonCopyable
{
public:
ParserInputBuffer();
virtual ~ParserInputBuffer();
public:
/** gives an access to the underlying libxml structure to the children
*/
_xmlParserInputBuffer* cobj();
/** gives an access to the underlying libxml structure to the children
*/
const _xmlParserInputBuffer* cobj() const;
private:
int on_read(char * buffer, int len);
bool on_close();
/** Function called when some data are read from the buffer.
* @param buffer The datas encoded in the charset given to the constructor
* @param len bytes to read
* @return Number of bytes read
*
* This function MUST be overriden in herited classes.
*/
virtual int do_read(char * buffer, int len) = 0;
/** Function called before closing the buffer.
* Herited classes should override it if some actions are required before
* closing the buffer, instead of doing them in the destructor.
*/
virtual bool do_close();
/**
* Underlying libxml2 structure.
*/
_xmlParserInputBuffer* impl_;
friend struct ParserInputBufferCallback;
};
};
#endif
......@@ -18,5 +18,7 @@
#include <libxml++/nodes/textnode.h>
#include <libxml++/attribute.h>
#include <libxml++/document.h>
#include <libxml++/validators/validator.h>
#include <libxml++/validators/dtdvalidator.h>
#endif //__LIBXMLCPP_H
INCLUDES = -I$(top_srcdir) @LIBXML_CFLAGS@
h_sources_public = validator.h dtdvalidator.h
cc_sources = validator.cc dtdvalidator.cc
noinst_LTLIBRARIES = libvalidators.la
libvalidators_la_SOURCES = $(h_sources_public) $(cc_sources)
# Install the headers:
library_includedir=$(includedir)/libxml++-2.6/libxml++/validators
library_include_HEADERS = $(h_sources_public)
/* dtdvalidator.cpp
* libxml++ and this file are copyright (C) 2000 by Ari Johnson
* (C) 2002-2004 by the libxml dev team and
* are covered by the GNU Lesser General Public License, which should be
* included with libxml++ as the file COPYING.
*/
#include "libxml++/validators/dtdvalidator.h"
#include "libxml++/dtd.h"
#include "libxml++/nodes/element.h"
#include "libxml++/nodes/textnode.h"
#include "libxml++/nodes/commentnode.h"
#include "libxml++/keepblanks.h"
#include "libxml++/exceptions/internal_error.h"
#include "libxml++/io/istreamparserinputbuffer.h"
#include <libxml/parserInternals.h>//For xmlCreateFileParserCtxt().
#include <sstream>
#include <iostream>
namespace xmlpp
{
DtdValidator::DtdValidator()
: dtd_(0)
{
}
DtdValidator::DtdValidator(const Glib::ustring& file)
: dtd_(0)
{
parse_subset("",file);
}
DtdValidator::DtdValidator(const Glib::ustring& external,const Glib::ustring& system)
: dtd_(0)
{
parse_subset(external,system);
}
DtdValidator::~DtdValidator()
{
release_underlying();
Validator::release_underlying();
}
void DtdValidator::parse_file(const Glib::ustring& filename)
{
parse_subset("",filename);
}
void DtdValidator::parse_subset(const Glib::ustring& external,const Glib::ustring& system)
{
release_underlying(); // Free any existing dtd.
xmlDtd* dtd = xmlParseDTD(
external.empty() ? 0 : (const xmlChar *)external.c_str(),
system.empty() ? 0 : (const xmlChar *)system.c_str());
if ( ! dtd )
throw parse_error("Dtd could not be parsed");
dtd_ = static_cast<Dtd*>(dtd->_private);
}
void DtdValidator::parse_memory(const Glib::ustring& contents)
{
// Prepare an istream with buffer
std::istringstream is( contents );
parse_stream( is );
}
void DtdValidator::parse_stream(std::istream& in)
{
release_underlying(); //Free any existing document.
IStreamParserInputBuffer ibuff( in );
xmlDtd* dtd = xmlIOParseDTD( 0, ibuff.cobj(), XML_CHAR_ENCODING_UTF8 );
if ( ! dtd )
throw parse_error("Dtd could not be parsed");
dtd_ = static_cast<Dtd*>(dtd->_private);
}
void DtdValidator::release_underlying()
{
if(dtd_)
{
xmlFreeDtd(dtd_->cobj());
dtd_ = 0;
}
}
DtdValidator::operator bool() const
{
return dtd_ != 0;
}
Dtd* DtdValidator::get_dtd()
{
return dtd_;
}
const Dtd* DtdValidator::get_dtd() const
{
return dtd_;
}
bool DtdValidator::validate(const Document* doc)
{
// A context is required at this stage only
if (!valid_)
valid_ = xmlNewValidCtxt();
if(!valid_)
{
throw internal_error("Couldn't create parsing context");
}
if (!doc)
throw internal_error("Document pointer cannot be 0");
initialize_valid();
bool res = (bool)xmlValidateDtd( valid_, (xmlDoc*)doc->cobj(), dtd_->cobj() );
if(res == 0)
{
check_for_exception();
throw validity_error("Document failed Dtd validation");
}
return res;
}
} // namespace xmlpp
/* xml++.h
* libxml++ and this file are copyright (C) 2000 by Ari Johnson,
* (C) 2002-2004 by the libxml dev team and
* are covered by the GNU Lesser General Public License, which should be
* included with libxml++ as the file COPYING.
*/
#ifndef __LIBXMLPP_PARSERS_DTDVALIDATOR_H
#define __LIBXMLPP_PARSERS_DTDVALIDATOR_H
#include <libxml++/validators/validator.h>
#include <libxml++/dtd.h>
#include <libxml++/document.h>
namespace xmlpp {
/** XML DOM parser.
*
*/
class DtdValidator : public Validator
{
public:
DtdValidator();
explicit DtdValidator(const Glib::ustring& file);
explicit DtdValidator(const Glib::ustring& external,const Glib::ustring& system);
virtual ~DtdValidator();
virtual void parse_subset(const Glib::ustring& external,const Glib::ustring& system);
virtual void parse_file(const Glib::ustring& filename);
virtual void parse_memory(const Glib::ustring& contents);
virtual void parse_stream(std::istream& in);
/** Test whether a document has been parsed.
*/
operator bool() const;
Dtd* get_dtd();
const Dtd* get_dtd() const;
bool validate(const Document* doc);
protected:
virtual void release_underlying();
Dtd* dtd_;
};
} // namespace xmlpp
#endif //__LIBXMLPP_PARSERS_DTDVALIDATOR_H
/* xml++.cc
* libxml++ and this file are copyright (C) 2000 by Ari Johnson
* (C) 2002-2004 by the libxml dev team and
* are covered by the GNU Lesser General Public License, which should be
* included with libxml++ as the file COPYING.
*/
#include "libxml++/validators/validator.h"
#include <libxml/parser.h>
#include <cstdarg> //For va_list.
namespace xmlpp {
Validator::Validator()
: valid_(0), exception_(0)
{
}
Validator::~Validator()
{
release_underlying();
}
void Validator::initialize_valid()
{
//Tell the validity valid about the callbacks:
//(These are only called if validation is on - see above)
valid_->error = &callback_validity_error;
valid_->warning = &callback_validity_warning;
//Allow the callback_validity_*() methods to retrieve the C++ instance:
valid_->userData = this;
//Clear these temporary buffers too:
validate_error_.erase();
validate_warning_.erase();
}
void Validator::release_underlying()
{
if(valid_)
{
valid_->userData = 0; //Not really necessary.
xmlFreeValidCtxt(valid_);
valid_ = 0;
}
}
void Validator::on_validity_error(const Glib::ustring& message)
{
//Throw an exception later when the whole message has been received:
validate_error_ += message;
}
void Validator::on_validity_warning(const Glib::ustring& message)
{
//Throw an exception later when the whole message has been received:
validate_warning_ += message;
}
void Validator::check_for_validity_messages()
{
if(!validate_error_.empty())
{
if(!exception_)
exception_ = new validity_error("Validity error:\n" + validate_error_);
validate_error_.erase();