blob: 476e41514cdd41a6446be5a80b8a79434ac3f83d [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
Georges-Henri Baron326a31d2012-06-28 12:05:09 +020039CXmlDocSource::CXmlDocSource(_xmlDoc *pDoc, _xmlNode *pRootNode):
Georges-Henri Baroncec86c12012-09-04 17:30:28 +020040 _pDoc(pDoc),
41 _pRootNode(pRootNode),
42 _strXmlSchemaFile(""),
43 _strRootElementType(""),
44 _strRootElementName(""),
45 _strNameAttrituteName(""),
46 _bNameCheck(false)
Patrick Benavoli68a91282011-08-31 11:23:23 +020047{
Georges-Henri Baroncec86c12012-09-04 17:30:28 +020048 init();
49}
Patrick Benavoli68a91282011-08-31 11:23:23 +020050
Georges-Henri Baroncec86c12012-09-04 17:30:28 +020051CXmlDocSource::CXmlDocSource(_xmlDoc *pDoc,
52 const string& strXmlSchemaFile,
53 const string& strRootElementType,
54 const string& strRootElementName,
55 const string& strNameAttrituteName) :
56 _pDoc(pDoc),
57 _pRootNode(NULL),
58 _strXmlSchemaFile(strXmlSchemaFile),
59 _strRootElementType(strRootElementType),
60 _strRootElementName(strRootElementName),
61 _strNameAttrituteName(strNameAttrituteName),
62 _bNameCheck(true)
63{
64 init();
65}
Patrick Benavoli68a91282011-08-31 11:23:23 +020066
Georges-Henri Baroncec86c12012-09-04 17:30:28 +020067CXmlDocSource::CXmlDocSource(_xmlDoc* pDoc,
68 const string& strXmlSchemaFile,
69 const string& strRootElementType) :
70 _pDoc(pDoc), _pRootNode(NULL),
71 _strXmlSchemaFile(strXmlSchemaFile),
72 _strRootElementType(strRootElementType),
73 _strRootElementName(""),
74 _strNameAttrituteName(""),
75 _bNameCheck(false)
76{
77 init();
Patrick Benavoli68a91282011-08-31 11:23:23 +020078}
79
Georges-Henri Baron326a31d2012-06-28 12:05:09 +020080CXmlDocSource::~CXmlDocSource()
Patrick Benavoli68a91282011-08-31 11:23:23 +020081{
Georges-Henri Baron326a31d2012-06-28 12:05:09 +020082 if (_pDoc) {
83 // Free XML doc
84 xmlFreeDoc(_pDoc);
85 _pDoc = NULL;
86 }
Patrick Benavoli68a91282011-08-31 11:23:23 +020087}
88
Georges-Henri Baron326a31d2012-06-28 12:05:09 +020089void CXmlDocSource::getRootElement(CXmlElement& xmlRootElement) const
Patrick Benavoli68a91282011-08-31 11:23:23 +020090{
91 xmlRootElement.setXmlElement(_pRootNode);
92}
93
Georges-Henri Baron326a31d2012-06-28 12:05:09 +020094string CXmlDocSource::getRootElementName() const
Patrick Benavoli68a91282011-08-31 11:23:23 +020095{
96 return (const char*)_pRootNode->name;
97}
98
Georges-Henri Baron326a31d2012-06-28 12:05:09 +020099string CXmlDocSource::getRootElementAttributeString(const string& strAttributeName) const
Patrick Benavoli68a91282011-08-31 11:23:23 +0200100{
101 CXmlElement topMostElement(_pRootNode);
102
103 return topMostElement.getAttributeString(strAttributeName);
104}
105
Georges-Henri Baron326a31d2012-06-28 12:05:09 +0200106_xmlDoc* CXmlDocSource::getDoc() const
107{
108 return _pDoc;
109}
Patrick Benavoli68a91282011-08-31 11:23:23 +0200110
Georges-Henri Baroncec86c12012-09-04 17:30:28 +0200111bool CXmlDocSource::validate(CXmlSerializingContext& serializingContext)
112{
113 // Check that the doc has been created
114 if (!_pDoc) {
115
116 serializingContext.setError("Could not parse document ");
117
118 return false;
119 }
120
121 // Validate
122 if (!isInstanceDocumentValid()) {
123
124 serializingContext.setError("Document is not valid");
125
126 return false;
127 }
128
129 // Check Root element type
130 if (getRootElementName() != _strRootElementType) {
131
132 serializingContext.setError("Error: Wrong XML structure document ");
133 serializingContext.appendLineToError("Root Element " + getRootElementName()
134 + " mismatches expected type " + _strRootElementType);
135
136 return false;
137 }
138
139 if (_bNameCheck) {
140
141 string strRootElementNameCheck = getRootElementAttributeString(_strNameAttrituteName);
142
143 // Check Root element name attribute (if any)
144 if (!_strRootElementName.empty() && strRootElementNameCheck != _strRootElementName) {
145
146 serializingContext.setError("Error: Wrong XML structure document ");
147 serializingContext.appendLineToError(_strRootElementType + " element "
148 + _strRootElementName + " mismatches expected "
149 + _strRootElementType + " type "
150 + strRootElementNameCheck);
151
152 return false;
153 }
154 }
155
156 return true;
157}
158
159void CXmlDocSource::init()
160{
161 if (!_bLibXml2CleanupScheduled) {
162
163 // Schedule cleanup
164 atexit(xmlCleanupParser);
165
166 _bLibXml2CleanupScheduled = true;
167 }
168
169 if (!_pRootNode) {
170
171 _pRootNode = xmlDocGetRootElement(_pDoc);
172 }
173}
174
175bool CXmlDocSource::isInstanceDocumentValid()
176{
177#ifdef LIBXML_SCHEMAS_ENABLED
178 xmlDocPtr pSchemaDoc = xmlReadFile(_strXmlSchemaFile.c_str(), NULL, XML_PARSE_NONET);
179
180 if (!pSchemaDoc) {
181 // Unable to load Schema
182 return false;
183 }
184
185 xmlSchemaParserCtxtPtr pParserCtxt = xmlSchemaNewDocParserCtxt(pSchemaDoc);
186
187 if (!pParserCtxt) {
188
189 // Unable to create schema context
190 xmlFreeDoc(pSchemaDoc);
191 return false;
192 }
193
194 // Get Schema
195 xmlSchemaPtr pSchema = xmlSchemaParse(pParserCtxt);
196
197 if (!pSchema) {
198
199 // Invalid Schema
200 xmlSchemaFreeParserCtxt(pParserCtxt);
201 xmlFreeDoc(pSchemaDoc);
202 return false;
203 }
204 xmlSchemaValidCtxtPtr pValidationCtxt = xmlSchemaNewValidCtxt(pSchema);
205
206 if (!pValidationCtxt) {
207
208 // Unable to create validation context
209 xmlSchemaFree(pSchema);
210 xmlSchemaFreeParserCtxt(pParserCtxt);
211 xmlFreeDoc(pSchemaDoc);
212 return false;
213 }
214
215 xmlSetStructuredErrorFunc(this, schemaValidityStructuredErrorFunc);
216
217 bool isDocValid = xmlSchemaValidateDoc(pValidationCtxt, _pDoc) == 0;
218
219 xmlSchemaFreeValidCtxt(pValidationCtxt);
220 xmlSchemaFree(pSchema);
221 xmlSchemaFreeParserCtxt(pParserCtxt);
222 xmlFreeDoc(pSchemaDoc);
223
224 return isDocValid;
225#else
226 return true;
227#endif
228}
229
230void CXmlDocSource::schemaValidityStructuredErrorFunc(void* pUserData, _xmlError* pError)
231{
232 (void)pUserData;
233
234#ifdef LIBXML_SCHEMAS_ENABLED
235 // Display message
236 puts(pError->message);
237#endif
238}