В моем приложении я получаю сериализованный структурированный запрос в виде строки. Мне нужно преобразовать эту строку в запрос и выполнить запрос.
Я использую cts:query
для построения запроса:
declare namespace search = "http://marklogic.com/appservices/search";
(: External string variable received by the application. :)
let $query := "" ||
"<search:search xmlns:search='http://marklogic.com/appservices/search'>" ||
" <element-value-query xmlns='http://marklogic.com/cts'>" ||
" <element>element</element>" ||
" <text>value</text>" ||
" </element-value-query>" ||
"</search:search>"
(: extract cts query from search. :)
let $q := document {
xdmp:unquote($query)/search:search/*
}
(: construct cts query. :)
return cts:query($q/*)
Это прекрасно работает, если запрос cts имеет префиксное пространство имен, подобное этому:
<cts:element-value-query xmlns:cts = "http://marklogic.com/cts">
<cts:element>element</cts:element>
<cts:text>value</cts:text>
</cts:element-value-query>
Но не в том случае, если используется пространство имен по умолчанию, как в моем первом примере кода.
Чтобы было понятнее, посмотрите этот пример:
xquery version "1.0-ml";
cts:query(
<element-value-query xmlns = "http://marklogic.com/cts">
<element>element</element>
<text>value</text>
</element-value-query>
),
cts:query(
<cts:element-value-query xmlns:cts = "http://marklogic.com/cts">
<cts:element>element</cts:element>
<cts:text>value</cts:text>
</cts:element-value-query>
)
Результат этого xquery:
cts:element-value-query(fn:QName("http://marklogic.com/cts","element"), "value", ("lang=en"), 1)
cts:element-value-query(fn:QName("","element"), "value", ("lang=en"), 1)
Пространство имен по умолчанию также используется в качестве пространства имен для «элемента». Я предполагаю, что это предполагаемое поведение.
Функция xdmp:with-namespaces() поддерживает пространство имен по умолчанию, поэтому обертывание вызова xdmp:with-namespaces() вокруг вызова десериализатора cts:query() мощь работает:
http://docs.marklogic.com/xdmp:with-namespaces
Тем не менее, решение проблемы путем изменения того, что создает пространство имен по умолчанию, может быть лучшим решением - некоторые люди считают пространство имен по умолчанию антипрактикой из-за возможности путаницы.
Надеясь, что это полезно,
В этом случае вам действительно нужен префикс, чтобы отличить сами элементы cts:query от элемента индекса, к которому вы обращаетесь. Однако ничто не мешает вам изменить префикс самостоятельно. Вы можете сделать это следующим образом:
xquery version "1.0-ml";
declare function local:qname($node, $ns, $prefix) {
if (fn:namespace-uri($node) eq $ns) then
if ($prefix eq '') then
QName($ns, local-name($node))
else
QName($ns, $prefix || ":" || local-name($node))
else
node-name($node)
};
declare function local:change-prefix(
$nodes as node()*,
$ns as xs:string,
$prefix as xs:string
)
as node()*
{
for $node in $nodes
return
typeswitch ($node)
case element() return
element { local:qname($node, $ns, $prefix) } {
$node/@*,
local:change-prefix($node/node(), $ns, $prefix)
}
case document-node() return
document {
local:change-prefix($node/node(), $ns, $prefix)
}
default return $node
};
cts:query(
local:change-prefix(
<element-value-query xmlns = "http://marklogic.com/cts">
<element>myelement</element>
<text xml:lang = "en">some text</text>
</element-value-query>,
"http://marklogic.com/cts",
"cts"
)
)
ХТХ!
+1 за то, что пространство имен по умолчанию рассматривается как антипрактика. Однако я не могу заставить это работать с
xdmp:with-namespace
.