[libxml++] Add RelaxNGSchema and RelaxNGValidator



commit cc998a01e532a64f727e2dacabf9d3de5e87c7b0
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date:   Thu Oct 16 13:16:54 2014 +0200

    Add RelaxNGSchema and RelaxNGValidator
    
    * Makefile.am: Add new files.
    * libxml++/libxml++.h: Add new header files.
    * examples/Makefile.am: Add schemavalidation/example.rng.
    * examples/schemavalidation/main.cc: Add test of RelaxNGValidator.
    * examples/schemavalidation/example.rng:
    * libxml++/relaxngschema.[cc|h]:
    * libxml++/validators/relaxngvalidator.[cc|h]: New files.
    
    Thanks to Tjalling Hattink <t hattink fugro nl>, who made other versions
    of the new files, which were attached to bug #737712.

 Makefile.am                             |    4 +
 examples/Makefile.am                    |    1 +
 examples/schemavalidation/example.rng   |  110 ++++++++++++++++++++
 examples/schemavalidation/main.cc       |   15 ++-
 libxml++/libxml++.h                     |    2 +
 libxml++/relaxngschema.cc               |  134 ++++++++++++++++++++++++
 libxml++/relaxngschema.h                |  113 +++++++++++++++++++++
 libxml++/validators/relaxngvalidator.cc |  169 +++++++++++++++++++++++++++++++
 libxml++/validators/relaxngvalidator.h  |  161 +++++++++++++++++++++++++++++
 9 files changed, 706 insertions(+), 3 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 2168a32..69f5336 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -27,6 +27,7 @@ h_root_sources_public = libxml++/libxml++.h \
        libxml++/dtd.h \
        libxml++/keepblanks.h \
        libxml++/noncopyable.h \
+       libxml++/relaxngschema.h \
        libxml++/schema.h \
        libxml++/schemabase.h \
        libxml++/xsdschema.h
@@ -54,6 +55,7 @@ h_parsers_sources_public = libxml++/parsers/parser.h \
        libxml++/parsers/domparser.h \
        libxml++/parsers/textreader.h
 h_validators_sources_public = libxml++/validators/dtdvalidator.h \
+       libxml++/validators/relaxngvalidator.h \
        libxml++/validators/schemavalidator.h \
        libxml++/validators/schemavalidatorbase.h \
        libxml++/validators/validator.h \
@@ -72,6 +74,7 @@ cc_sources = libxml++/attribute.cc \
        libxml++/dtd.cc \
        libxml++/keepblanks.cc \
        libxml++/noncopyable.cc \
+       libxml++/relaxngschema.cc \
        libxml++/schema.cc \
        libxml++/schemabase.cc \
        libxml++/xsdschema.cc \
@@ -99,6 +102,7 @@ cc_sources = libxml++/attribute.cc \
        libxml++/parsers/domparser.cc \
        libxml++/parsers/textreader.cc \
        libxml++/validators/dtdvalidator.cc \
+       libxml++/validators/relaxngvalidator.cc \
        libxml++/validators/schemavalidator.cc \
        libxml++/validators/schemavalidatorbase.cc \
        libxml++/validators/validator.cc \
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 57ebcc9..f73e285 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -135,6 +135,7 @@ dist_noinst_DATA = \
   sax_parser_build_dom/README \
   sax_parser_build_dom/example.xml \
   sax_parser_entities/example.xml \
+  schemavalidation/example.rng \
   schemavalidation/example.xml \
   schemavalidation/example.xsd \
   textreader/example.xml
diff --git a/examples/schemavalidation/example.rng b/examples/schemavalidation/example.rng
new file mode 100644
index 0000000..f17102c
--- /dev/null
+++ b/examples/schemavalidation/example.rng
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Example from XMLSchema recommendation 0 - primer at http://www.w3.org/TR/xmlschema-0/ -->
+<!-- Converted from an XSD schema to a RelaxNG schema at http://debeissat.nicolas.free.fr/XSDtoRNG.php -->
+<rng:grammar xmlns:rng="http://relaxng.org/ns/structure/1.0"; ns=""
+  datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes";>
+
+  <a:documentation xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0";>
+     Purchase order schema for Example.com.
+     Copyright 2000 Example.com. All rights reserved.
+  </a:documentation>
+
+  <rng:start combine="choice">
+    <rng:ref name="purchaseOrder"/>
+  </rng:start>
+
+  <rng:define name="purchaseOrder">
+    <rng:element name="purchaseOrder">
+      <rng:ref name="PurchaseOrderType"/>
+    </rng:element>
+  </rng:define>
+
+  <rng:start combine="choice">
+    <rng:ref name="comment"/>
+  </rng:start>
+  <rng:define name="comment">
+    <rng:element name="comment">
+      <rng:data type="string"/>
+    </rng:element>
+  </rng:define>
+
+  <rng:define name="PurchaseOrderType">
+    <rng:element name="shipTo">
+      <rng:ref name="USAddress"/>
+    </rng:element>
+    <rng:element name="billTo">
+      <rng:ref name="USAddress"/>
+    </rng:element>
+    <rng:optional>
+      <rng:ref name="comment"/>
+    </rng:optional>
+    <rng:element name="items">
+      <rng:ref name="Items"/>
+    </rng:element>
+    <rng:optional>
+      <rng:attribute name="orderDate">
+        <rng:data type="date"/>
+      </rng:attribute>
+    </rng:optional>
+  </rng:define>
+
+  <rng:define name="USAddress">
+    <rng:element name="name">
+      <rng:data type="string"/>
+    </rng:element>
+    <rng:element name="street">
+      <rng:data type="string"/>
+    </rng:element>
+    <rng:element name="city">
+      <rng:data type="string"/>
+    </rng:element>
+    <rng:element name="state">
+      <rng:data type="string"/>
+    </rng:element>
+    <rng:element name="zip">
+      <rng:data type="decimal"/>
+    </rng:element>
+    <rng:optional>
+      <rng:attribute name="country">
+        <rng:data type="NMTOKEN"/>
+      </rng:attribute>
+    </rng:optional>
+  </rng:define>
+
+  <rng:define name="Items">
+    <rng:zeroOrMore>
+      <rng:element name="item">
+        <rng:element name="productName">
+          <rng:data type="string"/>
+        </rng:element>
+        <rng:element name="quantity">
+          <rng:data type="positiveInteger">
+            <rng:param name="maxExclusive">100</rng:param>
+          </rng:data>
+        </rng:element>
+        <rng:element name="USPrice">
+          <rng:data type="decimal"/>
+        </rng:element>
+        <rng:optional>
+          <rng:ref name="comment"/>
+        </rng:optional>
+        <rng:optional>
+          <rng:element name="shipDate">
+            <rng:data type="date"/>
+          </rng:element>
+        </rng:optional>
+        <rng:attribute name="partNum">
+          <rng:ref name="SKU"/>
+        </rng:attribute>
+      </rng:element>
+    </rng:zeroOrMore>
+  </rng:define>
+
+  <!-- Stock Keeping Unit, a code for identifying products -->
+  <rng:define name="SKU">
+    <rng:data type="string">
+      <rng:param name="pattern">\d{3}-[A-Z]{2}</rng:param>
+    </rng:data>
+  </rng:define>
+
+</rng:grammar>
diff --git a/examples/schemavalidation/main.cc b/examples/schemavalidation/main.cc
index 9792a8c..4cfddf3 100644
--- a/examples/schemavalidation/main.cc
+++ b/examples/schemavalidation/main.cc
@@ -33,17 +33,19 @@ int main(int argc, char* argv[])
 
   std::string docfilepath("example.xml");
   std::string xsdschemafilepath("example.xsd");
+  std::string rngschemafilepath("example.rng");
 
-  if (argc != 1 && argc != 3)
+  if (argc != 1 && argc != 4)
   {
-    std::cout << "usage : " << argv[0] << " [document schema.xsd]" << std::endl;
+    std::cout << "usage : " << argv[0] << " [document schema.xsd schema.rng]" << std::endl;
     return EXIT_FAILURE;
   }
 
-  if (argc == 3)
+  if (argc == 4)
   {
     docfilepath = argv[1];
     xsdschemafilepath = argv[2];
+    rngschemafilepath = argv[3];
   }
 
   Glib::ustring phase;
@@ -57,6 +59,9 @@ int main(int argc, char* argv[])
     phase = "XSD";
     xmlpp::XsdValidator xsdvalidator(xsdschemafilepath);
 
+    phase = "RelaxNG";
+    xmlpp::RelaxNGValidator rngvalidator(rngschemafilepath);
+
     try
     {
       phase = "parsing";
@@ -71,6 +76,10 @@ int main(int argc, char* argv[])
       phase = "XSD validating";
       xsdvalidator.validate(parser.get_document());
       std::cout << "Valid document, XsdValidator" << std::endl;
+
+      phase = "RelaxNG validating";
+      rngvalidator.validate(parser.get_document());
+      std::cout << "Valid document, RelaxNGValidator" << std::endl;
     }
     catch (const xmlpp::exception& ex)
     {
diff --git a/libxml++/libxml++.h b/libxml++/libxml++.h
index 18b1ef9..1338b48 100644
--- a/libxml++/libxml++.h
+++ b/libxml++/libxml++.h
@@ -66,9 +66,11 @@
 #include <libxml++/attributedeclaration.h>
 #include <libxml++/attributenode.h>
 #include <libxml++/document.h>
+#include <libxml++/relaxngschema.h>
 #include <libxml++/xsdschema.h>
 #include <libxml++/validators/validator.h>
 #include <libxml++/validators/dtdvalidator.h>
+#include <libxml++/validators/relaxngvalidator.h>
 #include <libxml++/validators/schemavalidator.h>
 #include <libxml++/validators/xsdvalidator.h>
 
diff --git a/libxml++/relaxngschema.cc b/libxml++/relaxngschema.cc
new file mode 100644
index 0000000..a747bf6
--- /dev/null
+++ b/libxml++/relaxngschema.cc
@@ -0,0 +1,134 @@
+/* Copyright (C) 2014 The libxml++ development team
+ *
+ * This file is part of libxml++.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This file was adapted from schema.cc by Fugro Intersite B.V./Tjalling Hattink
+ */
+
+#include <libxml++/relaxngschema.h>
+
+#include <libxml/tree.h>
+#include <libxml/relaxng.h>
+
+namespace
+{
+  // This class holds an xmlRelaxNGParserCtxtPtr and releases it on
+  // destruction. This way, we make sure we don't leak it, not even
+  // when an exception is thrown.
+  class RelaxNGSchemaParserContextHolder
+  {
+  public:
+    RelaxNGSchemaParserContextHolder(xmlRelaxNGParserCtxtPtr ctx): ctx_(ctx) {}
+    ~RelaxNGSchemaParserContextHolder() { if (ctx_) xmlRelaxNGFreeParserCtxt(ctx_); }
+
+  private:
+    xmlRelaxNGParserCtxtPtr ctx_;
+  };
+}
+
+namespace xmlpp
+{
+
+struct RelaxNGSchema::Impl
+{
+  Impl() : schema(0) {}
+
+  _xmlRelaxNG* schema;
+};
+
+  
+RelaxNGSchema::RelaxNGSchema()
+: pimpl_(new Impl)
+{
+}
+
+RelaxNGSchema::RelaxNGSchema(_xmlRelaxNG* schema)
+: pimpl_(new Impl)
+{
+  pimpl_->schema = schema;
+}
+
+RelaxNGSchema::RelaxNGSchema(const Glib::ustring& filename)
+: pimpl_(new Impl)
+{
+  parse_file(filename);
+}
+
+RelaxNGSchema::RelaxNGSchema(const Document* document)
+: pimpl_(new Impl)
+{
+  parse_document(document);
+}
+
+RelaxNGSchema::~RelaxNGSchema()
+{
+  release_underlying();
+}
+
+void RelaxNGSchema::parse_file(const Glib::ustring& filename)
+{
+  parse_context(xmlRelaxNGNewParserCtxt(filename.c_str()));
+}
+
+void RelaxNGSchema::parse_memory(const Glib::ustring& contents)
+{
+  parse_context(xmlRelaxNGNewMemParserCtxt(contents.c_str(), contents.bytes()));
+}
+
+void RelaxNGSchema::parse_document(const Document* document)
+{
+  if (!document)
+    throw parse_error("RelaxNGSchema::parse_document(): document must not be 0.");
+
+  // xmlRelaxNGNewDocParserCtxt() takes a copy of the xmlDoc.
+  parse_context(xmlRelaxNGNewDocParserCtxt(const_cast<xmlDoc*>(document->cobj())));
+}
+
+void RelaxNGSchema::parse_context(_xmlRelaxNGParserCtxt* context)
+{
+  xmlResetLastError();
+  release_underlying();
+
+  if (!context)
+    throw parse_error("RelaxNGSchema::parse_context(): Could not create parser context.\n" + 
format_xml_error());
+  
+  RelaxNGSchemaParserContextHolder holder(context);
+
+  pimpl_->schema = xmlRelaxNGParse(context);
+  if (!pimpl_->schema)
+    throw parse_error("RelaxNGSchema::parse_context(): Schema could not be parsed.\n" + format_xml_error());
+}
+
+_xmlRelaxNG* RelaxNGSchema::cobj()
+{
+  return pimpl_->schema;
+}
+
+const _xmlRelaxNG* RelaxNGSchema::cobj() const
+{
+  return pimpl_->schema;
+}
+
+void RelaxNGSchema::release_underlying()
+{
+  if (pimpl_->schema)
+  {
+    xmlRelaxNGFree(pimpl_->schema);
+    pimpl_->schema = 0;
+  }
+}
+
+} //namespace xmlpp
diff --git a/libxml++/relaxngschema.h b/libxml++/relaxngschema.h
new file mode 100644
index 0000000..befa434
--- /dev/null
+++ b/libxml++/relaxngschema.h
@@ -0,0 +1,113 @@
+/* Copyright (C) 2014 The libxml++ development team
+ *
+ * This file is part of libxml++.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This file was adapted from schema.h by Fugro Intersite B.V./Tjalling Hattink
+ */
+
+#ifndef __LIBXMLPP_RELAXNGSCHEMA_H
+#define __LIBXMLPP_RELAXNGSCHEMA_H
+
+#include <libxml++/schemabase.h>
+#include <libxml++/document.h>
+#include <memory> // std::auto_ptr
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+extern "C" {
+  struct _xmlRelaxNG;
+  struct _xmlRelaxNGParserCtxt;
+}
+#endif //DOXYGEN_SHOULD_SKIP_THIS
+
+namespace xmlpp
+{
+
+/** Represents a RelaxNG schema for validating XML files.
+ * RelaxNG = REgular LAnguage for XML Next Generation
+ *
+ * @newin{2,38}
+ */
+class RelaxNGSchema : public SchemaBase
+{
+public:
+  RelaxNGSchema();
+
+  /** Create a schema from the underlying libxml schema element.
+   * @param schema A pointer to the libxml schema element. The RelaxNGSchema takes
+   *               ownership of the _xmlRelaxNG. The caller must not deallocate it.
+   */
+  explicit RelaxNGSchema(_xmlRelaxNG* schema);
+
+  /** Create a schema from a schema definition file.
+   * The schema must be defined with XML syntax (.rng file). The compact syntax
+   * (.rnc file) is not supported.
+   * @param filename The URL of the schema.
+   * @throws xmlpp::parse_error
+   */
+  explicit RelaxNGSchema(const Glib::ustring& filename);
+
+  /** Create a schema from an XML document.
+   * @param document A preparsed document tree, containing the schema definition.
+   * @throws xmlpp::parse_error
+   */
+  explicit RelaxNGSchema(const Document* document);
+
+  virtual ~RelaxNGSchema();
+
+  /** Parse a schema definition file.
+   * The schema must be defined with XML syntax (.rng file). The compact syntax
+   * (.rnc file) is not supported.
+   *
+   * If another schema has been parsed before, that schema is replaced by the new one.
+   * @param filename The URL of the schema.
+   * @throws xmlpp::parse_error
+   */
+  virtual void parse_file(const Glib::ustring& filename);
+
+  /** Parse a schema definition from a string.
+   * The schema must be defined with XML syntax. The compact syntax is not supported.
+   *
+   * If another schema has been parsed before, that schema is replaced by the new one.
+   * @param contents The schema definition as a string.
+   * @throws xmlpp::parse_error
+   */
+  virtual void parse_memory(const Glib::ustring& contents);
+
+  /** Parse a schema definition from a document.
+   * If another schema has been parsed before, that schema is replaced by the new one.
+   * @param document A preparsed document tree, containing the schema definition.
+   * @throws xmlpp::parse_error
+   */
+  virtual void parse_document(const Document* document);
+
+  /** Access the underlying libxml implementation. */
+  _xmlRelaxNG* cobj();
+
+  /** Access the underlying libxml implementation. */
+  const _xmlRelaxNG* cobj() const;
+
+protected:
+  void release_underlying();
+  void parse_context(_xmlRelaxNGParserCtxt* context);
+
+private:
+  struct Impl;
+  std::auto_ptr<Impl> pimpl_;
+};
+
+} // namespace xmlpp
+
+#endif //__LIBXMLPP_RELAXNGSCHEMA_H
diff --git a/libxml++/validators/relaxngvalidator.cc b/libxml++/validators/relaxngvalidator.cc
new file mode 100644
index 0000000..d16a197
--- /dev/null
+++ b/libxml++/validators/relaxngvalidator.cc
@@ -0,0 +1,169 @@
+/* Copyright (C) 2014 The libxml++ development team
+ *
+ * This file is part of libxml++.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This file was adapted from schemavalidator.cc by Fugro Intersite B.V./Tjalling Hattink
+ */
+
+#include "libxml++/validators/relaxngvalidator.h"
+#include "libxml++/parsers/domparser.h"
+#include "libxml++/relaxngschema.h"
+
+#include <libxml/relaxng.h>
+
+namespace xmlpp
+{
+
+struct RelaxNGValidator::Impl
+{
+  Impl() : schema(0), is_schema_owner(false), context(0) {}
+
+  RelaxNGSchema* schema;
+  bool is_schema_owner;
+  _xmlRelaxNGValidCtxt* context;
+};
+
+
+RelaxNGValidator::RelaxNGValidator()
+: pimpl_(new Impl)
+{
+}
+
+RelaxNGValidator::RelaxNGValidator(const Glib::ustring& filename)
+: pimpl_(new Impl)
+{
+  parse_file(filename);
+}
+
+RelaxNGValidator::RelaxNGValidator(const Document* document)
+: pimpl_(new Impl)
+{
+  parse_document(document);
+}
+
+RelaxNGValidator::RelaxNGValidator(RelaxNGSchema* schema, bool take_ownership)
+: pimpl_(new Impl)
+{
+  set_schema(schema, take_ownership);
+}
+
+RelaxNGValidator::~RelaxNGValidator()
+{
+  release_underlying();
+}
+
+void RelaxNGValidator::parse_file(const Glib::ustring& filename)
+{
+  set_schema(new RelaxNGSchema(filename), true);
+}
+
+void RelaxNGValidator::parse_memory(const Glib::ustring& contents)
+{
+  std::auto_ptr<RelaxNGSchema> schema(new RelaxNGSchema());
+  schema->parse_memory(contents);
+  set_schema(schema.release(), true);
+}
+
+void RelaxNGValidator::parse_document(const Document* document)
+{
+  set_schema(new RelaxNGSchema(document), true);
+}
+
+void RelaxNGValidator::set_schema(RelaxNGSchema* schema, bool take_ownership)
+{
+  release_underlying();
+  pimpl_->schema = schema;
+  pimpl_->is_schema_owner = take_ownership;
+}
+
+void RelaxNGValidator::release_underlying()
+{
+  if (pimpl_->context)
+  {
+    xmlRelaxNGFreeValidCtxt(pimpl_->context);
+    pimpl_->context = 0;
+  }
+
+  if (pimpl_->schema)
+  {
+    if (pimpl_->is_schema_owner)
+      delete pimpl_->schema;
+    pimpl_->schema = 0;
+  }
+
+  SchemaValidatorBase::release_underlying();
+}
+
+RelaxNGSchema* RelaxNGValidator::get_schema()
+{
+  return pimpl_->schema;
+}
+
+const RelaxNGSchema* RelaxNGValidator::get_schema() const
+{
+  return pimpl_->schema;
+}
+
+RelaxNGValidator::operator const void*() const
+{
+  return reinterpret_cast<const void*>(pimpl_->schema && pimpl_->schema->cobj());
+}
+
+
+void RelaxNGValidator::initialize_valid()
+{
+  xmlRelaxNGSetValidErrors(pimpl_->context, &callback_validity_error, &callback_validity_warning, this);
+  SchemaValidatorBase::initialize_valid();
+}
+
+void RelaxNGValidator::validate(const Document* document)
+{
+  if (!document)
+    throw internal_error("RelaxNGValidator::validate(): document must not be 0.");
+
+  if (!*this)
+    throw internal_error("RelaxNGValidator::validate(): Must have a schema to validate document");
+
+  // A context is required at this stage only
+  if (!pimpl_->context)
+    pimpl_->context = xmlRelaxNGNewValidCtxt(pimpl_->schema->cobj());
+
+  if (!pimpl_->context)
+    throw internal_error("RelaxNGValidator::validate(): Could not create validating context");
+
+  xmlResetLastError();
+  initialize_valid();
+
+  const int res = xmlRelaxNGValidateDoc(pimpl_->context, const_cast<xmlDoc*>(document->cobj()));
+  if (res != 0)
+  {
+    check_for_exception();
+
+    Glib::ustring error_str = format_xml_error();
+    if (error_str.empty())
+      error_str = "Error code from xmlRelaxNGValidateDoc(): " + Glib::ustring::format(res);
+    throw validity_error("Document failed RelaxNG schema validation.\n" + error_str);
+  }
+}
+
+void RelaxNGValidator::validate(const Glib::ustring& filename)
+{
+  // There is no xmlRelaxNGValidateFile().
+  DomParser parser(filename);
+  validate(parser.get_document());
+}
+
+} // namespace xmlpp
diff --git a/libxml++/validators/relaxngvalidator.h b/libxml++/validators/relaxngvalidator.h
new file mode 100644
index 0000000..61917a5
--- /dev/null
+++ b/libxml++/validators/relaxngvalidator.h
@@ -0,0 +1,161 @@
+/* Copyright (C) 2014 The libxml++ development team
+ *
+ * This file is part of libxml++.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This file was adapted from schemavalidator.h by Fugro Intersite B.V./Tjalling Hattink
+ */
+
+#ifndef __LIBXMLPP_VALIDATOR_RELAXNGVALIDATOR_H
+#define __LIBXMLPP_VALIDATOR_RELAXNGVALIDATOR_H
+
+#include <libxml++/validators/schemavalidatorbase.h>
+#include <memory> // std::auto_ptr
+
+namespace Glib
+{
+class ustring;
+}
+
+namespace xmlpp
+{
+class Document;
+class RelaxNGSchema;
+
+/** RelaxNG schema validator.
+ * RelaxNG = REgular LAnguage for XML Next Generation
+ *
+ * @newin{2,38}
+ */
+class RelaxNGValidator : public SchemaValidatorBase
+{
+public:
+  RelaxNGValidator();
+
+  /** Create a validator and parse a schema definition file.
+   * The schema must be defined with XML syntax (.rng file). The compact syntax
+   * (.rnc file) is not supported.
+   * @param filename The URL of the schema.
+   * @throws xmlpp::parse_error
+   */
+  explicit RelaxNGValidator(const Glib::ustring& filename);
+
+  /** Create a validator and parse a schema definition document.
+   * @param document A preparsed document tree, containing the schema definition.
+   * @throws xmlpp::parse_error
+   */
+  explicit RelaxNGValidator(const Document* document);
+
+  /** Create a validator.
+   * @param schema A pointer to the schema to use when validating XML documents.
+   * @param take_ownership If <tt>true</tt>, the validator takes ownership of
+   *        the schema. The caller must not delete it.<br>
+   *        If <tt>false</tt>, the validator does not take ownership of the schema.
+   *        The caller must guarantee that the schema exists as long as the
+   *        validator keeps a pointer to it. The caller is responsible for
+   *        deleting the schema when it's no longer needed.
+   */
+  explicit RelaxNGValidator(RelaxNGSchema* schema, bool take_ownership);
+
+  virtual ~RelaxNGValidator();
+
+  /** Parse a schema definition file.
+   * The schema must be defined with XML syntax (.rng file). The compact syntax
+   * (.rnc file) is not supported.
+   *
+   * If the validator already contains a schema, that schema is released
+   * (deleted if the validator owns the schema).
+   * @param filename The URL of the schema.
+   * @throws xmlpp::parse_error
+   */
+  virtual void parse_file(const Glib::ustring& filename);
+
+  /** Parse a schema definition from a string.
+   * The schema must be defined with XML syntax. The compact syntax is not supported.
+   *
+   * If the validator already contains a schema, that schema is released
+   * (deleted if the validator owns the schema).
+   * @param contents The schema definition as a string.
+   * @throws xmlpp::parse_error
+   */
+  virtual void parse_memory(const Glib::ustring& contents);
+
+  /** Parse a schema definition from a document.
+   * If the validator already contains a schema, that schema is released
+   * (deleted if the validator owns the schema).
+   * @param document A preparsed document tree, containing the schema definition.
+   * @throws xmlpp::parse_error
+   */
+  virtual void parse_document(const Document* document);
+
+  /** Set a schema.
+   * If the validator already contains a schema, that schema is released
+   * (deleted if the validator owns the schema).
+   * @param schema A pointer to the schema to use when validating XML documents.
+   * @param take_ownership If <tt>true</tt>, the validator takes ownership of
+   *        the schema. The caller must not delete it.<br>
+   *        If <tt>false</tt>, the validator does not take ownership of the schema.
+   *        The caller must guarantee that the schema exists as long as the
+   *        validator keeps a pointer to it. The caller is responsible for
+   *        deleting the schema when it's no longer needed.
+   */
+  void set_schema(RelaxNGSchema* schema, bool take_ownership);
+
+  /** Test whether a schema has been parsed.
+   * For instance
+   * @code
+   * if (relaxng_validator)
+   *   do_something();
+   * @endcode
+   */
+  virtual operator BoolExpr() const;
+
+  /** Get the schema.
+   * @returns A pointer to the schema, or <tt>0</tt>.
+   */
+  RelaxNGSchema* get_schema();
+
+  /** Get the schema.
+   * @returns A pointer to the schema, or <tt>0</tt>.
+   */
+  const RelaxNGSchema* get_schema() const;
+
+  /** Validate a document, using a previously parsed schema.
+   * @param document Pointer to the document.
+   * @throws xmlpp::internal_error
+   * @throws xmlpp::validity_error
+   */
+  virtual void validate(const Document* document);
+
+  /** Validate an XML file, using a previously parsed schema.
+   * @param filename The URL of the XML file.
+   * @throws xmlpp::internal_error
+   * @throws xmlpp::parse_error
+   * @throws xmlpp::validity_error
+   */
+  virtual void validate(const Glib::ustring& filename);
+
+protected:
+  virtual void initialize_valid();
+  virtual void release_underlying();
+
+private:
+  struct Impl;
+  std::auto_ptr<Impl> pimpl_;
+};
+
+} // namespace xmlpp
+
+#endif //__LIBXMLPP_VALIDATOR_RELAXNGVALIDATOR_H


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]