Я использую BaseX (v9.3.2) XQuery v3.1. У меня есть сценарий XQuery, который оценивает все файлы XML в коллекции BaseX. В коллекции около 100 файлов, каждый размером от 30 МБ до 1,5 ГБ с одинаковой схемой XSD. Сценарий для повышения производительности использует Map Module BaseX для сопоставления ключей со значениями и быстрого получения значений с помощью ключ. Я объявил несколько глобальных переменных модуля типа map(*)
. Суть в том, что значения ключей уникальны только в одном файле XML. Чтобы сделать ключ уникальным для всей коллекции, я просто добавил base-uri($value),'_'
в качестве дополнительной части ключа :). Это работает нормально. Основным недостатком, который я вижу, является необходимость туннелирования base-uri
через все последовательные вызовы функций FooN($baseuri, $arg2) FooN-1($baseuri, $arg2) ... Foo1($baseuri, $arg2)
, даже если значение $baseuri
установлено с первым вызовом FooN($baseuri, $arg2)
, но используется только в последней функции цепочки выполнения. Чтобы сделать это более понятным, см. код XQuery ниже. Здесь $basuri
, наконец, нужен только в helper:Foo1
, но нам нужно передать его в качестве аргумента и в helper:Foo2
.
Мой вопрос в том, есть ли лучший подход к туннелированию аргументов и без других недостатков (производительность, память).
Код XQuery
xquery version "3.1" encoding "utf-8";
declare namespace helper="helperns";
declare variable $helper:root := db:open("BMW");
declare variable $helper:mapAS_ApplicationRecordElementByTypeRef as map(*) := map:merge(for $value in $helper:root//*:APPLICATION-RECORD-ELEMENT[*:TYPE-TREF/@DEST='APPLICATION-PRIMITIVE-DATA-TYPE'] return map:entry(concat(base-uri($value),'_',$value/*:TYPE-TREF/tokenize(text(),'/')[last()]), $value));
declare variable $helper:mapAS_ImplementationDataTypeRefByApplicationDatatypeRef as map(*) := ...
...
declare function helper:Foo1($applPrimitiveDataType as element(),$basuri as xs:string)
as element() {
let $applRecordElement := map:get($helper:mapAS_ApplicationRecordElementByTypeRef, concat($basuri,'_',$applPrimitiveDataType/*:SHORT-NAME/text()))
...
let $resolved := if($implDataTypeElement) then (
...
)
else (
<RESOLVED_DATATYPE>
<SHORT-NAME resolveinfo='not resolved (DB ERROR)'>unknown</SHORT-NAME>
</RESOLVED_DATATYPE>
)
return ($resolved)
};
...
declare function helper:Foo2($basuri as xs:string)
as element()* {
let $applicationPrimitiveDataTypes := ...
let $res :=
for $applicationPrimitiveDataType in $applicationPrimitiveDataTypes
...
order by $shortname
return (
if (not($implDataTypeRef)) then (
let $dataTypeResolved := helper:Foo1($applicationPrimitiveDataType,$basuri)
return(
<MAPPING appldtname="{$shortname}" size="{$dataTypeResolved/*:SHORT-NAME/@size}" basedatatype="{$dataTypeResolved/*:SHORT-NAME}" resolveinfo="{$dataTypeResolved/SHORT-NAME/@resolveinfo}"/>
)
)
)
return($res)
};
let $mappingsForAllDocs :=
for $doc in helper:getAllDocs()/doc
...
let $missingmappings := helper:Foo2($doc/@baseuri)
return (
<FILE name="{$doc/@filename}" missing="{count($missingmappings)}">
<MISSING-MAPPING>{$missingmappings}</MISSING-MAPPING>
...
</FILE>
)
let $allDocs :=
for $doc in helper:getAllDocs()/doc
order by $doc/@filename
return (
<FILE name="{$doc/@filename}"/>
)
return($mappingsForAllDocs)
/path//to/the/@ID
уникальными:for $id in /path//to/the/@ID return replace value of node $id with concat(base-uri($id),'_',$id)
. Отмена тоже работает нормально:for $id in /path//to/the/@ID return replace value of node $id with replace($id,concat(base-uri($id),"_"),'')
. 18.05.2020