Imported Upstream version 2.91.2
[platform/upstream/libxml++.git] / libxml++ / relaxngschema.cc
1 /* Copyright (C) 2014 The libxml++ development team
2  *
3  * This file is part of libxml++.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * This file was adapted from schema.cc by Fugro Intersite B.V./Tjalling Hattink
19  */
20
21 #include <libxml++/relaxngschema.h>
22
23 #include <libxml/tree.h>
24 #include <libxml/relaxng.h>
25
26 namespace
27 {
28   // This class holds an xmlRelaxNGParserCtxtPtr and releases it on
29   // destruction. This way, we make sure we don't leak it, not even
30   // when an exception is thrown.
31   class RelaxNGSchemaParserContextHolder
32   {
33   public:
34     RelaxNGSchemaParserContextHolder(xmlRelaxNGParserCtxtPtr ctx): ctx_(ctx) {}
35     ~RelaxNGSchemaParserContextHolder() { if (ctx_) xmlRelaxNGFreeParserCtxt(ctx_); }
36
37   private:
38     xmlRelaxNGParserCtxtPtr ctx_;
39   };
40 }
41
42 namespace xmlpp
43 {
44
45 struct RelaxNGSchema::Impl
46 {
47   Impl() : schema(nullptr) {}
48
49   _xmlRelaxNG* schema;
50 };
51
52   
53 RelaxNGSchema::RelaxNGSchema()
54 : pimpl_(new Impl)
55 {
56 }
57
58 RelaxNGSchema::RelaxNGSchema(_xmlRelaxNG* schema)
59 : pimpl_(new Impl)
60 {
61   pimpl_->schema = schema;
62 }
63
64 RelaxNGSchema::RelaxNGSchema(const std::string& filename)
65 : pimpl_(new Impl)
66 {
67   parse_file(filename);
68 }
69
70 RelaxNGSchema::RelaxNGSchema(const Document* document)
71 : pimpl_(new Impl)
72 {
73   parse_document(document);
74 }
75
76 RelaxNGSchema::~RelaxNGSchema()
77 {
78   release_underlying();
79 }
80
81 void RelaxNGSchema::parse_file(const std::string& filename)
82 {
83   parse_context(xmlRelaxNGNewParserCtxt(filename.c_str()));
84 }
85
86 void RelaxNGSchema::parse_memory(const Glib::ustring& contents)
87 {
88   parse_context(xmlRelaxNGNewMemParserCtxt(contents.c_str(), contents.bytes()));
89 }
90
91 void RelaxNGSchema::parse_document(const Document* document)
92 {
93   if (!document)
94     throw parse_error("RelaxNGSchema::parse_document(): document must not be nullptr.");
95
96   // xmlRelaxNGNewDocParserCtxt() takes a copy of the xmlDoc.
97   parse_context(xmlRelaxNGNewDocParserCtxt(const_cast<xmlDoc*>(document->cobj())));
98 }
99
100 void RelaxNGSchema::parse_context(_xmlRelaxNGParserCtxt* context)
101 {
102   xmlResetLastError();
103   release_underlying();
104
105   if (!context)
106     throw parse_error("RelaxNGSchema::parse_context(): Could not create parser context.\n" + format_xml_error());
107   
108   RelaxNGSchemaParserContextHolder holder(context);
109
110   pimpl_->schema = xmlRelaxNGParse(context);
111   if (!pimpl_->schema)
112     throw parse_error("RelaxNGSchema::parse_context(): Schema could not be parsed.\n" + format_xml_error());
113 }
114
115 _xmlRelaxNG* RelaxNGSchema::cobj()
116 {
117   return pimpl_->schema;
118 }
119
120 const _xmlRelaxNG* RelaxNGSchema::cobj() const
121 {
122   return pimpl_->schema;
123 }
124
125 void RelaxNGSchema::release_underlying()
126 {
127   if (pimpl_->schema)
128   {
129     xmlRelaxNGFree(pimpl_->schema);
130     pimpl_->schema = nullptr;
131   }
132 }
133
134 } //namespace xmlpp