blob: 35a8f4e8ca8edd7dc209f6f7c941d8e3c2a99231 [file] [log] [blame]
Georges-Henri Baron326a31d2012-06-28 12:05:09 +02001/*
David Wagnerb76c9d62014-02-05 18:30:24 +01002 * Copyright (c) 2011-2014, Intel Corporation
3 * All rights reserved.
Georges-Henri Baron326a31d2012-06-28 12:05:09 +02004 *
David Wagnerb76c9d62014-02-05 18:30:24 +01005 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
Georges-Henri Baron326a31d2012-06-28 12:05:09 +02007 *
David Wagnerb76c9d62014-02-05 18:30:24 +01008 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation and/or
13 * other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors
16 * may be used to endorse or promote products derived from this software without
17 * specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Patrick Benavoli68a91282011-08-31 11:23:23 +020029 */
Georges-Henri Baroncec86c12012-09-04 17:30:28 +020030
Georges-Henri Baron326a31d2012-06-28 12:05:09 +020031#include "XmlDocSource.h"
Patrick Benavoli68a91282011-08-31 11:23:23 +020032#include <libxml/tree.h>
Georges-Henri Baroncec86c12012-09-04 17:30:28 +020033#include <libxml/xmlschemas.h>
Patrick Benavoli68a91282011-08-31 11:23:23 +020034#include <stdlib.h>
35
Sebastien Gonzalved9526492014-02-20 22:28:03 +010036using std::string;
37
Patrick Benavoli68a91282011-08-31 11:23:23 +020038// Schedule for libxml2 library
Georges-Henri Baron326a31d2012-06-28 12:05:09 +020039bool CXmlDocSource::_bLibXml2CleanupScheduled;
Patrick Benavoli68a91282011-08-31 11:23:23 +020040
Mattijs Korpershoek31418912014-04-08 14:05:21 +020041CXmlDocSource::CXmlDocSource(_xmlDoc *pDoc, _xmlNode *pRootNode,
42 bool bValidateWithSchema) :
Georges-Henri Baroncec86c12012-09-04 17:30:28 +020043 _pDoc(pDoc),
44 _pRootNode(pRootNode),
45 _strXmlSchemaFile(""),
46 _strRootElementType(""),
47 _strRootElementName(""),
48 _strNameAttrituteName(""),
Mattijs Korpershoek31418912014-04-08 14:05:21 +020049 _bNameCheck(false),
50 _bValidateWithSchema(bValidateWithSchema)
Patrick Benavoli68a91282011-08-31 11:23:23 +020051{
Georges-Henri Baroncec86c12012-09-04 17:30:28 +020052 init();
53}
Patrick Benavoli68a91282011-08-31 11:23:23 +020054
Georges-Henri Baroncec86c12012-09-04 17:30:28 +020055CXmlDocSource::CXmlDocSource(_xmlDoc *pDoc,
56 const string& strXmlSchemaFile,
57 const string& strRootElementType,
58 const string& strRootElementName,
59 const string& strNameAttrituteName) :
60 _pDoc(pDoc),
61 _pRootNode(NULL),
62 _strXmlSchemaFile(strXmlSchemaFile),
63 _strRootElementType(strRootElementType),
64 _strRootElementName(strRootElementName),
65 _strNameAttrituteName(strNameAttrituteName),
Mattijs Korpershoek31418912014-04-08 14:05:21 +020066 _bNameCheck(true),
67 _bValidateWithSchema(false)
Georges-Henri Baroncec86c12012-09-04 17:30:28 +020068{
69 init();
70}
Patrick Benavoli68a91282011-08-31 11:23:23 +020071
Georges-Henri Baroncec86c12012-09-04 17:30:28 +020072CXmlDocSource::CXmlDocSource(_xmlDoc* pDoc,
73 const string& strXmlSchemaFile,
Mattijs Korpershoek31418912014-04-08 14:05:21 +020074 const string& strRootElementType,
75 bool bValidateWithSchema) :
Georges-Henri Baroncec86c12012-09-04 17:30:28 +020076 _pDoc(pDoc), _pRootNode(NULL),
77 _strXmlSchemaFile(strXmlSchemaFile),
78 _strRootElementType(strRootElementType),
79 _strRootElementName(""),
80 _strNameAttrituteName(""),
Mattijs Korpershoek31418912014-04-08 14:05:21 +020081 _bNameCheck(false),
82 _bValidateWithSchema(bValidateWithSchema)
83{
84 init();
85}
86
87CXmlDocSource::CXmlDocSource(_xmlDoc *pDoc,
88 const string& strXmlSchemaFile,
89 const string& strRootElementType,
90 const string& strRootElementName,
91 const string& strNameAttrituteName,
92 bool bValidateWithSchema) :
93 _pDoc(pDoc),
94 _pRootNode(NULL),
95 _strXmlSchemaFile(strXmlSchemaFile),
96 _strRootElementType(strRootElementType),
97 _strRootElementName(strRootElementName),
98 _strNameAttrituteName(strNameAttrituteName),
99 _bNameCheck(true),
100 _bValidateWithSchema(bValidateWithSchema)
Georges-Henri Baroncec86c12012-09-04 17:30:28 +0200101{
102 init();
Patrick Benavoli68a91282011-08-31 11:23:23 +0200103}
104
Georges-Henri Baron326a31d2012-06-28 12:05:09 +0200105CXmlDocSource::~CXmlDocSource()
Patrick Benavoli68a91282011-08-31 11:23:23 +0200106{
Georges-Henri Baron326a31d2012-06-28 12:05:09 +0200107 if (_pDoc) {
108 // Free XML doc
109 xmlFreeDoc(_pDoc);
110 _pDoc = NULL;
111 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200112}
113
Georges-Henri Baron326a31d2012-06-28 12:05:09 +0200114void CXmlDocSource::getRootElement(CXmlElement& xmlRootElement) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200115{
116 xmlRootElement.setXmlElement(_pRootNode);
117}
118
Georges-Henri Baron326a31d2012-06-28 12:05:09 +0200119string CXmlDocSource::getRootElementName() const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200120{
121 return (const char*)_pRootNode->name;
122}
123
Georges-Henri Baron326a31d2012-06-28 12:05:09 +0200124string CXmlDocSource::getRootElementAttributeString(const string& strAttributeName) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200125{
126 CXmlElement topMostElement(_pRootNode);
127
128 return topMostElement.getAttributeString(strAttributeName);
129}
130
Georges-Henri Baron326a31d2012-06-28 12:05:09 +0200131_xmlDoc* CXmlDocSource::getDoc() const
132{
133 return _pDoc;
134}
Patrick Benavoli68a91282011-08-31 11:23:23 +0200135
Georges-Henri Baroncec86c12012-09-04 17:30:28 +0200136bool CXmlDocSource::validate(CXmlSerializingContext& serializingContext)
137{
138 // Check that the doc has been created
139 if (!_pDoc) {
140
141 serializingContext.setError("Could not parse document ");
142
143 return false;
144 }
145
Mattijs Korpershoek31418912014-04-08 14:05:21 +0200146 // Validate if necessary
147 if (_bValidateWithSchema)
148 {
149 if (!isInstanceDocumentValid()) {
Georges-Henri Baroncec86c12012-09-04 17:30:28 +0200150
Mattijs Korpershoek31418912014-04-08 14:05:21 +0200151 serializingContext.setError("Document is not valid");
Georges-Henri Baroncec86c12012-09-04 17:30:28 +0200152
Mattijs Korpershoek31418912014-04-08 14:05:21 +0200153 return false;
154 }
Georges-Henri Baroncec86c12012-09-04 17:30:28 +0200155 }
156
157 // Check Root element type
158 if (getRootElementName() != _strRootElementType) {
159
160 serializingContext.setError("Error: Wrong XML structure document ");
161 serializingContext.appendLineToError("Root Element " + getRootElementName()
162 + " mismatches expected type " + _strRootElementType);
163
164 return false;
165 }
166
167 if (_bNameCheck) {
168
169 string strRootElementNameCheck = getRootElementAttributeString(_strNameAttrituteName);
170
171 // Check Root element name attribute (if any)
172 if (!_strRootElementName.empty() && strRootElementNameCheck != _strRootElementName) {
173
174 serializingContext.setError("Error: Wrong XML structure document ");
175 serializingContext.appendLineToError(_strRootElementType + " element "
176 + _strRootElementName + " mismatches expected "
177 + _strRootElementType + " type "
178 + strRootElementNameCheck);
179
180 return false;
181 }
182 }
183
184 return true;
185}
186
187void CXmlDocSource::init()
188{
189 if (!_bLibXml2CleanupScheduled) {
190
191 // Schedule cleanup
192 atexit(xmlCleanupParser);
193
194 _bLibXml2CleanupScheduled = true;
195 }
196
197 if (!_pRootNode) {
198
199 _pRootNode = xmlDocGetRootElement(_pDoc);
200 }
201}
202
203bool CXmlDocSource::isInstanceDocumentValid()
204{
205#ifdef LIBXML_SCHEMAS_ENABLED
206 xmlDocPtr pSchemaDoc = xmlReadFile(_strXmlSchemaFile.c_str(), NULL, XML_PARSE_NONET);
207
208 if (!pSchemaDoc) {
209 // Unable to load Schema
210 return false;
211 }
212
213 xmlSchemaParserCtxtPtr pParserCtxt = xmlSchemaNewDocParserCtxt(pSchemaDoc);
214
215 if (!pParserCtxt) {
216
217 // Unable to create schema context
218 xmlFreeDoc(pSchemaDoc);
219 return false;
220 }
221
222 // Get Schema
223 xmlSchemaPtr pSchema = xmlSchemaParse(pParserCtxt);
224
225 if (!pSchema) {
226
227 // Invalid Schema
228 xmlSchemaFreeParserCtxt(pParserCtxt);
229 xmlFreeDoc(pSchemaDoc);
230 return false;
231 }
232 xmlSchemaValidCtxtPtr pValidationCtxt = xmlSchemaNewValidCtxt(pSchema);
233
234 if (!pValidationCtxt) {
235
236 // Unable to create validation context
237 xmlSchemaFree(pSchema);
238 xmlSchemaFreeParserCtxt(pParserCtxt);
239 xmlFreeDoc(pSchemaDoc);
240 return false;
241 }
242
243 xmlSetStructuredErrorFunc(this, schemaValidityStructuredErrorFunc);
244
245 bool isDocValid = xmlSchemaValidateDoc(pValidationCtxt, _pDoc) == 0;
246
247 xmlSchemaFreeValidCtxt(pValidationCtxt);
248 xmlSchemaFree(pSchema);
249 xmlSchemaFreeParserCtxt(pParserCtxt);
250 xmlFreeDoc(pSchemaDoc);
251
252 return isDocValid;
253#else
254 return true;
255#endif
256}
257
258void CXmlDocSource::schemaValidityStructuredErrorFunc(void* pUserData, _xmlError* pError)
259{
260 (void)pUserData;
261
262#ifdef LIBXML_SCHEMAS_ENABLED
263 // Display message
264 puts(pError->message);
265#endif
266}