【问题标题】:Marklogic how to create a document from a mapMarklogic 如何从地图创建文档
【发布时间】:2014-04-17 15:01:43
【问题描述】:

我需要从地图创建一个特定格式的文档

我有以下代码:

declare function local:buid-map-doc(
  $wijk as xs:string,
  $wm as map:map) as element()
{  
  let $a := for $k in map:keys($wm)
              let $v := map:get($wm,$k)
              return element x {$v}
  return <y>{$a}</y>
};

let $wijk := "101101"
let $wm := map:map()
let $p := map:put($wm, "cat1:::k1",45683)
let $p := map:put($wm, "cat1:::k2",123)
let $p := map:put($wm, "cat2:::k2",123)

return  local:buid-map-doc($wijk,$wm)

给予:

<y>
  <x>123</x>
  <x>123</x>
  <x>45683</x>
</y>

但我想要 map:keys i 元素名称... 如果我这样做:

declare function local:buid-map-doc(
  $wijk as xs:string,
  $wm as map:map) as element()
{  
  let $a := for $k in map:keys($wm)
              let $v := map:get($wm,$k)
              return element {$k} {$v}
  return <y>{$a}</y>
};

let $wijk := "101101"
let $wm := map:map()
let $p := map:put($wm, "cat1:::k1",45683)
let $p := map:put($wm, "cat1:::k2",123)
let $p := map:put($wm, "cat2:::k2",123)

return  local:buid-map-doc($wijk,$wm)

然后我得到如下错误:

[1.0-ml] XDMP-QNAMELEXFORM: let $s := fn:QName("http://www.example.com/example", "k") -- QName 的词法形式无效

添加:

理想情况下,我希望得到这样的输出,可能还有更深的嵌套:

<results>
    <cat1>
        <k1>45683</k1>
        <k2>123</k2>
    </cat1>
    <cat2>
        <k2>123</k2>
    </cat2>
</results>

【问题讨论】:

    标签: marklogic


    【解决方案1】:

    对于computed element constructors,元素名称的表达式需要在括号中:CompElemConstructor ::= "element" (QName | ("{" Expr "}")) "{" ContentExpr? "}"

    declare function local:buid-map-doc(
      $wijk as xs:string,
      $wm as map:map) as element()
    {  
      let $a := 
        for $k in map:keys($wm)
        let $v := map:get($wm, $k)
        return element { replace($k, ':::', '-')} { $v }
      return <y>{$a}</y>
    };
    

    【讨论】:

    • 不,经过测试但不起作用...仍然 [1.0-ml] XDMP-QNAMELEXFORM: let $v := map:get($wm, $k) -- 的词法形式无效QName ...有趣的部分是它抱怨元素之前的行但光标指向元素
    • @HugoKoopmans 正如 grtjn 在他的回答中指出的那样,冒号字符不是有效的 NCName,因为它保留用作命名空间前缀和本地名称之间的分隔符。有关规范规则,请参阅:w3.org/TR/REC-xml/#NT-Char。我更新了从元素 QNames 中删除冒号的答案。
    【解决方案2】:

    您的代码的问题是您的映射键不是有效的 QName。所以,实际的错误 id 是正确的,但它报告错误的代码确实很奇怪。我会确保它在 MarkLogic 上得到报告。

    解决方案很简单,不要在 map:keys 中使用冒号,或者只使用一个,并且让前面的部分与已知的命名空间前缀匹配。例如。这会起作用:

    declare function local:buid-map-doc(
      $wijk as xs:string,
      $wm as map:map) as element()
    {  
      let $a := for $k in map:keys($wm)
                let $v := map:get($wm,$k)
                return element {$k} {$v}
      return <y>{$a}</y>
    };
    
    let $wijk := "101101"
    let $wm := map:map()
    let $p := map:put($wm, "cat1_k1",45683)
    let $p := map:put($wm, "cat1_k2",123)
    let $p := map:put($wm, "cat2_k2",123)
    
    return  local:buid-map-doc($wijk,$wm)
    

    添加:

    如果三冒号实际上表示层次结构,最好先将扁平地图转换为嵌套地图。将嵌套映射转换为嵌套 XML 非常简单。这是构建嵌套地图的粗略实现:

    declare function local:nest-keys($nested-map, $keys, $value) {
      let $key := $keys[1]
      let $remainder := $keys[position() > 1]
      return
      if ($key) then
        let $_ :=
          if (not(map:contains($nested-map, $key))) then
            map:put($nested-map, $key, map:map())
          else()
        let $key-map :=
          map:get($nested-map, $key)
        return
          if ($remainder) then
            local:nest-keys($key-map, $remainder, $value)
          else
            map:put($nested-map, $key, $value)
      else
        ()
    };
    
    let $map := map:map(
    <map:map xmlns:map="http://marklogic.com/xdmp/map">
      <map:entry>
        <map:key>cat1:::var1:::seg1</map:key>
        <map:value>waarde1</map:value>
      </map:entry>
      <map:entry>
        <map:key>cat1:::var1:::seg2</map:key>
        <map:value>waarde2</map:value>
      </map:entry>
      <map:entry>
        <map:key>cat1:::var2:::seg1</map:key>
        <map:value>waarde3</map:value>
      </map:entry>
      <map:entry>
        <map:key>cat1:::var2:::seg2</map:key>
        <map:value>waarde4</map:value>
      </map:entry>
      <map:entry>
        <map:key>cat2:::var1:::seg1</map:key>
        <map:value>waarde5</map:value>
      </map:entry>
    </map:map>
    )
    let $nested-map := map:map()
    let $_ :=
      for $key in map:keys($map)
      let $keys := tokenize($key, ":::")
      return
        local:nest-keys($nested-map, $keys, map:get($map, $key))
    return $nested-map
    

    HTH!

    【讨论】:

    • 实际上在真正的问题中我们有 3 层键,最终的解决方案是使用嵌套映射来获得我们需要的结构...谢谢您的帮助
    猜你喜欢
    • 2017-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多