1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtXmlPatterns module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include <QtMath> |
41 | |
42 | #include "qxsdtypechecker_p.h" |
43 | |
44 | #include "qabstractdatetime_p.h" |
45 | #include "qbase64binary_p.h" |
46 | #include "qboolean_p.h" |
47 | #include "qdecimal_p.h" |
48 | #include "qderivedinteger_p.h" |
49 | #include "qduration_p.h" |
50 | #include "qgenericstaticcontext_p.h" |
51 | #include "qhexbinary_p.h" |
52 | #include "qnamespaceresolver_p.h" |
53 | #include "qpatternplatform_p.h" |
54 | #include "qqnamevalue_p.h" |
55 | #include "qvaluefactory_p.h" |
56 | #include "qxmlnamepool.h" |
57 | #include "qxsdschemahelper_p.h" |
58 | #include "qxsdschemamerger_p.h" |
59 | #include "qxsdstatemachine_p.h" |
60 | |
61 | #include "qxsdschemadebugger_p.h" |
62 | |
63 | QT_BEGIN_NAMESPACE |
64 | |
65 | using namespace QPatternist; |
66 | |
67 | XsdSchemaSourceLocationReflection::XsdSchemaSourceLocationReflection(const QSourceLocation &location) |
68 | : m_sourceLocation(location) |
69 | { |
70 | } |
71 | |
72 | const SourceLocationReflection* XsdSchemaSourceLocationReflection::actualReflection() const |
73 | { |
74 | return this; |
75 | } |
76 | |
77 | QSourceLocation XsdSchemaSourceLocationReflection::sourceLocation() const |
78 | { |
79 | return m_sourceLocation; |
80 | } |
81 | |
82 | |
83 | static AnySimpleType::Ptr comparableType(const AnySimpleType::Ptr &type) |
84 | { |
85 | if (!type->isDefinedBySchema()) { |
86 | return type; |
87 | } else { |
88 | const XsdSimpleType::Ptr simpleType(type); |
89 | if (type->category() == SchemaType::SimpleTypeAtomic) { |
90 | return simpleType->primitiveType(); |
91 | } else if (type->category() == SchemaType::SimpleTypeList) { |
92 | return simpleType->itemType(); |
93 | } else if (type->category() == SchemaType::SimpleTypeUnion) { |
94 | return simpleType->memberTypes().first(); |
95 | } |
96 | } |
97 | |
98 | Q_ASSERT(false); |
99 | return AnySimpleType::Ptr(); |
100 | } |
101 | |
102 | static int totalDigitsForSignedLongLong(long long value) |
103 | { |
104 | QString number = QString::number(value); |
105 | if (number.startsWith(c: QLatin1Char('-'))) |
106 | number = number.mid(position: 1); |
107 | |
108 | return number.length(); |
109 | } |
110 | |
111 | static int totalDigitsForUnsignedLongLong(unsigned long long value) |
112 | { |
113 | const QString number = QString::number(value); |
114 | return number.length(); |
115 | } |
116 | |
117 | static int totalDigitsForDecimal(const QString &lexicalValue) |
118 | { |
119 | const QLatin1Char zeroChar('0'); |
120 | const int length = lexicalValue.length() - 1; |
121 | |
122 | // strip leading zeros |
123 | int pos = 0; |
124 | while (lexicalValue.at(i: pos) == zeroChar && (pos != length)) |
125 | pos++; |
126 | |
127 | QString value = lexicalValue.mid(position: pos); |
128 | |
129 | // if contains '.' strip trailing zeros |
130 | if (value.contains(c: QLatin1Char('.'))) { |
131 | pos = value.length() - 1; |
132 | while (value.at(i: pos) == zeroChar) { |
133 | pos--; |
134 | } |
135 | |
136 | value = value.left(n: pos + 1); |
137 | } |
138 | |
139 | // check number of digits of remaining string |
140 | int totalDigits = 0; |
141 | for (int i = 0; i < value.count(); ++i) |
142 | if (value.at(i).isDigit()) |
143 | ++totalDigits; |
144 | |
145 | if (totalDigits == 0) |
146 | totalDigits = 1; |
147 | |
148 | return totalDigits; |
149 | } |
150 | |
151 | static int fractionDigitsForDecimal(const QString &lexicalValue) |
152 | { |
153 | const int pos = lexicalValue.indexOf(c: QLatin1Char('.')); |
154 | if (pos == -1) |
155 | return 0; |
156 | const QStringRef fraction = QStringRef(&lexicalValue).mid(pos).trimmed(); |
157 | int i = fraction.length() - 1; // fraction[0] is '.' so fraction is not empty |
158 | while (fraction.at(i) == QLatin1Char('0')) |
159 | --i; |
160 | return i; // The significant fraction-digits are fraction[1 through i]. |
161 | } |
162 | |
163 | XsdTypeChecker::XsdTypeChecker(const XsdSchemaContext::Ptr &context, const QVector<QXmlName> &namespaceBindings, const QSourceLocation &location) |
164 | : m_context(context) |
165 | , m_namePool(m_context->namePool()) |
166 | , m_namespaceBindings(namespaceBindings) |
167 | , m_reflection(new XsdSchemaSourceLocationReflection(location)) |
168 | { |
169 | } |
170 | |
171 | XsdTypeChecker::~XsdTypeChecker() |
172 | { |
173 | delete m_reflection; |
174 | } |
175 | |
176 | QString XsdTypeChecker::normalizedValue(const QString &value, const XsdFacet::Hash &facets) |
177 | { |
178 | if (!facets.contains(akey: XsdFacet::WhiteSpace)) |
179 | return value; |
180 | |
181 | const XsdFacet::Ptr whiteSpaceFacet = facets.value(akey: XsdFacet::WhiteSpace); |
182 | |
183 | const DerivedString<TypeString>::Ptr facetValue = whiteSpaceFacet->value(); |
184 | const QString stringValue = facetValue->stringValue(); |
185 | if (stringValue == XsdSchemaToken::toString(token: XsdSchemaToken::Preserve)) |
186 | return value; |
187 | else if (stringValue == XsdSchemaToken::toString(token: XsdSchemaToken::Replace)) { |
188 | QString newValue(value); |
189 | newValue.replace(before: QLatin1Char('\t'), after: QLatin1Char(' ')); |
190 | newValue.replace(before: QLatin1Char('\n'), after: QLatin1Char(' ')); |
191 | newValue.replace(before: QLatin1Char('\r'), after: QLatin1Char(' ')); |
192 | |
193 | return newValue; |
194 | } else if (stringValue == XsdSchemaToken::toString(token: XsdSchemaToken::Collapse)) { |
195 | return value.simplified(); |
196 | } |
197 | |
198 | return value; |
199 | } |
200 | |
201 | XsdFacet::Hash XsdTypeChecker::mergedFacetsForType(const SchemaType::Ptr &type, const XsdSchemaContext::Ptr &context) |
202 | { |
203 | if (!type) |
204 | return XsdFacet::Hash(); |
205 | |
206 | const XsdFacet::Hash baseFacets = mergedFacetsForType(type: type->wxsSuperType(), context); |
207 | const XsdFacet::Hash facets = context->facetsForType(type); |
208 | |
209 | XsdFacet::Hash result = baseFacets; |
210 | for (auto it = facets.cbegin(), end = facets.cend(); it != end; ++it) |
211 | result.insert(akey: it.key(), avalue: it.value()); |
212 | |
213 | return result; |
214 | } |
215 | |
216 | bool XsdTypeChecker::isValidString(const QString &normalizedString, const AnySimpleType::Ptr &type, QString &errorMsg, AnySimpleType::Ptr *boundType) const |
217 | { |
218 | if (type->name(np: m_namePool) == BuiltinTypes::xsAnySimpleType->name(np: m_namePool)) { |
219 | if (boundType) |
220 | *boundType = type; |
221 | |
222 | return true; |
223 | } |
224 | |
225 | if (!type->isDefinedBySchema()) { |
226 | // special QName check |
227 | if (BuiltinTypes::xsQName->wxsTypeMatches(other: type)) { |
228 | if (!XPathHelper::isQName(qName: normalizedString)) { |
229 | errorMsg = QtXmlPatterns::tr(sourceText: "%1 is not valid according to %2." ).arg(a: formatData(data: normalizedString)).arg(a: formatType(np: m_namePool, type)); |
230 | return false; |
231 | } |
232 | } |
233 | |
234 | const AtomicValue::Ptr value = fromLexical(value: normalizedString, type, context: m_context, reflection: m_reflection); |
235 | if (value->hasError()) { |
236 | errorMsg = QtXmlPatterns::tr(sourceText: "%1 is not valid according to %2." ).arg(a: formatData(data: normalizedString)).arg(a: formatType(np: m_namePool, type)); |
237 | return false; |
238 | } |
239 | |
240 | if (!checkConstrainingFacets(value, lexicalValue: normalizedString, type, errorMsg)) { |
241 | return false; |
242 | } |
243 | |
244 | if (boundType) |
245 | *boundType = type; |
246 | |
247 | } else { |
248 | const XsdSimpleType::Ptr simpleType(type); |
249 | |
250 | if (simpleType->category() == XsdSimpleType::SimpleTypeAtomic) { |
251 | AnySimpleType::Ptr targetType = simpleType->primitiveType(); |
252 | if (!simpleType->wxsSuperType()->isDefinedBySchema()) |
253 | targetType = simpleType->wxsSuperType(); |
254 | |
255 | const AtomicValue::Ptr value = fromLexical(value: normalizedString, type: targetType, context: m_context, reflection: m_reflection); |
256 | if (value->hasError()) { |
257 | errorMsg = QtXmlPatterns::tr(sourceText: "%1 is not valid according to %2." ).arg(a: formatData(data: normalizedString)).arg(a: formatType(np: m_namePool, type: targetType)); |
258 | return false; |
259 | } |
260 | |
261 | if (!checkConstrainingFacets(value, lexicalValue: normalizedString, type, errorMsg)) { |
262 | return false; |
263 | } |
264 | |
265 | if (boundType) |
266 | *boundType = type; |
267 | |
268 | } else if (simpleType->category() == XsdSimpleType::SimpleTypeList) { |
269 | QStringList entries = normalizedString.split(sep: QLatin1Char(' '), behavior: Qt::SkipEmptyParts); |
270 | for (int i = 0; i < entries.count(); ++i) { |
271 | entries[i] = normalizedValue(value: entries.at(i), facets: mergedFacetsForType(type: simpleType->itemType(), context: m_context)); |
272 | } |
273 | |
274 | if (!checkConstrainingFacetsList(values: entries, lexicalValue: normalizedString, itemType: simpleType->itemType(), facets: mergedFacetsForType(type: simpleType, context: m_context), errorMsg)) { |
275 | return false; |
276 | } |
277 | |
278 | for (int i = 0; i < entries.count(); ++i) { |
279 | if (!isValidString(normalizedString: entries.at(i), type: simpleType->itemType(), errorMsg)) { |
280 | return false; |
281 | } |
282 | } |
283 | |
284 | if (boundType) |
285 | *boundType = simpleType->itemType(); |
286 | |
287 | } else if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) { |
288 | if (!checkConstrainingFacetsUnion(value: normalizedString, lexicalValue: normalizedString, simpleType, facets: mergedFacetsForType(type: simpleType, context: m_context), errorMsg)) { |
289 | return false; |
290 | } |
291 | |
292 | const AnySimpleType::List memberTypes = simpleType->memberTypes(); |
293 | |
294 | bool foundValidType = false; |
295 | for (int i = 0; i < memberTypes.count(); ++i) { |
296 | const XsdFacet::Hash mergedFacets = mergedFacetsForType(type: memberTypes.at(i), context: m_context); |
297 | if (isValidString(normalizedString: normalizedValue(value: normalizedString, facets: mergedFacets), type: memberTypes.at(i), errorMsg)) { |
298 | foundValidType = true; |
299 | |
300 | if (boundType) |
301 | *boundType = memberTypes.at(i); |
302 | |
303 | break; |
304 | } |
305 | } |
306 | |
307 | if (!foundValidType) { |
308 | return false; |
309 | } |
310 | } |
311 | } |
312 | |
313 | return true; |
314 | } |
315 | |
316 | bool XsdTypeChecker::valuesAreEqual(const QString &value, const QString &otherValue, const AnySimpleType::Ptr &type) const |
317 | { |
318 | const AnySimpleType::Ptr targetType = comparableType(type); |
319 | |
320 | // if the type is xs:anySimpleType we just do string comparison... |
321 | if (targetType->name(np: m_namePool) == BuiltinTypes::xsAnySimpleType->name(np: m_namePool)) |
322 | return (value == otherValue); |
323 | |
324 | if (BuiltinTypes::xsQName->wxsTypeMatches(other: type)) { |
325 | const QXmlName valueName = convertToQName(name: value); |
326 | const QXmlName otherValueName = convertToQName(name: otherValue); |
327 | |
328 | if (valueName == otherValueName) |
329 | return true; |
330 | } |
331 | |
332 | if (type->category() == SchemaType::SimpleTypeAtomic) { |
333 | // ... otherwise we use the casting platform for value comparison |
334 | const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(np: m_namePool, lexical: value); |
335 | const DerivedString<TypeString>::Ptr otherValueStr = DerivedString<TypeString>::fromLexical(np: m_namePool, lexical: otherValue); |
336 | |
337 | return XsdSchemaHelper::constructAndCompare(operand1: valueStr, op: AtomicComparator::OperatorEqual, operand2: otherValueStr, type: targetType, context: m_context, sourceLocationReflection: m_reflection); |
338 | } else if (type->category() == SchemaType::SimpleTypeList) { |
339 | const QStringList values = value.split(sep: QLatin1Char(' '), behavior: Qt::SkipEmptyParts); |
340 | const QStringList otherValues = otherValue.split(sep: QLatin1Char(' '), behavior: Qt::SkipEmptyParts); |
341 | if (values.count() != otherValues.count()) |
342 | return false; |
343 | |
344 | for (int i = 0; i < values.count(); ++i) { |
345 | if (!valuesAreEqual(value: values.at(i), otherValue: otherValues.at(i), type: XsdSimpleType::Ptr(type)->itemType())) |
346 | return false; |
347 | } |
348 | |
349 | return true; |
350 | } else if (type->category() == SchemaType::SimpleTypeUnion) { |
351 | const AnySimpleType::List memberTypes = XsdSimpleType::Ptr(type)->memberTypes(); |
352 | for (int i = 0; i < memberTypes.count(); ++i) { |
353 | if (valuesAreEqual(value, otherValue, type: memberTypes.at(i))) { |
354 | return true; |
355 | } |
356 | } |
357 | |
358 | return false; |
359 | } |
360 | |
361 | return false; |
362 | } |
363 | |
364 | bool XsdTypeChecker::checkConstrainingFacets(const AtomicValue::Ptr &value, const QString &lexicalValue, const AnySimpleType::Ptr &type, QString &errorMsg) const |
365 | { |
366 | const XsdFacet::Hash facets = mergedFacetsForType(type, context: m_context); |
367 | |
368 | if (BuiltinTypes::xsString->wxsTypeMatches(other: type) || |
369 | BuiltinTypes::xsUntypedAtomic->wxsTypeMatches(other: type)) { |
370 | return checkConstrainingFacetsString(value: value->stringValue(), facets, type: BuiltinTypes::xsString, errorMsg); |
371 | } else if (BuiltinTypes::xsAnyURI->wxsTypeMatches(other: type)) { |
372 | return checkConstrainingFacetsString(value: value->stringValue(), facets, type: BuiltinTypes::xsAnyURI, errorMsg); |
373 | } else if (BuiltinTypes::xsNOTATION->wxsTypeMatches(other: type)) { |
374 | return checkConstrainingFacetsNotation(value: value->as<QNameValue>()->qName(), facets, errorMsg); |
375 | } else if (BuiltinTypes::xsUnsignedByte->wxsTypeMatches(other: type) || |
376 | BuiltinTypes::xsUnsignedInt->wxsTypeMatches(other: type) || |
377 | BuiltinTypes::xsUnsignedLong->wxsTypeMatches(other: type) || |
378 | BuiltinTypes::xsUnsignedShort->wxsTypeMatches(other: type)) { |
379 | return checkConstrainingFacetsUnsignedInteger(value: value->as<Numeric>()->toUnsignedInteger(), lexicalValue, facets, errorMsg); |
380 | } else if (BuiltinTypes::xsInteger->wxsTypeMatches(other: type)) { |
381 | return checkConstrainingFacetsSignedInteger(value: value->as<Numeric>()->toInteger(), lexicalValue, facets, errorMsg); |
382 | } else if (BuiltinTypes::xsFloat->wxsTypeMatches(other: type) || |
383 | BuiltinTypes::xsDouble->wxsTypeMatches(other: type)) { |
384 | return checkConstrainingFacetsDouble(value: value->as<Numeric>()->toDouble(), lexicalValue, facets, errorMsg); |
385 | } else if (BuiltinTypes::xsDecimal->wxsTypeMatches(other: type)) { |
386 | return checkConstrainingFacetsDecimal(value, lexicalValue, facets, errorMsg); |
387 | } else if (BuiltinTypes::xsDateTime->wxsTypeMatches(other: type)) { |
388 | return checkConstrainingFacetsDateTime(value: value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, type: BuiltinTypes::xsDateTime, errorMsg); |
389 | } else if (BuiltinTypes::xsDate->wxsTypeMatches(other: type)) { |
390 | return checkConstrainingFacetsDateTime(value: value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, type: BuiltinTypes::xsDate, errorMsg); |
391 | } else if (BuiltinTypes::xsGYear->wxsTypeMatches(other: type)) { |
392 | return checkConstrainingFacetsDateTime(value: value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, type: BuiltinTypes::xsGYear, errorMsg); |
393 | } else if (BuiltinTypes::xsGYearMonth->wxsTypeMatches(other: type)) { |
394 | return checkConstrainingFacetsDateTime(value: value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, type: BuiltinTypes::xsGYearMonth, errorMsg); |
395 | } else if (BuiltinTypes::xsGMonth->wxsTypeMatches(other: type)) { |
396 | return checkConstrainingFacetsDateTime(value: value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, type: BuiltinTypes::xsGMonth, errorMsg); |
397 | } else if (BuiltinTypes::xsGMonthDay->wxsTypeMatches(other: type)) { |
398 | return checkConstrainingFacetsDateTime(value: value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, type: BuiltinTypes::xsGMonthDay, errorMsg); |
399 | } else if (BuiltinTypes::xsGDay->wxsTypeMatches(other: type)) { |
400 | return checkConstrainingFacetsDateTime(value: value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, type: BuiltinTypes::xsGDay, errorMsg); |
401 | } else if (BuiltinTypes::xsTime->wxsTypeMatches(other: type)) { |
402 | return checkConstrainingFacetsDateTime(value: value->as<AbstractDateTime>()->toDateTime(), lexicalValue, facets, type: BuiltinTypes::xsTime, errorMsg); |
403 | } else if (BuiltinTypes::xsDuration->wxsTypeMatches(other: type)) { |
404 | return checkConstrainingFacetsDuration(value, lexicalValue, facets, errorMsg); |
405 | } else if (BuiltinTypes::xsBoolean->wxsTypeMatches(other: type)) { |
406 | return checkConstrainingFacetsBoolean(value: value->as<Boolean>()->value(), lexicalValue, facets, errorMsg); |
407 | } else if (BuiltinTypes::xsHexBinary->wxsTypeMatches(other: type)) { |
408 | return checkConstrainingFacetsBinary(value: value->as<Base64Binary>()->asByteArray(), facets, type: BuiltinTypes::xsHexBinary, errorMsg); |
409 | } else if (BuiltinTypes::xsBase64Binary->wxsTypeMatches(other: type)) { |
410 | return checkConstrainingFacetsBinary(value: value->as<Base64Binary>()->asByteArray(), facets, type: BuiltinTypes::xsBase64Binary, errorMsg); |
411 | } else if (BuiltinTypes::xsQName->wxsTypeMatches(other: type)) { |
412 | return checkConstrainingFacetsQName(value->as<QNameValue>()->qName(), lexicalValue, facets, errorMsg); |
413 | } |
414 | |
415 | return true; |
416 | } |
417 | |
418 | bool XsdTypeChecker::checkConstrainingFacetsString(const QString &value, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const |
419 | { |
420 | if (facets.contains(akey: XsdFacet::Length)) { |
421 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Length); |
422 | const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value(); |
423 | if (length->toInteger() != value.length()) { |
424 | errorMsg = QtXmlPatterns::tr(sourceText: "String content does not match the length facet." ); |
425 | return false; |
426 | } |
427 | } |
428 | if (facets.contains(akey: XsdFacet::MinimumLength)) { |
429 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MinimumLength); |
430 | const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value(); |
431 | if (length->toInteger() > value.length()) { |
432 | errorMsg = QtXmlPatterns::tr(sourceText: "String content does not match the minLength facet." ); |
433 | return false; |
434 | } |
435 | } |
436 | if (facets.contains(akey: XsdFacet::MaximumLength)) { |
437 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MaximumLength); |
438 | const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value(); |
439 | if (length->toInteger() < value.length()) { |
440 | errorMsg = QtXmlPatterns::tr(sourceText: "String content does not match the maxLength facet." ); |
441 | return false; |
442 | } |
443 | } |
444 | if (facets.contains(akey: XsdFacet::Pattern)) { |
445 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Pattern); |
446 | const AtomicValue::List multiValue = facet->multiValue(); |
447 | bool found = false; |
448 | for (int j = 0; j < multiValue.count(); ++j) { |
449 | const QString pattern = multiValue.at(i: j)->as<DerivedString<TypeString> >()->stringValue(); |
450 | QRegExp exp = PatternPlatform::parsePattern(pattern, context: m_context, location: m_reflection); |
451 | if (exp.exactMatch(str: value)) { |
452 | found = true; |
453 | break; |
454 | } |
455 | } |
456 | |
457 | if (!found) { |
458 | errorMsg = QtXmlPatterns::tr(sourceText: "String content does not match pattern facet." ); |
459 | return false; |
460 | } |
461 | } |
462 | if (facets.contains(akey: XsdFacet::Enumeration)) { |
463 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Enumeration); |
464 | const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(np: m_namePool, lexical: value); |
465 | |
466 | const AtomicValue::List multiValue = facet->multiValue(); |
467 | bool found = false; |
468 | for (int j = 0; j < multiValue.count(); ++j) { |
469 | if (XsdSchemaHelper::constructAndCompare(operand1: valueStr, op: AtomicComparator::OperatorEqual, operand2: multiValue.at(i: j), type, context: m_context, sourceLocationReflection: m_reflection)) { |
470 | found = true; |
471 | break; |
472 | } |
473 | } |
474 | |
475 | if (!found) { |
476 | errorMsg = QtXmlPatterns::tr(sourceText: "String content is not listed in the enumeration facet." ); |
477 | return false; |
478 | } |
479 | } |
480 | if (facets.contains(akey: XsdFacet::Assertion)) { |
481 | //TODO: implement |
482 | } |
483 | |
484 | return true; |
485 | } |
486 | |
487 | bool XsdTypeChecker::checkConstrainingFacetsSignedInteger(long long value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const |
488 | { |
489 | if (facets.contains(akey: XsdFacet::MaximumInclusive)) { |
490 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MaximumInclusive); |
491 | const Numeric::Ptr facetValue = ValueFactory::fromLexical(lexicalValue: facet->value()->as<DerivedString<TypeString> >()->stringValue(), type: BuiltinTypes::xsLong, context: m_context, sourceLocationReflection: m_reflection); |
492 | if (facetValue->toInteger() < value) { |
493 | errorMsg = QtXmlPatterns::tr(sourceText: "Signed integer content does not match the maxInclusive facet." ); |
494 | return false; |
495 | } |
496 | } |
497 | if (facets.contains(akey: XsdFacet::MaximumExclusive)) { |
498 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MaximumExclusive); |
499 | const Numeric::Ptr facetValue = ValueFactory::fromLexical(lexicalValue: facet->value()->as<DerivedString<TypeString> >()->stringValue(), type: BuiltinTypes::xsLong, context: m_context, sourceLocationReflection: m_reflection); |
500 | if (facetValue->toInteger() <= value) { |
501 | errorMsg = QtXmlPatterns::tr(sourceText: "Signed integer content does not match the maxExclusive facet." ); |
502 | return false; |
503 | } |
504 | } |
505 | if (facets.contains(akey: XsdFacet::MinimumInclusive)) { |
506 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MinimumInclusive); |
507 | const Numeric::Ptr facetValue = ValueFactory::fromLexical(lexicalValue: facet->value()->as<DerivedString<TypeString> >()->stringValue(), type: BuiltinTypes::xsLong, context: m_context, sourceLocationReflection: m_reflection); |
508 | if (facetValue->toInteger() > value) { |
509 | errorMsg = QtXmlPatterns::tr(sourceText: "Signed integer content does not match the minInclusive facet." ); |
510 | return false; |
511 | } |
512 | } |
513 | if (facets.contains(akey: XsdFacet::MinimumExclusive)) { |
514 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MinimumExclusive); |
515 | const Numeric::Ptr facetValue = ValueFactory::fromLexical(lexicalValue: facet->value()->as<DerivedString<TypeString> >()->stringValue(), type: BuiltinTypes::xsLong, context: m_context, sourceLocationReflection: m_reflection); |
516 | if (facetValue->toInteger() >= value) { |
517 | errorMsg = QtXmlPatterns::tr(sourceText: "Signed integer content does not match the minExclusive facet." ); |
518 | return false; |
519 | } |
520 | } |
521 | if (facets.contains(akey: XsdFacet::Enumeration)) { |
522 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Enumeration); |
523 | const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(np: m_namePool, lexical: QString::number(value)); |
524 | |
525 | const AtomicValue::List multiValue = facet->multiValue(); |
526 | bool found = false; |
527 | for (int j = 0; j < multiValue.count(); ++j) { |
528 | if (XsdSchemaHelper::constructAndCompare(operand1: valueStr, op: AtomicComparator::OperatorEqual, operand2: multiValue.at(i: j), type: BuiltinTypes::xsLong, context: m_context, sourceLocationReflection: m_reflection)) { |
529 | found = true; |
530 | break; |
531 | } |
532 | } |
533 | |
534 | if (!found) { |
535 | errorMsg = QtXmlPatterns::tr(sourceText: "Signed integer content is not listed in the enumeration facet." ); |
536 | return false; |
537 | } |
538 | } |
539 | if (facets.contains(akey: XsdFacet::Pattern)) { |
540 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Pattern); |
541 | const AtomicValue::List multiValue = facet->multiValue(); |
542 | bool found = false; |
543 | for (int j = 0; j < multiValue.count(); ++j) { |
544 | const QString pattern = multiValue.at(i: j)->as<DerivedString<TypeString> >()->stringValue(); |
545 | QRegExp exp = PatternPlatform::parsePattern(pattern, context: m_context, location: m_reflection); |
546 | if (exp.exactMatch(str: lexicalValue)) { |
547 | found = true; |
548 | break; |
549 | } |
550 | } |
551 | |
552 | if (!found) { |
553 | errorMsg = QtXmlPatterns::tr(sourceText: "Signed integer content does not match pattern facet." ); |
554 | return false; |
555 | } |
556 | } |
557 | if (facets.contains(akey: XsdFacet::TotalDigits)) { |
558 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::TotalDigits); |
559 | const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value(); |
560 | |
561 | if (totalDigitsForSignedLongLong(value) > facetValue->toInteger()) { |
562 | errorMsg = QtXmlPatterns::tr(sourceText: "Signed integer content does not match in the totalDigits facet." ); |
563 | return false; |
564 | } |
565 | } |
566 | if (facets.contains(akey: XsdFacet::Assertion)) { |
567 | //TODO: implement |
568 | } |
569 | |
570 | return true; |
571 | } |
572 | |
573 | bool XsdTypeChecker::checkConstrainingFacetsUnsignedInteger(unsigned long long value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const |
574 | { |
575 | if (facets.contains(akey: XsdFacet::MaximumInclusive)) { |
576 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MaximumInclusive); |
577 | const Numeric::Ptr facetValue = ValueFactory::fromLexical(lexicalValue: facet->value()->as<DerivedString<TypeString> >()->stringValue(), type: BuiltinTypes::xsUnsignedLong, context: m_context, sourceLocationReflection: m_reflection); |
578 | if (facetValue->toUnsignedInteger() < value) { |
579 | errorMsg = QtXmlPatterns::tr(sourceText: "Unsigned integer content does not match the maxInclusive facet." ); |
580 | return false; |
581 | } |
582 | } |
583 | if (facets.contains(akey: XsdFacet::MaximumExclusive)) { |
584 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MaximumExclusive); |
585 | const Numeric::Ptr facetValue = ValueFactory::fromLexical(lexicalValue: facet->value()->as<DerivedString<TypeString> >()->stringValue(), type: BuiltinTypes::xsUnsignedLong, context: m_context, sourceLocationReflection: m_reflection); |
586 | if (facetValue->toUnsignedInteger() <= value) { |
587 | errorMsg = QtXmlPatterns::tr(sourceText: "Unsigned integer content does not match the maxExclusive facet." ); |
588 | return false; |
589 | } |
590 | } |
591 | if (facets.contains(akey: XsdFacet::MinimumInclusive)) { |
592 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MinimumInclusive); |
593 | const Numeric::Ptr facetValue = ValueFactory::fromLexical(lexicalValue: facet->value()->as<DerivedString<TypeString> >()->stringValue(), type: BuiltinTypes::xsUnsignedLong, context: m_context, sourceLocationReflection: m_reflection); |
594 | if (facetValue->toUnsignedInteger() > value) { |
595 | errorMsg = QtXmlPatterns::tr(sourceText: "Unsigned integer content does not match the minInclusive facet." ); |
596 | return false; |
597 | } |
598 | } |
599 | if (facets.contains(akey: XsdFacet::MinimumExclusive)) { |
600 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MinimumExclusive); |
601 | const Numeric::Ptr facetValue = ValueFactory::fromLexical(lexicalValue: facet->value()->as<DerivedString<TypeString> >()->stringValue(), type: BuiltinTypes::xsUnsignedLong, context: m_context, sourceLocationReflection: m_reflection); |
602 | if (facetValue->toUnsignedInteger() >= value) { |
603 | errorMsg = QtXmlPatterns::tr(sourceText: "Unsigned integer content does not match the minExclusive facet." ); |
604 | return false; |
605 | } |
606 | } |
607 | if (facets.contains(akey: XsdFacet::Enumeration)) { |
608 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Enumeration); |
609 | const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(np: m_namePool, lexical: QString::number(value)); |
610 | |
611 | const AtomicValue::List multiValue = facet->multiValue(); |
612 | bool found = false; |
613 | for (int j = 0; j < multiValue.count(); ++j) { |
614 | if (XsdSchemaHelper::constructAndCompare(operand1: valueStr, op: AtomicComparator::OperatorEqual, operand2: multiValue.at(i: j), type: BuiltinTypes::xsUnsignedLong, context: m_context, sourceLocationReflection: m_reflection)) { |
615 | found = true; |
616 | break; |
617 | } |
618 | } |
619 | |
620 | if (!found) { |
621 | errorMsg = QtXmlPatterns::tr(sourceText: "Unsigned integer content is not listed in the enumeration facet." ); |
622 | return false; |
623 | } |
624 | } |
625 | if (facets.contains(akey: XsdFacet::Pattern)) { |
626 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Pattern); |
627 | const AtomicValue::List multiValue = facet->multiValue(); |
628 | bool found = false; |
629 | for (int j = 0; j < multiValue.count(); ++j) { |
630 | const QString pattern = multiValue.at(i: j)->as<DerivedString<TypeString> >()->stringValue(); |
631 | QRegExp exp = PatternPlatform::parsePattern(pattern, context: m_context, location: m_reflection); |
632 | if (exp.exactMatch(str: lexicalValue)) { |
633 | found = true; |
634 | break; |
635 | } |
636 | } |
637 | |
638 | if (!found) { |
639 | errorMsg = QtXmlPatterns::tr(sourceText: "Unsigned integer content does not match pattern facet." ); |
640 | return false; |
641 | } |
642 | } |
643 | if (facets.contains(akey: XsdFacet::TotalDigits)) { |
644 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::TotalDigits); |
645 | const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value(); |
646 | |
647 | if (totalDigitsForUnsignedLongLong(value) > facetValue->toInteger()) { |
648 | errorMsg = QtXmlPatterns::tr(sourceText: "Unsigned integer content does not match in the totalDigits facet." ); |
649 | return false; |
650 | } |
651 | } |
652 | if (facets.contains(akey: XsdFacet::Assertion)) { |
653 | //TODO: implement |
654 | } |
655 | |
656 | return true; |
657 | } |
658 | |
659 | bool XsdTypeChecker::checkConstrainingFacetsDouble(double value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const |
660 | { |
661 | if (facets.contains(akey: XsdFacet::MaximumInclusive)) { |
662 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MaximumInclusive); |
663 | const Numeric::Ptr facetValue = ValueFactory::fromLexical(lexicalValue: facet->value()->as<DerivedString<TypeString> >()->stringValue(), type: BuiltinTypes::xsDouble, context: m_context, sourceLocationReflection: m_reflection); |
664 | if (facetValue->toDouble() < value) { |
665 | errorMsg = QtXmlPatterns::tr(sourceText: "Double content does not match the maxInclusive facet." ); |
666 | return false; |
667 | } |
668 | } |
669 | if (facets.contains(akey: XsdFacet::MaximumExclusive)) { |
670 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MaximumExclusive); |
671 | const Numeric::Ptr facetValue = ValueFactory::fromLexical(lexicalValue: facet->value()->as<DerivedString<TypeString> >()->stringValue(), type: BuiltinTypes::xsDouble, context: m_context, sourceLocationReflection: m_reflection); |
672 | if (facetValue->toDouble() <= value) { |
673 | errorMsg = QtXmlPatterns::tr(sourceText: "Double content does not match the maxExclusive facet." ); |
674 | return false; |
675 | } |
676 | } |
677 | if (facets.contains(akey: XsdFacet::MinimumInclusive)) { |
678 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MinimumInclusive); |
679 | const Numeric::Ptr facetValue = ValueFactory::fromLexical(lexicalValue: facet->value()->as<DerivedString<TypeString> >()->stringValue(), type: BuiltinTypes::xsDouble, context: m_context, sourceLocationReflection: m_reflection); |
680 | if (facetValue->toDouble() > value) { |
681 | errorMsg = QtXmlPatterns::tr(sourceText: "Double content does not match the minInclusive facet." ); |
682 | return false; |
683 | } |
684 | } |
685 | if (facets.contains(akey: XsdFacet::MinimumExclusive)) { |
686 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MinimumExclusive); |
687 | const Numeric::Ptr facetValue = ValueFactory::fromLexical(lexicalValue: facet->value()->as<DerivedString<TypeString> >()->stringValue(), type: BuiltinTypes::xsDouble, context: m_context, sourceLocationReflection: m_reflection); |
688 | if (facetValue->toDouble() >= value) { |
689 | errorMsg = QtXmlPatterns::tr(sourceText: "Double content does not match the minExclusive facet." ); |
690 | return false; |
691 | } |
692 | } |
693 | if (facets.contains(akey: XsdFacet::Enumeration)) { |
694 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Enumeration); |
695 | const DerivedString<TypeString>::Ptr valueStr = DerivedString<TypeString>::fromLexical(np: m_namePool, lexical: QString::number(value)); |
696 | |
697 | const AtomicValue::List multiValue = facet->multiValue(); |
698 | bool found = false; |
699 | for (int j = 0; j < multiValue.count(); ++j) { |
700 | if (XsdSchemaHelper::constructAndCompare(operand1: valueStr, op: AtomicComparator::OperatorEqual, operand2: multiValue.at(i: j), type: BuiltinTypes::xsDouble, context: m_context, sourceLocationReflection: m_reflection)) { |
701 | found = true; |
702 | break; |
703 | } |
704 | } |
705 | |
706 | if (!found) { |
707 | errorMsg = QtXmlPatterns::tr(sourceText: "Double content is not listed in the enumeration facet." ); |
708 | return false; |
709 | } |
710 | } |
711 | if (facets.contains(akey: XsdFacet::Pattern)) { |
712 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Pattern); |
713 | const AtomicValue::List multiValue = facet->multiValue(); |
714 | bool found = false; |
715 | for (int j = 0; j < multiValue.count(); ++j) { |
716 | const QString pattern = multiValue.at(i: j)->as<DerivedString<TypeString> >()->stringValue(); |
717 | QRegExp exp = PatternPlatform::parsePattern(pattern, context: m_context, location: m_reflection); |
718 | if (exp.exactMatch(str: lexicalValue)) { |
719 | found = true; |
720 | break; |
721 | } |
722 | } |
723 | |
724 | if (!found) { |
725 | errorMsg = QtXmlPatterns::tr(sourceText: "Double content does not match pattern facet." ); |
726 | return false; |
727 | } |
728 | } |
729 | if (facets.contains(akey: XsdFacet::Assertion)) { |
730 | //TODO: implement |
731 | } |
732 | |
733 | return true; |
734 | } |
735 | |
736 | bool XsdTypeChecker::checkConstrainingFacetsDecimal(const AtomicValue::Ptr &value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const |
737 | { |
738 | if (facets.contains(akey: XsdFacet::FractionDigits)) { |
739 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::FractionDigits); |
740 | const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value(); |
741 | |
742 | if (fractionDigitsForDecimal(lexicalValue) > facetValue->toInteger()) { |
743 | errorMsg = QtXmlPatterns::tr(sourceText: "Decimal content does not match in the fractionDigits facet." ); |
744 | return false; |
745 | } |
746 | } |
747 | if (facets.contains(akey: XsdFacet::TotalDigits)) { |
748 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::TotalDigits); |
749 | const DerivedInteger<TypePositiveInteger>::Ptr facetValue = facet->value(); |
750 | |
751 | if (totalDigitsForDecimal(lexicalValue) > facetValue->toInteger()) { |
752 | errorMsg = QtXmlPatterns::tr(sourceText: "Decimal content does not match in the totalDigits facet." ); |
753 | return false; |
754 | } |
755 | } |
756 | |
757 | return checkConstrainingFacetsDouble(value: value->as<Decimal>()->toDouble(), lexicalValue, facets, errorMsg); |
758 | } |
759 | |
760 | bool XsdTypeChecker::checkConstrainingFacetsDateTime(const QDateTime &value, const QString &lexicalValue, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const |
761 | { |
762 | if (facets.contains(akey: XsdFacet::MaximumInclusive)) { |
763 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MaximumInclusive); |
764 | const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(lexicalValue: facet->value()->as<DerivedString<TypeString> >()->stringValue(), type, context: m_context, sourceLocationReflection: m_reflection); |
765 | if (facetValue->toDateTime() < value) { |
766 | errorMsg = QtXmlPatterns::tr(sourceText: "Date time content does not match the maxInclusive facet." ); |
767 | return false; |
768 | } |
769 | } |
770 | if (facets.contains(akey: XsdFacet::MaximumExclusive)) { |
771 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MaximumExclusive); |
772 | const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(lexicalValue: facet->value()->as<DerivedString<TypeString> >()->stringValue(), type, context: m_context, sourceLocationReflection: m_reflection); |
773 | if (facetValue->toDateTime() <= value) { |
774 | errorMsg = QtXmlPatterns::tr(sourceText: "Date time content does not match the maxExclusive facet." ); |
775 | return false; |
776 | } |
777 | } |
778 | if (facets.contains(akey: XsdFacet::MinimumInclusive)) { |
779 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MinimumInclusive); |
780 | const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(lexicalValue: facet->value()->as<DerivedString<TypeString> >()->stringValue(), type, context: m_context, sourceLocationReflection: m_reflection); |
781 | if (facetValue->toDateTime() > value) { |
782 | errorMsg = QtXmlPatterns::tr(sourceText: "Date time content does not match the minInclusive facet." ); |
783 | return false; |
784 | } |
785 | } |
786 | if (facets.contains(akey: XsdFacet::MinimumExclusive)) { |
787 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MinimumExclusive); |
788 | const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(lexicalValue: facet->value()->as<DerivedString<TypeString> >()->stringValue(), type, context: m_context, sourceLocationReflection: m_reflection); |
789 | if (facetValue->toDateTime() >= value) { |
790 | errorMsg = QtXmlPatterns::tr(sourceText: "Date time content does not match the minExclusive facet." ); |
791 | return false; |
792 | } |
793 | } |
794 | if (facets.contains(akey: XsdFacet::Enumeration)) { |
795 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Enumeration); |
796 | |
797 | const AtomicValue::List multiValue = facet->multiValue(); |
798 | bool found = false; |
799 | for (int j = 0; j < multiValue.count(); ++j) { |
800 | const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(lexicalValue: multiValue.at(i: j)->as<DerivedString<TypeString> >()->stringValue(), type, context: m_context, sourceLocationReflection: m_reflection); |
801 | if (facetValue->toDateTime() == value) { |
802 | found = true; |
803 | break; |
804 | } |
805 | } |
806 | |
807 | if (!found) { |
808 | errorMsg = QtXmlPatterns::tr(sourceText: "Date time content is not listed in the enumeration facet." ); |
809 | return false; |
810 | } |
811 | } |
812 | if (facets.contains(akey: XsdFacet::Pattern)) { |
813 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Pattern); |
814 | const AtomicValue::List multiValue = facet->multiValue(); |
815 | bool found = false; |
816 | for (int j = 0; j < multiValue.count(); ++j) { |
817 | const QString pattern = multiValue.at(i: j)->as<DerivedString<TypeString> >()->stringValue(); |
818 | QRegExp exp = PatternPlatform::parsePattern(pattern, context: m_context, location: m_reflection); |
819 | if (exp.exactMatch(str: lexicalValue)) { |
820 | found = true; |
821 | break; |
822 | } |
823 | } |
824 | |
825 | if (!found) { |
826 | errorMsg = QtXmlPatterns::tr(sourceText: "Date time content does not match pattern facet." ); |
827 | return false; |
828 | } |
829 | } |
830 | |
831 | return true; |
832 | } |
833 | |
834 | bool XsdTypeChecker::checkConstrainingFacetsDuration(const AtomicValue::Ptr&, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const |
835 | { |
836 | if (facets.contains(akey: XsdFacet::MaximumInclusive)) { |
837 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MaximumInclusive); |
838 | const DerivedString<TypeString>::Ptr value = DerivedString<TypeString>::fromLexical(np: m_namePool, lexical: lexicalValue); |
839 | |
840 | if (XsdSchemaHelper::constructAndCompare(operand1: facets.value(akey: XsdFacet::MaximumInclusive)->value(), op: AtomicComparator::OperatorLessThan, operand2: value, type: BuiltinTypes::xsDuration, context: m_context, sourceLocationReflection: m_reflection)) { |
841 | errorMsg = QtXmlPatterns::tr(sourceText: "Duration content does not match the maxInclusive facet." ); |
842 | return false; |
843 | } |
844 | } |
845 | if (facets.contains(akey: XsdFacet::MaximumExclusive)) { |
846 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MaximumExclusive); |
847 | const DerivedString<TypeString>::Ptr value = DerivedString<TypeString>::fromLexical(np: m_namePool, lexical: lexicalValue); |
848 | |
849 | if (XsdSchemaHelper::constructAndCompare(operand1: facets.value(akey: XsdFacet::MaximumExclusive)->value(), op: AtomicComparator::OperatorLessOrEqual, operand2: value, type: BuiltinTypes::xsDuration, context: m_context, sourceLocationReflection: m_reflection)) { |
850 | errorMsg = QtXmlPatterns::tr(sourceText: "Duration content does not match the maxExclusive facet." ); |
851 | return false; |
852 | } |
853 | } |
854 | if (facets.contains(akey: XsdFacet::MinimumInclusive)) { |
855 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MinimumInclusive); |
856 | const DerivedString<TypeString>::Ptr value = DerivedString<TypeString>::fromLexical(np: m_namePool, lexical: lexicalValue); |
857 | |
858 | if (XsdSchemaHelper::constructAndCompare(operand1: facets.value(akey: XsdFacet::MinimumInclusive)->value(), op: AtomicComparator::OperatorGreaterThan, operand2: value, type: BuiltinTypes::xsDuration, context: m_context, sourceLocationReflection: m_reflection)) { |
859 | errorMsg = QtXmlPatterns::tr(sourceText: "Duration content does not match the minInclusive facet." ); |
860 | return false; |
861 | } |
862 | } |
863 | if (facets.contains(akey: XsdFacet::MinimumExclusive)) { |
864 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MinimumExclusive); |
865 | const DerivedString<TypeString>::Ptr value = DerivedString<TypeString>::fromLexical(np: m_namePool, lexical: lexicalValue); |
866 | |
867 | if (XsdSchemaHelper::constructAndCompare(operand1: facets.value(akey: XsdFacet::MinimumExclusive)->value(), op: AtomicComparator::OperatorGreaterOrEqual, operand2: value, type: BuiltinTypes::xsDuration, context: m_context, sourceLocationReflection: m_reflection)) { |
868 | errorMsg = QtXmlPatterns::tr(sourceText: "Duration content does not match the minExclusive facet." ); |
869 | return false; |
870 | } |
871 | } |
872 | if (facets.contains(akey: XsdFacet::Enumeration)) { |
873 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Enumeration); |
874 | const DerivedString<TypeString>::Ptr value = DerivedString<TypeString>::fromLexical(np: m_namePool, lexical: lexicalValue); |
875 | |
876 | const AtomicValue::List multiValue = facet->multiValue(); |
877 | bool found = false; |
878 | for (int j = 0; j < multiValue.count(); ++j) { |
879 | if (XsdSchemaHelper::constructAndCompare(operand1: multiValue.at(i: j), op: AtomicComparator::OperatorEqual, operand2: value, type: BuiltinTypes::xsDuration, context: m_context, sourceLocationReflection: m_reflection)) { |
880 | found = true; |
881 | break; |
882 | } |
883 | } |
884 | |
885 | if (!found) { |
886 | errorMsg = QtXmlPatterns::tr(sourceText: "Duration content is not listed in the enumeration facet." ); |
887 | return false; |
888 | } |
889 | } |
890 | if (facets.contains(akey: XsdFacet::Pattern)) { |
891 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Pattern); |
892 | const AtomicValue::List multiValue = facet->multiValue(); |
893 | bool found = false; |
894 | for (int j = 0; j < multiValue.count(); ++j) { |
895 | const QString pattern = multiValue.at(i: j)->as<DerivedString<TypeString> >()->stringValue(); |
896 | QRegExp exp = PatternPlatform::parsePattern(pattern, context: m_context, location: m_reflection); |
897 | if (exp.exactMatch(str: lexicalValue)) { |
898 | found = true; |
899 | break; |
900 | } |
901 | } |
902 | |
903 | if (!found) { |
904 | errorMsg = QtXmlPatterns::tr(sourceText: "Duration content does not match pattern facet." ); |
905 | return false; |
906 | } |
907 | } |
908 | if (facets.contains(akey: XsdFacet::Assertion)) { |
909 | //TODO: implement |
910 | } |
911 | |
912 | return true; |
913 | } |
914 | |
915 | bool XsdTypeChecker::checkConstrainingFacetsBoolean(bool, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const |
916 | { |
917 | if (facets.contains(akey: XsdFacet::Pattern)) { |
918 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Pattern); |
919 | const AtomicValue::List multiValue = facet->multiValue(); |
920 | bool found = false; |
921 | for (int j = 0; j < multiValue.count(); ++j) { |
922 | const QString pattern = multiValue.at(i: j)->as<DerivedString<TypeString> >()->stringValue(); |
923 | QRegExp exp = PatternPlatform::parsePattern(pattern, context: m_context, location: m_reflection); |
924 | if (exp.exactMatch(str: lexicalValue)) { |
925 | found = true; |
926 | break; |
927 | } |
928 | } |
929 | |
930 | if (!found) { |
931 | errorMsg = QtXmlPatterns::tr(sourceText: "Boolean content does not match pattern facet." ); |
932 | return false; |
933 | } |
934 | } |
935 | if (facets.contains(akey: XsdFacet::Assertion)) { |
936 | //TODO: implement |
937 | } |
938 | |
939 | return true; |
940 | } |
941 | |
942 | bool XsdTypeChecker::checkConstrainingFacetsBinary(const QByteArray &value, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const |
943 | { |
944 | if (facets.contains(akey: XsdFacet::Length)) { |
945 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Length); |
946 | const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value(); |
947 | if (length->toInteger() != value.length()) { |
948 | errorMsg = QtXmlPatterns::tr(sourceText: "Binary content does not match the length facet." ); |
949 | return false; |
950 | } |
951 | } |
952 | if (facets.contains(akey: XsdFacet::MinimumLength)) { |
953 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MinimumLength); |
954 | const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value(); |
955 | if (length->toInteger() > value.length()) { |
956 | errorMsg = QtXmlPatterns::tr(sourceText: "Binary content does not match the minLength facet." ); |
957 | return false; |
958 | } |
959 | } |
960 | if (facets.contains(akey: XsdFacet::MaximumLength)) { |
961 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::MaximumLength); |
962 | const DerivedInteger<TypeNonNegativeInteger>::Ptr length = facet->value(); |
963 | if (length->toInteger() < value.length()) { |
964 | errorMsg = QtXmlPatterns::tr(sourceText: "Binary content does not match the maxLength facet." ); |
965 | return false; |
966 | } |
967 | } |
968 | if (facets.contains(akey: XsdFacet::Enumeration)) { |
969 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Enumeration); |
970 | const AtomicValue::List multiValue = facet->multiValue(); |
971 | bool found = false; |
972 | for (int j = 0; j < multiValue.count(); ++j) { |
973 | const Base64Binary::Ptr binary = ValueFactory::fromLexical(lexicalValue: multiValue.at(i: j)->as<DerivedString<TypeString> >()->stringValue(), type, context: m_context, sourceLocationReflection: m_reflection); |
974 | const QByteArray facetValue = binary->as<Base64Binary>()->asByteArray(); |
975 | if (value == facetValue) { |
976 | found = true; |
977 | break; |
978 | } |
979 | } |
980 | |
981 | if (!found) { |
982 | errorMsg = QtXmlPatterns::tr(sourceText: "Binary content is not listed in the enumeration facet." ); |
983 | return false; |
984 | } |
985 | } |
986 | if (facets.contains(akey: XsdFacet::Pattern)) { |
987 | //TODO: implement |
988 | } |
989 | if (facets.contains(akey: XsdFacet::Assertion)) { |
990 | //TODO: implement |
991 | } |
992 | |
993 | return true; |
994 | } |
995 | |
996 | bool XsdTypeChecker::checkConstrainingFacetsQName(const QXmlName &value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const |
997 | { |
998 | if (facets.contains(akey: XsdFacet::Length)) { |
999 | // always true |
1000 | } |
1001 | if (facets.contains(akey: XsdFacet::MinimumLength)) { |
1002 | // always true |
1003 | } |
1004 | if (facets.contains(akey: XsdFacet::MaximumLength)) { |
1005 | // always true |
1006 | } |
1007 | if (facets.contains(akey: XsdFacet::Enumeration)) { |
1008 | if (!XPathHelper::isQName(qName: lexicalValue)) { |
1009 | errorMsg = QtXmlPatterns::tr(sourceText: "Invalid QName content: %1." ).arg(a: formatData(data: lexicalValue)); |
1010 | return false; |
1011 | } |
1012 | |
1013 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Enumeration); |
1014 | const AtomicValue::List multiValue = facet->multiValue(); |
1015 | bool found = false; |
1016 | for (int j = 0; j < multiValue.count(); ++j) { |
1017 | const QXmlName facetValue = multiValue.at(i: j)->as<QNameValue>()->qName(); |
1018 | |
1019 | if (value == facetValue) { |
1020 | found = true; |
1021 | break; |
1022 | } |
1023 | } |
1024 | |
1025 | if (!found) { |
1026 | errorMsg = QtXmlPatterns::tr(sourceText: "QName content is not listed in the enumeration facet." ); |
1027 | return false; |
1028 | } |
1029 | } |
1030 | if (facets.contains(akey: XsdFacet::Pattern)) { |
1031 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Pattern); |
1032 | const AtomicValue::List multiValue = facet->multiValue(); |
1033 | bool found = false; |
1034 | for (int j = 0; j < multiValue.count(); ++j) { |
1035 | const QString pattern = multiValue.at(i: j)->as<DerivedString<TypeString> >()->stringValue(); |
1036 | QRegExp exp = PatternPlatform::parsePattern(pattern, context: m_context, location: m_reflection); |
1037 | if (exp.exactMatch(str: lexicalValue)) { |
1038 | found = true; |
1039 | break; |
1040 | } |
1041 | } |
1042 | |
1043 | if (!found) { |
1044 | errorMsg = QtXmlPatterns::tr(sourceText: "QName content does not match pattern facet." ); |
1045 | return false; |
1046 | } |
1047 | } |
1048 | if (facets.contains(akey: XsdFacet::Assertion)) { |
1049 | //TODO: implement |
1050 | } |
1051 | |
1052 | return true; |
1053 | } |
1054 | |
1055 | bool XsdTypeChecker::checkConstrainingFacetsNotation(const QXmlName &value, const XsdFacet::Hash &facets, QString &errorMsg) const |
1056 | { |
1057 | if (facets.contains(akey: XsdFacet::Length)) { |
1058 | // deprecated by spec |
1059 | } |
1060 | if (facets.contains(akey: XsdFacet::MinimumLength)) { |
1061 | // deprecated by spec |
1062 | } |
1063 | if (facets.contains(akey: XsdFacet::MaximumLength)) { |
1064 | // deprecated by spec |
1065 | } |
1066 | if (facets.contains(akey: XsdFacet::Enumeration)) { |
1067 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Enumeration); |
1068 | const AtomicValue::List multiValue = facet->multiValue(); |
1069 | bool found = false; |
1070 | for (int j = 0; j < multiValue.count(); ++j) { |
1071 | const QXmlName facetValue = multiValue.at(i: j)->as<QNameValue>()->qName(); |
1072 | |
1073 | if (value == facetValue) { |
1074 | found = true; |
1075 | break; |
1076 | } |
1077 | } |
1078 | |
1079 | if (!found) { |
1080 | errorMsg = QtXmlPatterns::tr(sourceText: "Notation content is not listed in the enumeration facet." ); |
1081 | return false; |
1082 | } |
1083 | } |
1084 | if (facets.contains(akey: XsdFacet::Pattern)) { |
1085 | //TODO: implement |
1086 | } |
1087 | if (facets.contains(akey: XsdFacet::Assertion)) { |
1088 | //TODO: implement |
1089 | } |
1090 | |
1091 | return true; |
1092 | } |
1093 | |
1094 | bool XsdTypeChecker::checkConstrainingFacetsList(const QStringList &values, const QString &lexicalValue, const AnySimpleType::Ptr &itemType, const XsdFacet::Hash &facets, QString &errorMsg) const |
1095 | { |
1096 | if (facets.contains(akey: XsdFacet::Length)) { |
1097 | const DerivedInteger<TypeNonNegativeInteger>::Ptr value = facets.value(akey: XsdFacet::Length)->value(); |
1098 | if (value->toInteger() != values.count()) { |
1099 | errorMsg = QtXmlPatterns::tr(sourceText: "List content does not match length facet." ); |
1100 | return false; |
1101 | } |
1102 | } |
1103 | if (facets.contains(akey: XsdFacet::MinimumLength)) { |
1104 | const DerivedInteger<TypeNonNegativeInteger>::Ptr value = facets.value(akey: XsdFacet::MinimumLength)->value(); |
1105 | if (value->toInteger() > values.count()) { |
1106 | errorMsg = QtXmlPatterns::tr(sourceText: "List content does not match minLength facet." ); |
1107 | return false; |
1108 | } |
1109 | } |
1110 | if (facets.contains(akey: XsdFacet::MaximumLength)) { |
1111 | const DerivedInteger<TypeNonNegativeInteger>::Ptr value = facets.value(akey: XsdFacet::MaximumLength)->value(); |
1112 | if (value->toInteger() < values.count()) { |
1113 | errorMsg = QtXmlPatterns::tr(sourceText: "List content does not match maxLength facet." ); |
1114 | return false; |
1115 | } |
1116 | } |
1117 | if (facets.contains(akey: XsdFacet::Enumeration)) { |
1118 | |
1119 | bool found = false; |
1120 | |
1121 | // we have to handle lists with QName derived items differently |
1122 | if (BuiltinTypes::xsQName->wxsTypeMatches(other: itemType) || BuiltinTypes::xsNOTATION->wxsTypeMatches(other: itemType)) { |
1123 | // first convert the string values from the instance document to a list of QXmlName |
1124 | QList<QXmlName> instanceValues; |
1125 | for (int i = 0; i < values.count(); ++i) { |
1126 | instanceValues.append(t: convertToQName(name: values.at(i))); |
1127 | } |
1128 | |
1129 | // fetch the values from the facet and create a list of QXmlNames for each of them |
1130 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Enumeration); |
1131 | |
1132 | const AtomicValue::List multiValue = facet->multiValue(); |
1133 | for (int i = 0; i < multiValue.count(); ++i) { |
1134 | const QStringList facetValueList = multiValue.at(i)->as<DerivedString<TypeString> >()->stringValue().split(sep: QLatin1Char(' '), behavior: Qt::SkipEmptyParts); |
1135 | |
1136 | // create the list of atomic string values |
1137 | QList<QXmlName> facetValues; |
1138 | for (int j = 0; j < facetValueList.count(); ++j) { |
1139 | facetValues.append(t: convertToQName(name: facetValueList.at(i: j))); |
1140 | } |
1141 | |
1142 | // check if both lists have the same length |
1143 | if (instanceValues.count() != facetValues.count()) |
1144 | continue; |
1145 | |
1146 | // check if both lists are equal, that means the contain equal items in the same order |
1147 | bool matchesAll = true; |
1148 | for (int j = 0; j < instanceValues.count(); ++j) { |
1149 | if (instanceValues.at(i: j) != facetValues.at(i: j)) { |
1150 | matchesAll = false; |
1151 | break; |
1152 | } |
1153 | } |
1154 | |
1155 | if (matchesAll) { |
1156 | found = true; |
1157 | break; |
1158 | } |
1159 | } |
1160 | } else { |
1161 | // first convert the string values from the instance document to atomic values of type string |
1162 | AtomicValue::List instanceValues; |
1163 | for (int i = 0; i < values.count(); ++i) { |
1164 | instanceValues.append(t: DerivedString<TypeString>::fromLexical(np: m_namePool, lexical: values.at(i))); |
1165 | } |
1166 | |
1167 | // fetch the values from the facet and create a list of atomic string values for each of them |
1168 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Enumeration); |
1169 | |
1170 | const AnySimpleType::Ptr targetType = comparableType(type: itemType); |
1171 | |
1172 | const AtomicValue::List multiValue = facet->multiValue(); |
1173 | for (int i = 0; i < multiValue.count(); ++i) { |
1174 | const QStringList facetValueList = multiValue.at(i)->as<DerivedString<TypeString> >()->stringValue().split(sep: QLatin1Char(' '), behavior: Qt::SkipEmptyParts); |
1175 | |
1176 | // create the list of atomic string values |
1177 | AtomicValue::List facetValues; |
1178 | for (int j = 0; j < facetValueList.count(); ++j) { |
1179 | facetValues.append(t: DerivedString<TypeString>::fromLexical(np: m_namePool, lexical: facetValueList.at(i: j))); |
1180 | } |
1181 | |
1182 | // check if both lists have the same length |
1183 | if (instanceValues.count() != facetValues.count()) |
1184 | continue; |
1185 | |
1186 | // check if both lists are equal, that means the contain equal items in the same order |
1187 | bool matchesAll = true; |
1188 | for (int j = 0; j < instanceValues.count(); ++j) { |
1189 | if (!XsdSchemaHelper::constructAndCompare(operand1: instanceValues.at(i: j), op: AtomicComparator::OperatorEqual, operand2: facetValues.at(i: j), type: targetType, context: m_context, sourceLocationReflection: m_reflection)) { |
1190 | matchesAll = false; |
1191 | break; |
1192 | } |
1193 | } |
1194 | |
1195 | if (matchesAll) { |
1196 | found = true; |
1197 | break; |
1198 | } |
1199 | } |
1200 | } |
1201 | |
1202 | if (!found) { |
1203 | errorMsg = QtXmlPatterns::tr(sourceText: "List content is not listed in the enumeration facet." ); |
1204 | return false; |
1205 | } |
1206 | } |
1207 | if (facets.contains(akey: XsdFacet::Pattern)) { |
1208 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Pattern); |
1209 | const AtomicValue::List multiValue = facet->multiValue(); |
1210 | bool found = false; |
1211 | for (int j = 0; j < multiValue.count(); ++j) { |
1212 | const QString pattern = multiValue.at(i: j)->as<DerivedString<TypeString> >()->stringValue(); |
1213 | QRegExp exp = PatternPlatform::parsePattern(pattern, context: m_context, location: m_reflection); |
1214 | if (exp.exactMatch(str: lexicalValue)) { |
1215 | found = true; |
1216 | break; |
1217 | } |
1218 | } |
1219 | |
1220 | if (!found) { |
1221 | errorMsg = QtXmlPatterns::tr(sourceText: "List content does not match pattern facet." ); |
1222 | return false; |
1223 | } |
1224 | } |
1225 | if (facets.contains(akey: XsdFacet::Assertion)) { |
1226 | //TODO: implement |
1227 | } |
1228 | |
1229 | return true; |
1230 | } |
1231 | |
1232 | bool XsdTypeChecker::checkConstrainingFacetsUnion(const QString &value, const QString &lexicalValue, const XsdSimpleType::Ptr &simpleType, const XsdFacet::Hash &facets, QString &errorMsg) const |
1233 | { |
1234 | if (facets.contains(akey: XsdFacet::Enumeration)) { |
1235 | const AnySimpleType::List memberTypes = simpleType->memberTypes(); |
1236 | |
1237 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Enumeration); |
1238 | |
1239 | // convert the instance value into an atomic string value |
1240 | const DerivedString<TypeString>::Ptr valueString = DerivedString<TypeString>::fromLexical(np: m_namePool, lexical: value); |
1241 | |
1242 | // collect the facet values into a list of atomic string values |
1243 | const AtomicValue::List facetValues = facet->multiValue(); |
1244 | |
1245 | // compare the instance value against the facetValues for each member type and |
1246 | // search for a match |
1247 | |
1248 | bool found = false; |
1249 | for (int i = 0; i < memberTypes.count(); ++i) { |
1250 | const AnySimpleType::Ptr targetType = comparableType(type: memberTypes.at(i)); |
1251 | for (int j = 0; j < facetValues.count(); ++j) { |
1252 | if (XsdSchemaHelper::constructAndCompare(operand1: valueString, op: AtomicComparator::OperatorEqual, operand2: facetValues.at(i: j), type: targetType, context: m_context, sourceLocationReflection: m_reflection)) { |
1253 | found = true; |
1254 | break; |
1255 | } |
1256 | } |
1257 | } |
1258 | |
1259 | if (!found) { |
1260 | errorMsg = QtXmlPatterns::tr(sourceText: "Union content is not listed in the enumeration facet." ); |
1261 | return false; |
1262 | } |
1263 | } |
1264 | if (facets.contains(akey: XsdFacet::Pattern)) { |
1265 | const XsdFacet::Ptr facet = facets.value(akey: XsdFacet::Pattern); |
1266 | const AtomicValue::List multiValue = facet->multiValue(); |
1267 | bool found = false; |
1268 | for (int j = 0; j < multiValue.count(); ++j) { |
1269 | const QString pattern = multiValue.at(i: j)->as<DerivedString<TypeString> >()->stringValue(); |
1270 | QRegExp exp = PatternPlatform::parsePattern(pattern, context: m_context, location: m_reflection); |
1271 | if (exp.exactMatch(str: lexicalValue)) { |
1272 | found = true; |
1273 | break; |
1274 | } |
1275 | } |
1276 | |
1277 | if (!found) { |
1278 | errorMsg = QtXmlPatterns::tr(sourceText: "Union content does not match pattern facet." ); |
1279 | return false; |
1280 | } |
1281 | } |
1282 | if (facets.contains(akey: XsdFacet::Assertion)) { |
1283 | //TODO: implement |
1284 | } |
1285 | |
1286 | return true; |
1287 | } |
1288 | |
1289 | AtomicValue::Ptr XsdTypeChecker::fromLexical(const QString &value, const SchemaType::Ptr &type, const ReportContext::Ptr &context, const SourceLocationReflection *const reflection) const |
1290 | { |
1291 | if (type->name(np: m_namePool) == BuiltinTypes::xsNOTATION->name(np: m_namePool) || type->name(np: m_namePool) == BuiltinTypes::xsQName->name(np: m_namePool)) { |
1292 | if (value.simplified().isEmpty()) |
1293 | return ValidationError::createError(description: QtXmlPatterns::tr(sourceText: "Data of type %1 are not allowed to be empty." ).arg(a: formatType(np: m_namePool, type: BuiltinTypes::xsNOTATION))); |
1294 | |
1295 | const QXmlName valueName = convertToQName(name: value); |
1296 | return QNameValue::fromValue(np: m_namePool, name: valueName); |
1297 | } else { |
1298 | return ValueFactory::fromLexical(lexicalValue: value, type, context, sourceLocationReflection: reflection); |
1299 | } |
1300 | } |
1301 | |
1302 | QXmlName XsdTypeChecker::convertToQName(const QString &name) const |
1303 | { |
1304 | const int pos = name.indexOf(c: QLatin1Char(':')); |
1305 | |
1306 | QXmlName::PrefixCode prefixCode = 0; |
1307 | QXmlName::NamespaceCode namespaceCode; |
1308 | QXmlName::LocalNameCode localNameCode; |
1309 | if (pos != -1) { |
1310 | prefixCode = m_context->namePool()->allocatePrefix(prefix: name.left(n: pos)); |
1311 | namespaceCode = StandardNamespaces::empty; |
1312 | for (int i = 0; i < m_namespaceBindings.count(); ++i) { |
1313 | if (m_namespaceBindings.at(i).prefix() == prefixCode) { |
1314 | namespaceCode = m_namespaceBindings.at(i).namespaceURI(); |
1315 | break; |
1316 | } |
1317 | } |
1318 | localNameCode = m_context->namePool()->allocateLocalName(ln: name.mid(position: pos + 1)); |
1319 | } else { |
1320 | prefixCode = StandardPrefixes::empty; |
1321 | namespaceCode = StandardNamespaces::empty; |
1322 | for (int i = 0; i < m_namespaceBindings.count(); ++i) { |
1323 | if (m_namespaceBindings.at(i).prefix() == prefixCode) { |
1324 | namespaceCode = m_namespaceBindings.at(i).namespaceURI(); |
1325 | break; |
1326 | } |
1327 | } |
1328 | localNameCode = m_context->namePool()->allocateLocalName(ln: name); |
1329 | } |
1330 | |
1331 | return QXmlName(namespaceCode, localNameCode, prefixCode); |
1332 | } |
1333 | |
1334 | QT_END_NAMESPACE |
1335 | |