2 * libxml++ and this file are copyright (C) 2000 by Ari Johnson
3 * (C) 2002-2004 by the libxml dev team and
4 * are covered by the GNU Lesser General Public License, which should be
5 * included with libxml++ as the file COPYING.
8 #include "libxml++/validators/dtdvalidator.h"
9 #include "libxml++/dtd.h"
10 #include "libxml++/nodes/node.h"
11 #include "libxml++/exceptions/internal_error.h"
12 #include "libxml++/exceptions/validity_error.h"
13 #include "libxml++/io/istreamparserinputbuffer.h"
14 #include "libxml++/document.h"
16 #include <libxml/parser.h>
24 struct DtdValidator::Impl
26 Impl() : dtd(nullptr), is_dtd_owner(false), context(nullptr) {}
30 _xmlValidCtxt* context;
34 DtdValidator::DtdValidator()
39 DtdValidator::DtdValidator(const std::string& filename)
45 DtdValidator::DtdValidator(const Glib::ustring& external, const Glib::ustring& system)
48 parse_subset(external, system);
51 DtdValidator::DtdValidator(Dtd* dtd, bool take_ownership)
54 set_dtd(dtd, take_ownership);
57 DtdValidator::~DtdValidator()
62 void DtdValidator::parse_file(const std::string& filename)
64 set_dtd(new Dtd(filename), true);
67 void DtdValidator::parse_subset(const Glib::ustring& external, const Glib::ustring& system)
69 set_dtd(new Dtd(external, system), true);
72 void DtdValidator::parse_memory(const Glib::ustring& contents)
74 std::unique_ptr<Dtd> dtd(new Dtd());
75 dtd->parse_memory(contents);
76 set_dtd(dtd.release(), true);
79 void DtdValidator::parse_stream(std::istream& in)
81 std::unique_ptr<Dtd> dtd(new Dtd());
82 dtd->parse_stream(in);
83 set_dtd(dtd.release(), true);
86 void DtdValidator::set_dtd(Dtd* dtd, bool take_ownership)
90 pimpl_->is_dtd_owner = take_ownership;
93 void DtdValidator::initialize_context()
95 Validator::initialize_context();
99 //Tell the validation context about the callbacks:
100 pimpl_->context->error = &callback_validity_error;
101 pimpl_->context->warning = &callback_validity_warning;
103 //Allow the callback_validity_*() methods to retrieve the C++ instance:
104 pimpl_->context->userData = this;
108 void DtdValidator::release_underlying()
112 pimpl_->context->userData = nullptr; //Not really necessary.
114 xmlFreeValidCtxt(pimpl_->context);
115 pimpl_->context = nullptr;
120 if (pimpl_->is_dtd_owner)
122 pimpl_->dtd = nullptr;
125 Validator::release_underlying();
128 DtdValidator::operator bool() const noexcept
130 return pimpl_->dtd && pimpl_->dtd->cobj();
133 Dtd* DtdValidator::get_dtd()
138 const Dtd* DtdValidator::get_dtd() const
143 void DtdValidator::validate(const Document* document)
147 throw internal_error("Document pointer cannot be 0.");
152 throw internal_error("No DTD to use for validation.");
155 // A context is required at this stage only
156 if (!pimpl_->context)
157 pimpl_->context = xmlNewValidCtxt();
159 if (!pimpl_->context)
161 throw internal_error("Couldn't create validation context");
165 initialize_context();
167 const bool res = (bool)xmlValidateDtd(pimpl_->context, (xmlDoc*)document->cobj(),
168 pimpl_->dtd->cobj());
172 check_for_exception();
173 throw validity_error("Document failed DTD validation\n" + format_xml_error());