blob: 5e53a819e5d2263bd52095a65a0781111e763c5d [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
36// Schedule for libxml2 library
Georges-Henri Baron326a31d2012-06-28 12:05:09 +020037bool CXmlDocSource::_bLibXml2CleanupScheduled;
Patrick Benavoli68a91282011-08-31 11:23:23 +020038
Mattijs Korpershoek31418912014-04-08 14:05:21 +020039CXmlDocSource::CXmlDocSource(_xmlDoc *pDoc, _xmlNode *pRootNode,
40 bool bValidateWithSchema) :
Georges-Henri Baroncec86c12012-09-04 17:30:28 +020041 _pDoc(pDoc),
42 _pRootNode(pRootNode),
43 _strXmlSchemaFile(""),
44 _strRootElementType(""),
45 _strRootElementName(""),
46 _strNameAttrituteName(""),
Mattijs Korpershoek31418912014-04-08 14:05:21 +020047 _bNameCheck(false),
48 _bValidateWithSchema(bValidateWithSchema)
Patrick Benavoli68a91282011-08-31 11:23:23 +020049{
Georges-Henri Baroncec86c12012-09-04 17:30:28 +020050 init();
51}
Patrick Benavoli68a91282011-08-31 11:23:23 +020052
Georges-Henri Baroncec86c12012-09-04 17:30:28 +020053CXmlDocSource::CXmlDocSource(_xmlDoc *pDoc,
54 const string& strXmlSchemaFile,
55 const string& strRootElementType,
56 const string& strRootElementName,
57 const string& strNameAttrituteName) :
58 _pDoc(pDoc),
59 _pRootNode(NULL),
60 _strXmlSchemaFile(strXmlSchemaFile),
61 _strRootElementType(strRootElementType),
62 _strRootElementName(strRootElementName),
63 _strNameAttrituteName(strNameAttrituteName),
Mattijs Korpershoek31418912014-04-08 14:05:21 +020064 _bNameCheck(true),
65 _bValidateWithSchema(false)
Georges-Henri Baroncec86c12012-09-04 17:30:28 +020066{
67 init();
68}
Patrick Benavoli68a91282011-08-31 11:23:23 +020069
Georges-Henri Baroncec86c12012-09-04 17:30:28 +020070CXmlDocSource::CXmlDocSource(_xmlDoc* pDoc,
71 const string& strXmlSchemaFile,
Mattijs Korpershoek31418912014-04-08 14:05:21 +020072 const string& strRootElementType,
73 bool bValidateWithSchema) :
Georges-Henri Baroncec86c12012-09-04 17:30:28 +020074 _pDoc(pDoc), _pRootNode(NULL),
75 _strXmlSchemaFile(strXmlSchemaFile),
76 _strRootElementType(strRootElementType),
77 _strRootElementName(""),
78 _strNameAttrituteName(""),
Mattijs Korpershoek31418912014-04-08 14:05:21 +020079 _bNameCheck(false),
80 _bValidateWithSchema(bValidateWithSchema)
81{
82 init();
83}
84
85CXmlDocSource::CXmlDocSource(_xmlDoc *pDoc,
86 const string& strXmlSchemaFile,
87 const string& strRootElementType,
88 const string& strRootElementName,
89 const string& strNameAttrituteName,
90 bool bValidateWithSchema) :
91 _pDoc(pDoc),
92 _pRootNode(NULL),
93 _strXmlSchemaFile(strXmlSchemaFile),
94 _strRootElementType(strRootElementType),
95 _strRootElementName(strRootElementName),
96 _strNameAttrituteName(strNameAttrituteName),
97 _bNameCheck(true),
98 _bValidateWithSchema(bValidateWithSchema)
Georges-Henri Baroncec86c12012-09-04 17:30:28 +020099{
100 init();
Patrick Benavoli68a91282011-08-31 11:23:23 +0200101}
102
Georges-Henri Baron326a31d2012-06-28 12:05:09 +0200103CXmlDocSource::~CXmlDocSource()
Patrick Benavoli68a91282011-08-31 11:23:23 +0200104{
Georges-Henri Baron326a31d2012-06-28 12:05:09 +0200105 if (_pDoc) {
106 // Free XML doc
107 xmlFreeDoc(_pDoc);
108 _pDoc = NULL;
109 }
Patrick Benavoli68a91282011-08-31 11:23:23 +0200110}
111
Georges-Henri Baron326a31d2012-06-28 12:05:09 +0200112void CXmlDocSource::getRootElement(CXmlElement& xmlRootElement) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200113{
114 xmlRootElement.setXmlElement(_pRootNode);
115}
116
Georges-Henri Baron326a31d2012-06-28 12:05:09 +0200117string CXmlDocSource::getRootElementName() const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200118{
119 return (const char*)_pRootNode->name;
120}
121
Georges-Henri Baron326a31d2012-06-28 12:05:09 +0200122string CXmlDocSource::getRootElementAttributeString(const string& strAttributeName) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200123{
124 CXmlElement topMostElement(_pRootNode);
125
126 return topMostElement.getAttributeString(strAttributeName);
127}
128
Georges-Henri Baron326a31d2012-06-28 12:05:09 +0200129_xmlDoc* CXmlDocSource::getDoc() const
130{
131 return _pDoc;
132}
Patrick Benavoli68a91282011-08-31 11:23:23 +0200133
Georges-Henri Baroncec86c12012-09-04 17:30:28 +0200134bool CXmlDocSource::validate(CXmlSerializingContext& serializingContext)
135{
136 // Check that the doc has been created
137 if (!_pDoc) {
138
139 serializingContext.setError("Could not parse document ");
140
141 return false;
142 }
143
Mattijs Korpershoek31418912014-04-08 14:05:21 +0200144 // Validate if necessary
145 if (_bValidateWithSchema)
146 {
147 if (!isInstanceDocumentValid()) {
Georges-Henri Baroncec86c12012-09-04 17:30:28 +0200148
Mattijs Korpershoek31418912014-04-08 14:05:21 +0200149 serializingContext.setError("Document is not valid");
Georges-Henri Baroncec86c12012-09-04 17:30:28 +0200150
Mattijs Korpershoek31418912014-04-08 14:05:21 +0200151 return false;
152 }
Georges-Henri Baroncec86c12012-09-04 17:30:28 +0200153 }
154
155 // Check Root element type
156 if (getRootElementName() != _strRootElementType) {
157
158 serializingContext.setError("Error: Wrong XML structure document ");
159 serializingContext.appendLineToError("Root Element " + getRootElementName()
160 + " mismatches expected type " + _strRootElementType);
161
162 return false;
163 }
164
165 if (_bNameCheck) {
166
167 string strRootElementNameCheck = getRootElementAttributeString(_strNameAttrituteName);
168
169 // Check Root element name attribute (if any)
170 if (!_strRootElementName.empty() && strRootElementNameCheck != _strRootElementName) {
171
172 serializingContext.setError("Error: Wrong XML structure document ");
173 serializingContext.appendLineToError(_strRootElementType + " element "
174 + _strRootElementName + " mismatches expected "
175 + _strRootElementType + " type "
176 + strRootElementNameCheck);
177
178 return false;
179 }
180 }
181
182 return true;
183}
184
185void CXmlDocSource::init()
186{
187 if (!_bLibXml2CleanupScheduled) {
188
189 // Schedule cleanup
190 atexit(xmlCleanupParser);
191
192 _bLibXml2CleanupScheduled = true;
193 }
194
195 if (!_pRootNode) {
196
197 _pRootNode = xmlDocGetRootElement(_pDoc);
198 }
199}
200
201bool CXmlDocSource::isInstanceDocumentValid()
202{
203#ifdef LIBXML_SCHEMAS_ENABLED
204 xmlDocPtr pSchemaDoc = xmlReadFile(_strXmlSchemaFile.c_str(), NULL, XML_PARSE_NONET);
205
206 if (!pSchemaDoc) {
207 // Unable to load Schema
208 return false;
209 }
210
211 xmlSchemaParserCtxtPtr pParserCtxt = xmlSchemaNewDocParserCtxt(pSchemaDoc);
212
213 if (!pParserCtxt) {
214
215 // Unable to create schema context
216 xmlFreeDoc(pSchemaDoc);
217 return false;
218 }
219
220 // Get Schema
221 xmlSchemaPtr pSchema = xmlSchemaParse(pParserCtxt);
222
223 if (!pSchema) {
224
225 // Invalid Schema
226 xmlSchemaFreeParserCtxt(pParserCtxt);
227 xmlFreeDoc(pSchemaDoc);
228 return false;
229 }
230 xmlSchemaValidCtxtPtr pValidationCtxt = xmlSchemaNewValidCtxt(pSchema);
231
232 if (!pValidationCtxt) {
233
234 // Unable to create validation context
235 xmlSchemaFree(pSchema);
236 xmlSchemaFreeParserCtxt(pParserCtxt);
237 xmlFreeDoc(pSchemaDoc);
238 return false;
239 }
240
241 xmlSetStructuredErrorFunc(this, schemaValidityStructuredErrorFunc);
242
243 bool isDocValid = xmlSchemaValidateDoc(pValidationCtxt, _pDoc) == 0;
244
245 xmlSchemaFreeValidCtxt(pValidationCtxt);
246 xmlSchemaFree(pSchema);
247 xmlSchemaFreeParserCtxt(pParserCtxt);
248 xmlFreeDoc(pSchemaDoc);
249
250 return isDocValid;
251#else
252 return true;
253#endif
254}
255
256void CXmlDocSource::schemaValidityStructuredErrorFunc(void* pUserData, _xmlError* pError)
257{
258 (void)pUserData;
259
260#ifdef LIBXML_SCHEMAS_ENABLED
261 // Display message
262 puts(pError->message);
263#endif
264}