搜索中的命名空间声明:当为同一URI声明2+前缀时,搜索选项节点将被删除

时间:2015-11-05 23:31:52

标签: marklogic marklogic-8

MarkLogic版本:8.0-3.2

如果在搜索:搜索选项节点(如<element xmlns:bar="myuri:baz" xmlns:foo="myuri:baz">)中有一个具有不同前缀但具有相同URI的多个名称空间声明,则除了第一个前缀之外的每个前缀都会在搜索:搜索调用中丢失。

这是预期的行为吗?它在ML7.0-4.3下不存在,我不知道在不同前缀下的同一名称空间uri的多个声明违反了XML命名空间或xQuery规范。

非常感谢任何见解。

测试设置脚本:

(:~
 : Two transactions:
 : (1) Create an element range index on element {myuri:baz}child in "Documents" database
 : (2) Insert a test document at /baz/test/test-baz.xml
 :
 : Expected output: empty sequence
 :)

(: Transaction (1): Set up index :)
xquery version "1.0-ml";

import module namespace admin = "http://marklogic.com/xdmp/admin" at "/MarkLogic/admin.xqy";

let $config := admin:get-configuration(),
    $dbid := xdmp:database("Documents"),
    $rangespec := admin:database-range-element-index("string", "myuri:baz", "child", "http://marklogic.com/collation/", fn:false(), "reject")
return
    try {
        admin:save-configuration-without-restart(
            admin:database-add-range-element-index($config, $dbid, $rangespec)
        )
    } catch($e) {
        "Index already exists? Check logs.",
        xdmp:log($e, "debug")
    }

;

(: Transaction (2): Insert test document :)
xquery version "1.0-ml";

declare namespace baz = "myuri:baz";

let $uri := "/baz/test/test-baz.xml",
    $document :=
        <baz:root>
            <baz:child>TEST</baz:child>
        </baz:root>
return
    xdmp:document-insert($uri, $document)

测试脚本(为了清晰/可读性而详细):

xquery version "1.0-ml";

import module namespace search = "http://marklogic.com/appservices/search" at "/MarkLogic/appservices/search/search.xqy";

(: additional-query: xmlns:foo first, xmlns:bar second; cts:element: foo:child. Succeeds. :)
declare variable $search-options-1 :=
  <options xmlns="http://marklogic.com/appservices/search">
    <additional-query xmlns:foo="myuri:baz" xmlns:bar="myuri:baz">
      <cts:element-range-query operator="=">
        <cts:element>foo:child</cts:element>
        <cts:value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">TEST</cts:value>
      </cts:element-range-query>
    </additional-query>
  </options>;

(: additional-query: xmlns:foo first, xmlns:bar second; cts:element: bar:child. Fails. :)
declare variable $search-options-2 :=
  <options xmlns="http://marklogic.com/appservices/search">
    <additional-query xmlns:foo="myuri:baz" xmlns:bar="myuri:baz">
      <cts:element-range-query operator="=">
        <cts:element>bar:child</cts:element>
        <cts:value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">TEST</cts:value>
      </cts:element-range-query>
    </additional-query>
  </options>;

(: additional-query: xmlns:bar first, xmlns:foo second; cts:element: bar:child. Succeeds. :)
declare variable $search-options-3 :=
  <options xmlns="http://marklogic.com/appservices/search">
    <additional-query xmlns:bar="myuri:baz" xmlns:foo="myuri:baz">
      <cts:element-range-query operator="=">
        <cts:element>bar:child</cts:element>
        <cts:value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">TEST</cts:value>
      </cts:element-range-query>
    </additional-query>
  </options>;

(: additional-query: xmlns:bar first, xmlns:foo second; cts:element: foo:child. Fails. :)
declare variable $search-options-4 :=
  <options xmlns="http://marklogic.com/appservices/search">
    <additional-query xmlns:bar="myuri:baz" xmlns:foo="myuri:baz">
      <cts:element-range-query operator="=">
        <cts:element>foo:child</cts:element>
        <cts:value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">TEST</cts:value>
      </cts:element-range-query>
    </additional-query>
  </options>;

for $search-options in ($search-options-1, $search-options-2, $search-options-3, $search-options-4)
return
    try {
        let $test := search:search("", $search-options, 1) instance of element(search:response)
        return
            if ($test) then "PASS"
            else "FAIL" (: won't reach :)
    } catch($e) {
        $e/error:format-string/fn:string(.)
    }

测试输出(注意错误子字符串“没有字符串元素范围索引 for child ”---没有命名空间)

PASS

XDMP-ELEMRIDXNOTFOUND:cts:search(fn:collection(),cts:and-query(cts:element-range-query(xs:QName(“bar:child”),“=”,“TEST”, (“collat​​ion = http://marklogic.com/collation/”),1),()),(“score-logtfidf”,cts:score-order(“descending”)),xs:double(“1”),()) - 子http://marklogic.com/collation/

没有字符串元素范围索引

PASS

XDMP-ELEMRIDXNOTFOUND:cts:search(fn:collection(),cts:and-query(cts:element-range-query(xs:QName(“foo:child”),“=”,“TEST”, (“collat​​ion = http://marklogic.com/collation/”),1),()),(“score-logtfidf”,cts:score-order(“descending”)),xs:double(“1”),()) - 子http://marklogic.com/collation/

没有字符串元素范围索引

更新:元素级命名空间声明(带有直接构造函数或通过fn:QName()序列化)在祖先在不同前缀下多次声明相同的命名空间URI时,也会在ML8(不是ML7)下中断

当任何祖先多次在不同的前缀下声明相同的URI时,前缀在self :: *中丢失:

xquery version "1.0-ml";

import module namespace search = "http://marklogic.com/appservices/search" at "/MarkLogic/appservices/search/search.xqy";

(: Serialize namespace w/ fn:QName(), no namespace inheritance: PASS :)
declare variable $search-options-1 :=
  <options xmlns="http://marklogic.com/appservices/search">
    <additional-query>
      <cts:element-range-query operator="=">
        <cts:element>{fn:QName("myuri:baz", "child")}</cts:element>
        <cts:value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">TEST</cts:value>
      </cts:element-range-query>
    </additional-query>
  </options>;

(: Serialize namespace w/ fn:QName(), namespace inheritance, declared once: PASS :)
declare variable $search-options-2 :=
  <options xmlns="http://marklogic.com/appservices/search">
    <additional-query xmlns:foo="myuri:baz">
      <cts:element-range-query operator="=">
        <cts:element>{fn:QName("myuri:baz", "child")}</cts:element>
        <cts:value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">TEST</cts:value>
      </cts:element-range-query>
    </additional-query>
  </options>;

(: Serialize namespace w/ fn:QName(), namespace inheritance, declared twice: FAIL :)
declare variable $search-options-3 :=
  <options xmlns="http://marklogic.com/appservices/search">
    <additional-query xmlns:foo="myuri:baz" xmlns:bar="myuri:baz">
      <cts:element-range-query operator="=">
        <cts:element>{fn:QName("myuri:baz", "child")}</cts:element>
        <cts:value xsi:type="xs:string" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">TEST</cts:value>
      </cts:element-range-query>
    </additional-query>
  </options>;

for $search-options in ($search-options-1, $search-options-2, $search-options-3)
return
    try {
        let $test := search:search("", $search-options, 1) instance of element(search:response)
        return
            if ($test) then "PASS"
            else "FAIL" (: won't reach :)
    } catch($e) {
        $e/error:format-string/fn:string(.)
    }

输出ML7.0-4.3:

PASS

PASS

PASS

输出ML8.0-3.2:

PASS

PASS

XDMP-ELEMRIDXNOTFOUND:cts:search(fn:collection(),cts:and-query(cts:element-range-query(xs:QName(“bar:child”),“=”,“TEST”, (“collat​​ion = http://marklogic.com/collation/”),1),()),(“score-logtfidf”,cts:score-order(“descending”)),xs:double(“1”),()) - 子http://marklogic.com/collation/

没有字符串元素范围索引

2 个答案:

答案 0 :(得分:3)

如果您在XQuery上下文中直接使用Search API,则可以使用fn:QName()来获取元素QName的一致序列化:

<cts:element>{ fn:QName("myuri:baz", "child") }</cts:element>

评估为:

<cts:element xmlns:_1="myuri:baz">_1:child</cts:element>

或者,xs:QName()将使用可用的范围内前缀:

declare namespace foo ="myuri:baz";
<cts:element>{ xs:QName("foo:child") }</cts:element>

评估为:

<cts:element xmlns:foo="myuri:baz">foo:child</cts:element>

当然,如果您将REST API与存储的搜索选项一起使用,这种方法将无济于事。

答案 1 :(得分:0)

我相信Search API一直有此限制。我同意这个意外是不幸的 - 标准并不支持这个限制 - 但是你是否很难通过为每个命名空间uri使用一个且只有一个前缀来解决限制?如果不出意外,这会使声明变得更简单。