具有默认名称空间的序列化结构化查询

时间:2019-07-23 16:48:55

标签: marklogic

在我的应用程序中,我以字符串形式接收序列化的结构化查询。我需要将此字符串转换为查询并执行查询。

我使用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)

默认名称空间也用作“元素”的名称空间。我猜这是预期的行为。

  • 有没有办法防止这种情况?我想使用默认的cts命名空间,同时拥有一个没有命名空间的元素。

3 个答案:

答案 0 :(得分:1)

并非不修改输入查询XML。但是,假设您始终不希望使用名称空间,则可以使用ns属性进行指定:

cts:query(
<cts:element-value-query xmlns:cts="http://marklogic.com/cts">
  <cts:element ns="">myelement</cts:element>
  <cts:text xml:lang="en">some text</cts:text>
</cts:element-value-query>)

返回:

cts:element-value-query(fn:QName("","myelement"), "some text", ("lang=en"), 1)

答案 1 :(得分:1)

xdmp:with-namespaces()函数支持默认名称空间,因此将对xdmp:with-namespaces()的调用包装在对cts:query()解串器可能的调用周围:

http://docs.marklogic.com/xdmp:with-namespaces

那就是说,通过更改产生默认名称空间的方式来解决问题可能是一个更好的解决方案-有些人认为默认名称空间是一种反实践,因为存在混淆的可能。

希望有用

答案 2 :(得分:1)

在这种情况下,您确实需要一个前缀来区分cts:query元素本身与要寻址的index元素。但是没有什么可以阻止您自己更改前缀的。您可以按照以下步骤进行操作:

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"
  )
)

HTH!