XQuery
Введение
XQuery — это язык для обхода XML-документов, позволяющий выбирать и агрегировать интересующие элементы, а также преобразовывать их в XML или другой формат вывода. XPath — это часть XQuery, отвечающая за выбор элементов.
Модуль Qt XML Patterns поддерживает использование XQuery 1.0 и XPath 2.0 в приложениях Qt для запроса данных XML и для запроса данных, не являющихся XML, которые могут быть смоделированы как XML. Читатели, не знакомые с языком XQuery/XPath, могут прочитать Краткое руководство по XQuery для краткого введения.
Преимущества использования Qt XML Patterns и XQuery
Язык XQuery/XPath упрощает задачи поиска и преобразования данных, исключая необходимость написания большого объёма процедурной программы на C++ или Java для каждого нового запроса. Вот пример XQuery, который строит библиографию содержимого библиотеки:
<bibliography>
{doc("library.xml")/bib/book[publisher="Addison-Wesley" and @year>1991]/<book year="{@year}">{title}</book>}
</bibliography> Сначала запрос открывает элемент <bibliography> в выводе. Встроенное выражение пути (выражение пути) затем загружает XML-документ, описывающий содержимое библиотеки (library.xml), и начинает поиск. Для каждого <book> элемента, который он находит, где издателем был Addison-Wesley, а год публикации был после 1991 года, он создаёт новый элемент <book> в выводе как дочерний элемент открытого элемента <bibliography>. Каждый новый элемент <book> получает название книги в качестве содержимого и год публикации книги в качестве атрибута. Наконец, элемент <bibliography> закрывается.
Преимущества использования Qt XML Patterns и XQuery в ваших программах Qt можно резюмировать следующим образом:
- Простота разработки: Весь код C++, необходимый для выполнения задач по запросу данных, можно заменить простым XQuery, как в приведённом выше примере.
- Комплексная функциональность: Синтаксис выражений (синтаксис выражений) и богатый набор функций и операторов (функций и операторов) XQuery достаточно для выполнения любых задач поиска, выбора и сортировки данных.
- Соответствие стандартам: Соответствие всем применимым стандартам XML и XQuery гарантирует, что Qt XML Patterns всегда сможет обрабатывать XML-документы, сгенерированные другими соответствующими приложениями, и что XML-документы, созданные с помощью Qt XML Patterns, могут быть обработаны другими соответствующими приложениями.
- Максимальная гибкость Модуль Qt XML Patterns может быть использован для запроса данных XML и данных, не являющихся XML, которые могут быть смоделированы как XML.
Использование модуля Qt XML Patterns
Существует два способа использования Qt XML Patterns для оценки запросов. Вы можете запустить движок запросов в своём приложении Qt, используя API Qt XML Patterns на C++, или запустить движок запросов из командной строки, используя утилиту xmlpatterns командной строки Qt.
Запуск движка запросов из вашего приложения Qt
Если мы сохраним пример XQuery, показанный выше, в текстовом файле (например, myquery.xq), мы можем запустить его из приложения Qt, используя стандартную последовательность кода Qt XML Patterns:
QFile xq("myquery.xq");
QXmlQuery query;
query.setQuery(&xq, QUrl::fromLocalFile(xq.fileName()));
QXmlSerializer serializer(query, myOutputDevice);
query.evaluateTo(&serializer); Сначала создайте QFile для текстового файла, содержащего XQuery (myquery.xq). Затем создайте экземпляр QXmlQuery и вызовите его функцию setQuery() для загрузки и парсинга файла XQuery. Затем создайте сериализатор XML для вывода набора результатов запроса в виде неформатированного XML. Наконец, вызовите функцию evaluateTo() для оценки запроса и сериализации результатов в виде XML.
Примечание: Если вы компилируете Qt самостоятельно, модуль Qt XML Patterns не будет скомпилирован, если исключения отключены, или если вы компилируете Qt с компилятором, не поддерживающим шаблоны членов, например, MSVC 6.
См. документацию QXmlQuery для получения дополнительной информации об API Qt XML Patterns на C++.
Запуск движка запросов из утилиты командной строки
xmlpatterns — это утилита командной строки для выполнения XQuery. Она ожидает имя файла, содержащего текст XQuery.
xmlpatterns myQuery.xq
XQuery в myQuery.xq будет оценён, и его вывод будет записан в stdout. Передайте переключатель -help для получения списка входных флагов и их значений.
xmlpatterns можно использовать в скриптах. Однако описания и сообщения, которые она выводит, не предназначены для парсинга и могут быть изменены в будущих выпусках Qt.
Модель данных XQuery
XQuery представляет элементы данных как атомные значения или узлы. Атомное значение — это значение в области одного из встроенных типов данных, определённых во части 2 спецификации W3C XML Schema. Узел обычно представляет собой XML-элемент или атрибут, но когда данные, не являющиеся XML, смоделированы как XML, узел может также представлять собой данные, не являющиеся XML.
При выполнении XQuery с помощью API на C++ в приложении Qt вы часто захотите связать переменные программы с $переменными в XQuery. После оценки запроса вы захотите интерпретировать последовательность элементов данных в наборе результатов.
Связывание переменных программы с переменными XQuery
Если вы хотите запустить параметризованный XQuery из своего приложения Qt, вам необходимо связать переменные в вашей программе с переменными $имя в вашем XQuery.
Предположим, вы хотите параметризовать XQuery библиографии в примере выше. Вы могли бы определить переменные для каталога, содержащего библиотеку ($file), имя издателя ($publisher) и год публикации ($year):
<bibliography>
{
doc($file)/bib/book[publisher = $publisher and @year > $year]/<book year="{@year}">{title}</book>
}
</bibliography> Измените код Qt XML Patterns, чтобы использовать одну из функций bindVariable() для связывания переменной программы с каждой переменной $переменной XQuery:
QFile xq("myquery.xq");
QString fileName("the filename");
QString publisherName("the publisher");
qlonglong year = 1234;
QXmlQuery query;
query.bindVariable("file", QVariant(fileName));
query.bindVariable("publisher", QVariant(publisherName));
query.bindVariable("year", QVariant(year));
query.setQuery(&xq, QUrl::fromLocalFile(xq.fileName()));
QXmlSerializer serializer(query, myOutputDevice);
query.evaluateTo(&serializer); Каждая переменная программы передаётся в Qt XML Patterns как QVariant типа переменной или константы C++, из которой она построена. Обратите внимание, что Qt XML Patterns предполагает, что тип QVariant в вызове bindVariable() является правильным типом, поэтому $переменная, к которой он привязан, должна использоваться в XQuery соответствующим образом. В следующей таблице показано, как типы QVariant отображаются в типы XQuery $переменных:
| QVariant тип | Тип XQuery $переменной |
|---|---|
| QVariant::LongLong | xs:integer |
| QVariant::Int | xs:integer |
| QVariant::UInt | xs:nonNegativeInteger |
| QVariant::ULongLong | xs:unsignedLong |
| QVariant::String | xs:string |
| QVariant::Double | xs:double |
| QVariant::Bool | xs:boolean |
| QVariant::Double | xs:decimal |
| QVariant::ByteArray | xs:base64Binary |
| QVariant::StringList | xs:string* |
| QVariant::Url | xs:string |
| QVariant::Date |
xs:date. |
| QVariant::DateTime | xs:dateTime |
| QVariant::Time. |
xs:time. (см. Связывание с QVariant::Time ниже) |
| QVariantList | (см. Связывание со списком QVariant ниже) |
Тип, не показанный в таблице, не поддерживается и приведёт к неопределённому поведению XQuery или ошибке связывания $переменной в зависимости от контекста в XQuery, где используется переменная.
Связывание со временем QVariant
Поскольку экземпляр QTime, используемый в QVariant::Time, не включает смещение зоны, экземпляр QVariant::Time не должен быть привязан к переменной XQuery типа xs:time, если QTime не является UTC. При привязке не-UTC QTime к переменной XQuery, он должен быть сначала передан как строка или преобразован в QDateTime с произвольной датой, а затем привязан к переменной XQuery типа xs:dateTime.
Связывание со списком QVariant
Список QVariantList можно привязать к переменной XQuery $переменной. Все QVariant в списке должны быть одного атомного типа, и $переменная, к которой привязан список вариантов, должна быть того же атомного типа. Если QVariants в списке не все одного атомного типа, поведение XQuery неопределённо.
Интерпретация результатов XQuery
Когда результаты XQuery возвращаются в последовательности элементов результатов, атомные значения в последовательности обрабатываются как экземпляры QVariant. Предположим, что вместо сериализации результатов XQuery как XML, мы обрабатываем результаты программно. Измените стандартную последовательность кода Qt XML Patterns, чтобы вызвать перегрузку QXmlQuery::evaluateTo(), которая заполняет последовательность элементов результатов результатами XQuery:
QFile xq("myquery.xq");
QString fileName("the filename");
QString publisherName("the publisher");
qlonglong year = 1234;
QXmlQuery query;
query.bindVariable("file", QVariant(fileName));
query.bindVariable("publisher", QVariant(publisherName));
query.bindVariable("year", QVariant(year));
query.setQuery(&xq, QUrl::fromLocalFile(xq.fileName()));
QXmlResultItems result;
query.evaluateTo(&result);
QXmlItem item(result.next());
while (!item.isNull()) {
if (item.isAtomicValue()) {
QVariant v = item.toAtomicValue();
switch (v.type()) {
case QVariant::LongLong:
// xs:integer
break;
case QVariant::String:
// xs:string
break;
default:
// error
break;
}
}
else if (item.isNode()) {
#ifdef qdoc
QXmlNodeModelIndex i = item.toNodeModelIndex();
// process node
#endif // qdoc
}
item = result.next();
} Переберите элементы результатов и проверьте каждый QXmlItem, чтобы узнать, является ли он атомным значением или узлом. Если это атомное значение, преобразуйте его в QVariant с помощью toAtomicValue() и переключайтесь на его тип варианта, чтобы обработать все атомные значения, которые может вернуть ваш XQuery. В следующей таблице показан тип QVariant, ожидаемый для каждого атомного типа (или QXmlName):
| Тип элемента результата XQuery | Возвращаемый тип QVariant |
|---|---|
xs:QName |
QXmlName (см. Обработка QXmlNames ниже) |
xs:integer |
QVariant::LongLong |
xs:string |
QVariant::String |
xs:string* |
QVariant::StringList |
xs:double |
QVariant::Double |
xs:float |
QVariant::Double |
xs:boolean |
QVariant::Bool |
xs:decimal |
QVariant::Double |
xs:hexBinary |
QVariant::ByteArray |
xs:base64Binary |
QVariant::ByteArray |
xs:gYear |
QVariant::DateTime |
xs:gYearMonth |
QVariant::DateTime |
xs:gMonthDay |
QVariant::DateTime |
xs:gDay |
QVariant::DateTime |
xs:gMonth |
QVariant::DateTime |
xs:anyURI |
QVariant::Url |
xs:untypedAtomic |
QVariant::String |
xs:ENTITY |
QVariant::String |
xs:date |
QVariant::DateTime |
xs:dateTime |
QVariant::DateTime |
xs:time |
(см. Отсутствие сопоставления для xs:time ниже) |
Обработка QXmlNames
Если ваш XQuery может возвращать атомарные значения типа xs:QName, они будут появляться в ваших QXmlResultItems как экземпляры QXmlName. Поскольку класс QVariant напрямую не поддерживает класс QXmlName, извлечение их из QXmlResultItems требует небольшого ухищрения с использованием системы метатипов Qt. Мы должны изменить наш пример, чтобы использовать пару шаблонных функций, друга QMetaType (qMetaTypeId<T>()) и друга QVariant (qvariant_cast<T>()):
QFile xq("myquery.xq");
QXmlQuery query;
query.setQuery(&xq, QUrl::fromLocalFile(xq.fileName()));
QXmlResultItems result;
query.evaluateTo(&result);
QXmlItem item(result.next());
while (!item.isNull()) {
if (item.isAtomicValue()) {
QVariant v = item.toAtomicValue();
switch (v.type()) {
case QVariant::LongLong:
// xs:integer
break;
case QVariant::String:
// xs:string
break;
default:
if (v.userType() == qMetaTypeId<QXmlName>()) {
#ifdef qdoc
QXmlName n = qvariant_cast<QXmlName>(v);
// process QXmlName n...
#endif // qdoc
}
else {
// error
}
break;
}
}
else if (item.isNode()) {
#ifdef qdoc
QXmlNodeModelIndex i = item.toNodeModelIndex();
// process node
#endif // qdoc
}
item = result.next();
} Для доступа к строкам в QXmlName, возвращаемой результатом оценки XQuery, необходимо обратиться к QXmlName с помощью пула имен из экземпляра QXmlQuery, который использовался для оценки.
Отсутствие сопоставления для xs:time
Экземпляр xs:time не может быть правильно представлен как экземпляр QVariant::Time, если xs:time не является временем UTC. Это связано с тем, что xs:time имеет смещение часового пояса (0 для UTC) в дополнение к значению времени, чего нет в QTime в QVariant::Time. Это означает, что если XQuery пытается вернуть атомарное значение типа xs:time, будет возвращено недопустимое QVariant. Запрос может вернуть атомарное значение типа xs:time, либо преобразовав его в xs:dateTime с произвольной датой, либо в xs:string.
Использование XQuery с данными, не являющимися XML
Хотя язык XQuery был разработан для запросов к XML, с Qt XML Patterns можно использовать XQuery для запросов к любым данным, которые можно смоделировать как XML. Данные, не являющиеся XML, моделируются как XML путем загрузки их в пользовательский подкласс QAbstractXmlNodeModel, где они затем представляются движку XQuery Qt XML Patterns через тот же API, который движок XQuery использует для запросов к XML.
Когда Qt XML Patterns загружает и запрашивает файлы XML и генерирует XML-вывод, он всегда может загрузить XML-данные в свою стандартную модель узлов XML, где они могут быть эффективно обработаны. Нижеследующий XQuery проходит по заказам продуктов, найденным в файле XML myOrders.xml, чтобы найти все заказы на косметические продукты и вывести их, отсортированные по дате доставки.
<result>
<para>The following skin care products have shipped, ordered by shipping date(oldest first):</para>
{
for $i in doc("myOrders.xml")/orders/order[@product = "Acme Skin Care"]
order by xs:date($i/@shippingDate) descending
return $i
}
</result> Qt XML Patterns может быть использован «из коробки» для выполнения этого запроса, при условии, что myOrders.xml действительно содержит корректный XML. Он может быть загружен непосредственно в стандартную модель узлов XML и обработан. Но предположим, что мы хотим, чтобы Qt XML Patterns выполнял запросы к иерархической структуре локальной файловой системы. Стандартная модель узлов XML в Qt XML Patterns не подходит для навигации по файловой системе, потому что нет файла XML для загрузки, содержащего её описание. Такой файл XML, если бы он существовал, мог бы выглядеть примерно так:
<?xml version="1.0" encoding="UTF-8"?>
<directory name="home">
<file name="myNote.txt" mimetype="text/plain" size="8" extension="txt" uri="file:///home/frans/myNote.txt">
<content asBase64Binary="TXkgTm90ZSE=" asStringFromUTF-8="My Note!"/>
</file>
<directory name="src">
...
</directory>
...
</directory> Пример файловой системы делает именно это.
Нет такого файла, который можно было бы загрузить в стандартную модель узлов XML, но можно написать подкласс QAbstractXmlNodeModel для представления файловой системы. Эта настраиваемая модель узлов XML, после заполнения всеми дескрипторами каталогов и файлов, полученными непосредственно из системы, представляет полную иерархию файловой системы движку запросов через тот же API, используемый стандартной моделью узлов XML для представления содержимого файла XML. Другими словами, после заполнения настраиваемой модели узлов XML она представляет файловую систему движку запросов так, как будто её описание было загружено в стандартную модель узлов XML из файла XML, подобного показанному выше.
Теперь мы можем написать XQuery, чтобы найти все XML-файлы и проанализировать их, чтобы найти те, которые не содержат корректного XML.
<html>
<body>
{
$myRoot//file[@mimetype = 'text/xml' or @mimetype = 'application/xml']
/
(if(doc-available(@uri))
then ()
else <p>Failed to parse file {@uri}.</p>)
}
</body>
</html> Без Qt XML Patterns нет простого способа решить эту проблему. Вы можете написать программу на C++, которая будет перебирать файловую систему, находить все XML-файлы и передавать каждый из них в XML-парсер, чтобы проверить, содержит ли он корректный XML. C++-код, необходимый для написания такой программы, вероятно, будет сложнее, чем C++-код, необходимый для создания подкласса QAbstractXmlNodeModel, но даже если они сопоставимы, ваша настраиваемая C++-программа может использоваться только для одной задачи, в то время как ваша настраиваемая модель узлов XML может использоваться любым XQuery, которому необходимо перемещаться по файловой системе.
Общий подход к использованию XQuery для выполнения запросов к данным, не являющимся XML, состоял из трёх шагов. На первом шаге данные загружаются в модель данных, не являющуюся XML. На втором шаге модель данных, не являющаяся XML, сериализуется как XML и выводится в XML (текстовые) файлы. На последнем шаге инструмент XML загружает XML-файлы во вторую, XML-модель данных, где можно выполнять запросы XQuery. Стоимость разработки для реализации этого процесса часто высока, а полученная трёхшаговая система неэффективна, поскольку две модели данных должны быть построены и поддерживаются отдельно.
С помощью Qt XML Patterns создание подкласса QAbstractXmlNodeModel устраняет необходимость преобразования, требуемого для перевода модели данных, не являющейся XML, в XML-модель данных, так как необходима только одна модель данных. Модель данных, не являющаяся XML, предоставляет данные, не являющиеся XML, движку запросов через API XML-модели данных. Кроме того, так как движок запросов использует API для доступа к QAbstractXmlNodeModel, подкласс модели данных может создавать элементы, атрибуты и другие данные по запросу, реагируя на специфические запросы запроса. Это может значительно повысить эффективность, поскольку это означает, что вся модель может не потребоваться. Например, в модели файловой системы выше нет необходимости создавать экземпляр для всего XML-файла, представляющего всю файловую систему. Вместо этого узлы создаются по требованию, что также, вероятно, является небольшой частью файловой системы.
Примеры других мест, где XQuery может быть использован в Qt XML Patterns для запросов к данным, не являющимся XML:
- Внутреннее представление документов текстового процессора
- Набор зависимостей для системы сборки программного обеспечения
- Иерархия (или граф), связывающий набор HTML-документов из веб-робота
- Изображения и метаданные в коллекции изображений
- Набор доступных интерфейсов D-Bus в системе
- Иерархия QObject.
См. документацию QAbstractXmlNodeModel для получения информации о том, как реализовать пользовательские модели узлов XML.
Подробнее об использовании Qt XML Patterns с данными, не являющимися XML
Наследование от QAbstractXmlNodeModel для предоставления движку запросов доступа к данным, не являющимся XML, с помощью того же API, который он использует для XML, является функцией, которая позволяет Qt XML Patterns выполнять запросы к данным, не являющимся XML, с помощью XQuery. Это позволяет XQuery использоваться в качестве слоя отображения между различными моделями узлов, не являющимися XML, или между моделью узлов, не являющейся XML, и встроенной моделью узлов XML. После написания подклассов QAbstractXmlNodeModel можно использовать XQuery для выбора набора элементов из одной модели узлов, преобразования выбранных элементов и вывода их, либо как XML с помощью QXmlQuery::evaluateTo() и QXmlSerializer, либо в каком-либо другом формате с помощью подкласса QAbstractXmlReceiver.
Рассмотрим приложение текстового процессора, которое должно импортировать и экспортировать данные в нескольких форматах. Вместо написания большого количества C++-кода для преобразования каждого входного формата во внутренний вид и большего количества C++-кода для преобразования внутреннего вида обратно в каждый выходной формат, можно реализовать решение на основе Qt XML Patterns, которое использует простые XQuery для преобразования каждого XML- или не-XML-формата (например, MathFormula.xml ниже) во внутренний формат (например, класс модели узлов DocumentRepresentation ниже) и простые XQuery для преобразования внутреннего формата обратно в каждый XML- или не-XML-формат.
Так как CSV-файлы не являются XML, используется подкласс QAbstractXmlNodeModel для представления данных CSV движку XQuery так, как будто это XML. Не показаны подклассы QAbstractXmlReceiver, которые затем отправляли бы выбранные элементы в модель узлов DocumentRepresentation, и подклассы QAbstractXmlNodeModel, которые в конечном итоге записывали бы выходные файлы в каждом формате.
Учёт безопасности
Вставка кода
XQuery уязвим для атак с внедрением кода так же, как и язык SQL. Если XQuery конструируется путём конкатенации строк, а строки получены из пользовательского ввода, то сконструированный XQuery может быть злонамеренным. Лучший способ предотвратить атаки с внедрением кода – не конструировать XQuery из пользовательских строк, а принимать пользовательские данные только с использованием QVariant и связывания переменных. Обратитесь к QXmlQuery::bindVariable().
В статьях Избегайте опасностей XPath-инъекций, Робби Сен, и Blind XPath Injection, Амит Кляйн, подробнее рассматривается проблема внедрения кода в XQuery.
Атаки с отказом в обслуживании
Приложения, использующие Qt XML Patterns, подвержены тем же ограничениям программного обеспечения, что и другие системы. Как правило, они не могут быть проверены. Это означает, что Qt XML Patterns не предотвращает несанкционированные запросы, потребляющие слишком много ресурсов. Например, запрос может занимать слишком много времени для выполнения или пытаться передать слишком много данных. Запрос также может выполнять слишком много рекурсий, что может привести к сбою системы. XQuery могут делать это случайно, но их также можно использовать в качестве преднамеренных атак с отказом в обслуживании.
Функции и соответствие
XQuery 1.0
Qt XML Patterns стремится быть соответствующим процессором XQuery. Он соответствует Минимальному соответствию и поддерживает Функцию сериализации и Полную функцию осей. Qt XML Patterns в настоящее время проходит 97% тестов в наборе тестов XML Query. Области, где соответствие может вызывать сомнения, и где поведение может быть изменено в будущих выпусках, включают:
- Некоторые частные случаи, связанные с именами пространств и конструкторами элементов, некорректны.
- XPath является подмножеством XQuery, и реализация Qt XML Patterns использует XPath 2.0 с XQuery 1.0.
В спецификации соответствие рассматривается подробнее: XQuery 1.0: Язык запросов XML. Также может быть интересен проект тестирования XQuery W3C, XML Query Test Suite.
В настоящее время fn:collection() не получает доступ к набору данных, и нет API для предоставления данных через коллекцию. В результате, оценка fn:collection() возвращает пустую последовательность. Мы намерены обеспечить эту функциональность в будущей версии Qt.
Поддерживаются только запросы, закодированные в UTF-8.
XSLT 2.0
Частичная поддержка XSLT была введена в Qt 4.5. Будущие версии Qt XML Patterns будут направлены на поддержку следующих функций XSLT:
- Базовый процессор XSLT 2.0
- Функция сериализации
- Функция обратной совместимости
Подробности см. в XSL Transformations (XSLT) Version 2.0, 21 Соответствие.
Примечание: В этом выпуске поддержка XSLT считается экспериментальной.
Функции XSLT, которые не поддерживаются или частично поддерживаются, документированы в следующей таблице. Реализация XSLT в Qt 4.5 можно рассматривать как XSLT 1.0, но с моделью данных XPath 2.0 и XSLT 2.0, а также с использованием функциональности XPath 2.0 и его соответствующей библиотеки функций. Когда Qt XML Patterns сталкивается с неподдерживаемой или частично поддерживаемой функцией, он либо сообщит об ошибке синтаксиса, либо тихо продолжит, если в таблице не указано иное.
В настоящее время реализация проходит 42% набора тестов XSLT W3C, который фокусируется на функциях, введенных в XSLT 2.0.
| Функция XSL | Статус поддержки |
|---|---|
xsl:key и fn:key()
|
не поддерживается |
xsl:include |
не поддерживается |
xsl:import |
не поддерживается |
xsl:copy |
Атрибуты copy-namespaces и inherit-namespaces не имеют эффекта. Для скопированных комментариев, атрибутов и инструкций обработки, копия имеет тот же идентификатор узла, что и оригинал. |
xsl:copy-of |
Атрибут copy-namespaces не имеет эффекта. |
fn:format-number() |
не поддерживается |
xsl:message |
не поддерживается |
xsl:use-when |
не поддерживается |
Tunnel Параметры |
не поддерживается |
xsl:attribute-set |
не поддерживается |
xsl:decimal-format |
не поддерживается |
xsl:fallback |
не поддерживается |
xsl:apply-imports |
не поддерживается |
xsl:character-map |
не поддерживается |
xsl:number |
не поддерживается |
xsl:namespace-alias |
не поддерживается |
xsl:output |
не поддерживается |
xsl:output-character |
не поддерживается |
xsl:preserve-space |
не поддерживается |
xsl:result-document |
не поддерживается |
| Шаблоны | Сложные шаблоны или шаблоны с предикатами имеют проблемы. |
2.0 Режим совместимости |
Стили обрабатываются как стили XSLT 2.0, даже если атрибут version в исходном XSLT равен 1.0. Другими словами, атрибут version игнорируется. |
| Группировка |
fn:current-group(), fn:grouping-key() и xsl:for-each-group. |
| Элементы regexp |
xsl:analyze-string, xsl:matching-substring, xsl:non-matching-substring, и fn:regex-group()
|
| Форматирование даты и времени |
fn:format-dateTime(), fn:format-date() и fn:format-time(). |
| Соответствие XPath | Поскольку XPath является подмножеством XSLT, его проблемы также действуют. |
Реализация XPath Data Model в Qt XML Patterns не включает сущностей (из-за того, что QXmlStreamReader их не сообщает). Это означает, что функции unparsed-entity-uri() и unparsed-entity-public-id() всегда возвращают отрицательный результат.
XPath 2.0
Поскольку XPath 2.0 является подмножеством XQuery 1.0, XPath 2.0 поддерживается. Области, где соответствие может вызывать сомнения, а следовательно, где поведение может быть изменено в будущих выпусках, включают:
- Поддержка регулярных выражений в настоящее время не соответствует стандарту, но следует синтаксису стандартных регулярных выражений Qt QRegExp.
- Операторы для
xs:time,xs:date, иxs:dateTimeнеполны. - Форматирование очень больших или очень малых значений
xs:double,xs:float, иxs:decimalможет быть некорректным.
xml:id
Обработка XML-файлов поддерживает xml:id. Это позволяет эффективно искать элементы, имеющие атрибут с именем xml:id, с помощью функции fn:id(). Подробнее см. xml:id Version 1.0.
XML Schema 1.0
Существует два способа использования Qt XML Patterns для проверки схем: вы можете использовать API C++ в своем приложении Qt, используя классы QXmlSchema и QXmlSchemaValidator, или вы можете использовать утилиту командной строки с именем xmlpatternsvalidator (расположенную в каталоге «bin» вашего сборки Qt).
Реализация Qt XML Patterns проверки XML Schema в значительной степени поддерживает спецификацию версии 1.0. Известные проблемы реализации и области, где соответствие может вызывать сомнения, включают:
- Большие значения
minOccursилиmaxOccursили глубоко вложенные требуют большого объема памяти, что может привести к зависанию системы. Такую схему следует переписать, используяunboundedвместо больших чисел. Это ограничение, надеемся, будет устранено в будущей версии. - Сравнение очень малых или очень больших значений с плавающей точкой может привести к неправильным результатам в некоторых случаях. Однако такие числа не должны быть существенными для повседневного использования.
- Поддержка регулярных выражений в настоящее время не соответствует стандарту, но следует синтаксису стандартных регулярных выражений Qt QRegExp.
- Проверки ограничений тождества не могут использовать значения по умолчанию или фиксированных определений атрибутов.
Загрузка ресурсов
При загрузке Qt XML Patterns XML-ресурса, например, с помощью функции fn:doc(), поддерживаются следующие схемы:
| Имя схемы | Описание |
|---|---|
file |
Локальные файлы. |
data |
Байты закодированы в самом URI. Например, data:application/xml,%3Ce%2F%3E представляет <e/>. |
ftp |
Ресурсы, полученные через FTP. |
http |
Ресурсы, полученные через HTTP. |
https |
Ресурсы, полученные через HTTPS. Это будет выполнено, если не возникнут ошибки SSL. |
qrc |
Файлы ресурсов Qt. Выражение его как пустой схемы, :/..., не поддерживается. |
XML
Поддерживаются XML 1.0 и пространства имен XML 1.0, в отличие от версий 1.1. Когда строка передается в запрос как QString, символы должны быть символами XML 1.0. В противном случае поведение неопределено. Это не проверяется.
URI сначала передаются в QAbstractUriResolver. См. QXmlQuery::setUriResolver() для возможных переписываний.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.13/xmlprocessing.html