174#if QT_CONFIG(xmlstreamreader)
175 QMimeTypeXMLData data;
177 QStack<QMimeMagicRule *> currentRules;
178 QList<QMimeMagicRule> rules;
179 QXmlStreamReader reader(dev);
180 ParseState ps = ParseBeginning;
181 while (!reader.atEnd()) {
182 switch (reader.readNext()) {
183 case QXmlStreamReader::StartElement: {
184 ps = nextState(ps, reader.name());
185 const QXmlStreamAttributes atts = reader.attributes();
187 case ParseMimeType: {
188 const QString name = atts.value(QLatin1StringView(mimeTypeAttributeC)).toString();
189 if (name.isEmpty()) {
190 reader.raiseError(QStringLiteral(
"Missing 'type'-attribute"));
196 case ParseGenericIcon:
197 data.genericIconName = atts.value(QLatin1StringView(nameAttributeC)).toString();
200 data.iconName = atts.value(QLatin1StringView(nameAttributeC)).toString();
202 case ParseGlobPattern: {
203 const QString pattern = atts.value(QLatin1StringView(patternAttributeC)).toString();
204 unsigned weight = atts.value(QLatin1StringView(weightAttributeC)).toInt();
205 const bool caseSensitive = atts.value(QLatin1StringView(caseSensitiveAttributeC)) ==
"true"_L1;
208 weight = QMimeGlobPattern::DefaultWeight;
210 Q_ASSERT(!data.name.isEmpty());
211 const QMimeGlobPattern glob(pattern, data.name, weight, caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive);
212 if (!process(glob, errorMessage))
214 data.addGlobPattern(pattern);
217 case ParseGlobDeleteAll:
218 data.globPatterns.clear();
219 data.hasGlobDeleteAll =
true;
221 case ParseSubClass: {
222 const QString inheritsFrom = atts.value(QLatin1StringView(mimeTypeAttributeC)).toString();
223 if (!inheritsFrom.isEmpty())
224 processParent(data.name, inheritsFrom);
229 QString locale = atts.value(QLatin1StringView(localeAttributeC)).toString();
230 const QString comment = reader.readElementText();
231 if (locale.isEmpty())
232 locale = QString::fromLatin1(
"default");
233 data.localeComments.insert(locale, comment);
237 const QString alias = atts.value(QLatin1StringView(mimeTypeAttributeC)).toString();
238 if (!alias.isEmpty())
239 processAlias(alias, data.name);
244 const auto priorityS = atts.value(QLatin1StringView(priorityAttributeC));
245 if (!priorityS.isEmpty()) {
246 if (!parseNumber(priorityS, &priority, errorMessage))
250 currentRules.clear();
254 case ParseMagicMatchRule: {
258 if (currentRules.size() >= QMimeMagicRule::MaxRecursionDepth) {
259 reader.raiseError(
"<match> elements nested more than "_L1
260 + QString::number(QMimeMagicRule::MaxRecursionDepth)
261 +
" levels deep"_L1);
264 auto result = createMagicMatchRule(atts);
265 if (Q_UNLIKELY(!result.rule.isValid()))
266 qWarning(
"QMimeDatabase: Error parsing %ls\n%ls",
267 qUtf16Printable(fileName), qUtf16Printable(result.errorMessage));
268 QList<QMimeMagicRule> *ruleList;
269 if (currentRules.isEmpty())
272 ruleList = ¤tRules.top()->m_subMatches;
273 ruleList->append(std::move(result.rule));
275 currentRules.push(&ruleList->last());
279 reader.raiseError(
"Unexpected element <"_L1 + reader.name() + u'>');
287 case QXmlStreamReader::EndElement:
289 const auto elementName = reader.name();
290 if (elementName == QLatin1StringView(mimeTypeTagC)) {
291 if (!process(data, errorMessage))
294 }
else if (elementName == QLatin1StringView(matchTagC)) {
298 }
else if (elementName == QLatin1StringView(magicTagC)) {
301 QMimeMagicRuleMatcher ruleMatcher(data.name, priority);
302 ruleMatcher.addRules(rules);
303 processMagicMatcher(ruleMatcher);
305 ps = ParseOtherMimeTypeSubTag;
314 if (Q_UNLIKELY(reader.hasError())) {
316 *errorMessage = QString::asprintf(
"An error has been encountered at line %lld of %ls: %ls:",
318 qUtf16Printable(fileName),
319 qUtf16Printable(reader.errorString()));
328 *errorMessage =
"QXmlStreamReader is not available, cannot parse '%1'."_L1.arg(fileName);