具有多个命名空间的MarkLogic json:transform-from-json?

时间:2019-04-16 02:46:54

标签: json xquery marklogic

在MarkLogic中,是否可以使用json:transform-from-json将json转换为具有多个名称空间的XML?例如,如何转换

def sum_column(key, data):
    return sum( data[key].values() )

进入

{
  options: {
    format: "xml"
  }
}

2 个答案:

答案 0 :(得分:1)

是的,它没有记录或简单,但不是秘密。 在Modules / MarkLogic / json / custom.xqy

中查看源代码

然后记录了更多自定义参数。 “有趣的”方法允许您覆盖用于转换的单个方法。 示例:使用自定义策略时,您可以设置替代。 以下是默认值,您可以更改它们。

map:put($c , $json-custom:element-qname-from-json-name  , json-custom:element-qname-from-json-name#2 ),
map:put($c , $json-custom:attribute-qname-from-json-name  , json-custom:attribute-qname-from-json-name#2 ),

将函数'json-custom:element-qname-from-json-name'替换为您自己的函数-给定配置对象和当前json字段名称,您可以使用所需的任何逻辑,返回完整的QName。

您可以从上面的文件中提取“内置”功能(未隐藏)。从9.0版本开始,它看起来像:

declare %private function json-custom:element-qname-from-json-name( $config as map:map , $json_name as xs:string? ) as xs:QName
{

   json-custom:qname( map:get( $config , $json-custom:element-namespace ) ,
                      map:get( $config , $json-custom:element-namespace-prefix ) ,
                      if(map:get($config , $json-custom:camel-case)) then  json-custom:from-camelCase($json_name) else $

 };

这可能会变得非常棘手。我建议结合使用自定义转换和xml后处理(使用xquery或xslt)。

棘手的部分是,从JSON到XML时,您不会得到太多的“上下文”。 JSON没有节点祖先或排序。您得到的只是一个字段名称。如果您可以从中映射到所需的QName,那么它很容易。例如,您可以创建JSON名称到QNames的映射,并将其与自定义函数一起放入配置。

通常,要求比较困难,因此建议您仅尝试通过配置“使其接近”,然后进行后续处理。

答案 1 :(得分:1)

示例JSON中没有任何内容指示应将这些名称空间应用于XML元素。

如果使用json:transform-from-json(),则生成的XML将位于http://marklogic.com/xdmp/json/basic命名空间中。

<json type="object" xmlns="http://marklogic.com/xdmp/json/basic">
  <options type="object">
    <format type="string">xml</format>
  </options>
</json>

然后,您需要转换XML,以便将这些元素放在所需的名称空间中。一种方法是使用递归类型切换功能:

xquery version "1.0-ml";
declare namespace j = "http://marklogic.com/xdmp/json/basic";
import module namespace json="http://marklogic.com/xdmp/json"
 at "/MarkLogic/json/json.xqy";

declare function local:convert($node as node()) as item()* {
  typeswitch($node)
    case attribute() return ()
    case element(j:json) return local:convert($node/node())
    case element(j:options) return element {fn:QName("xdmp:http-get", $node/local-name())} {local:convert($node/node())}
    case element() return element {fn:QName("xdmp:document-get", $node/local-name())} {local:convert($node/node())}
    default return $node
};

let $json := '{
  options: {
    format: "xml"
  }
}'

return local:convert(json:transform-from-json( $json ))

但是,如果您试图构造XML以构建xdmp:document-get()的选项,则可能更容易使用map:map而不是XML形式来指定选项。

  

用于自定义此操作的选项。您可以将选项指定为“ xdmp:document-get”命名空间中的XML元素,也可以指定为map:map。下面的选项名称是XML元素的本地名称。使用地图时,请将连字符替换为骆驼套。例如,当用作map:map键时,“ an-option”变为“ anOption”。

如果具有JSON对象,则可以选择options属性,然后使用fn:data()xdmp:from-json()来将options对象节点作为地图原子化:< / p>

fn:data($json//options)