表达式评估不起作用

expression evaluation does not work

我正在尝试从下面的函数构建 XML 到 return 的文档。如果我先使用 let 将其存储在另一个变量中,为什么评估替换会起作用?我不能就地评估表达式吗?正如您在最后的结果中看到的那样,生成的 XML 仅填充了我将其存储在 $x 变量中的变量值。

declare function local:oim-to-canonical($oimContent as node()) {
  let $x := $oimContent/account/domain/text()
  return
    <person xmlns="http://schemas.abbvienet.com/people-db/model">
      <account>
        <domain>{ $oimContent/account/domain/text()  }</domain>
        <username>{ $oimContent/account/username/text() }</username>
        <status>{ $oimContent/account/status/text() }</status>
        <x>{ $x }</x>
      </account>
    </person>
};

local:oim-to-canonical(
  <person>
    <account>
      <domain>MYDOMAIN</domain>
      <username>ttt</username>
      <status>ENABLED</status>
    </account>
  </person>
)

结果:

<person xmlns="http://schemas.abbvienet.com/people-db/model">
  <account>
    <domain/>
    <username/>
    <status/>
    <x>MYDOMAIN</x>
  </account>
</person>

这是正确的行为吗?

根据您所写答案后的评论,您是对的,在 XPath 中使用通配符命名空间是可行的:

<domain>{ $oimContent/*:account/*:domain/text()  }</domain>

但是,在可以避免的情况下,这被认为是一种不好的做法。为了执行该 XPath,MarkLogic 需要做比提供命名空间更多的工作。挑战在于您的输入 XML 使用的是空命名空间,并且无法指定它。我会修改输入以使用名称空间:

xquery version "1.0-ml";
declare namespace inp = "input";

declare function local:oim-to-canonical($oimContent as node()) {
  let $x := $oimContent/inp:account/inp:domain/text()
  return
    <person xmlns="http://schemas.abbvienet.com/people-db/model">
      <account>
        <domain>{ $oimContent/inp:account/inp:domain/text()  }</domain>
        <username>{ $oimContent/inp:account/inp:username/text() }</username>
        <status>{ $oimContent/inp:account/inp:status/text() }</status>
        <x>{ $x }</x>
      </account>
    </person>
};

local:oim-to-canonical(
  <person xmlns="input">
    <account>
      <domain>MYDOMAIN</domain>
      <username>ttt</username>
      <status>ENABLED</status>
    </account>
  </person>
)

这使您的 XPath 更加明确。小规模,差异可能无关紧要,但在规模上差异会增加。

我同意 Dave 的观点,使用命名空间输入可以让生活更轻松。为了完整起见,您还可以通过不使用带有默认命名空间的文字 XML 来防止出现此问题,而是使用元素构造函数来代替:

declare variable $ns := "http://schemas.abbvienet.com/people-db/model";

declare function local:oim-to-canonical($oimContent as node()) {
  let $x := $oimContent/account/domain/text()
  return
    element { fn:QName($ns, "person") } {
      element { fn:QName($ns, "account") } {
        element { fn:QName($ns, "domain") } { $oimContent/account/domain/text()  },
        element { fn:QName($ns, "username") } { $oimContent/account/username/text() },
        element { fn:QName($ns, "status") } { $oimContent/account/status/text() },
        element { fn:QName($ns, "x") } { $x }
      }
    }
};

local:oim-to-canonical(
  <person>
    <account>
      <domain>MYDOMAIN</domain>
      <username>ttt</username>
      <status>ENABLED</status>
    </account>
  </person>
)

虽然我通常更喜欢文字 XML,因为它更 dense/less 混乱..

HTH!