Marklogic json:config 生成“_children”

Marklogic json:config generate "_children"

我不明白为什么 Marklogic json:config 生成“_children”。我怎样才能排除“_children”。我看到所有枚举的 children 都返回 parents,但是 JSON 输出中有很多额外的垃圾。

let $config := json:config("custom")
let $_ := map:put( $config, "full-element-names",xs:QName("Nav:keynavlist")

Json 输出:

"Navigators": {
  "keynavlist": {
  "_children": [
     {
      "keynav": {
          "_value": "Fuel Cells"
      }
    }, 
 {
    "keynav": {
        "_value": "Microorganisms"
}
}, 
{
  "keynav": {
 "_value": "Waste Treatment"
}

我猜你想要这样的东西:

{
    "Navigators": {
        "keynavlist": [{
            "keynav": "Fuel Cells"
        }, {
            "keynav": "Microorganisms"
        }, {
            "keynav": "Waste Treatment"
        }]
    }
}

但最接近 json 转换库的是:

{
    "Navigators": {
        "keynavlist": {
            "keynav": ["Fuel Cells", "Microorganisms", "Waste Treatment"]
        }
    }
}

使用:

xquery version "1.0-ml";

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

let $config := json:config("custom")
let $_ := map:put($config, "array-element-names", ("keynav"))
return json:transform-to-json(
  <Navigators>
    <keynavlist>
      <keynav>Fuel Cells</keynav>
      <keynav>Microorganisms</keynav>
      <keynav>Waste Treatment</keynav>
    </keynavlist>
  </Navigators>,
  $config
)

考虑使用递归函数构建 json,可能是这样的:

declare function local:xml-to-json($nodes) {
  for $node in $nodes
  return typeswitch ($node)
    case element() return
      if ($node/attribute() or ($node/element() and $node/text())) then
        object-node {
          local-name($node): object-node {
            "@": array-node{ local:xml-to-json($node/attribute()) },
            "_": array-node { local:xml-to-json($node/node()) }
          }
        }
      else
        object-node {
          local-name($node): array-node{ local:xml-to-json($node/node()) }
        }
    case attribute() return
      object-node {
        local-name($node): data($node)
      }
    default return $node
};

local:xml-to-json(
  <Navigators>
    <keynavlist>
      <keynav>Fuel Cells</keynav>
      <keynav>Microorganisms</keynav>
      <keynav>Waste Treatment</keynav>
    </keynavlist>
  </Navigators>
)

HTH!

回答你的第一个问题

"I don't understand why Marklogic json:config generates "_children"

'custom' 配置旨在尽可能合理地支持 双向 JSON <> XML 转换。需要您引用的 "extra junk"(例如 _children)以反转过程并生成原始 XML。 'basic' 策略用于从 JSON 到 XML 的简单单向转换,而完整策略用于反向转换(xml 到 JSON)—— 同时保留尽可能多的信息

由于您要从 XML 翻译成 JSON,其中任何 xml 元素都可能同时具有属性和子元素,并且子元素可能具有重名,因此它们不能转换为简单的 JSON 对象而不会丢失数据(在一般情况下)。

'custom' 策略具有很大的灵活性(又名 'complexity')来解决 'My Case' 很少 'The General Case' 或 "Your Case" 这一事实。

一个这样的配置选项是能够指定 xml qnames 应该转换为数组而不是“_children” "array-element-names"

查看本页的最后一个示例:https://docs.marklogic.com/json:config

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

declare variable $doc :=   <a><b attr="d">c</b></a>;

let $c := json:config("custom") ,
    $_ := map:put( $c, "array-element-names", (xs:QName("a"),xs:QName("b")) ),
    $_ := map:put( $c, "attribute-names", ("attr" ) ), 
    $_ := map:put( $c, "text-value", "LABEL" ),
    $j := json:transform-to-json($doc ,$c ),
    $x := json:transform-from-json($j,$c) 
return ($j, $x)

(: The JSON property name "LABEL" is used to hold the text value from
    the element <b/>. Without the "text-value" option, the property name
    would be "_value". The query produces the following output: 

{"a":[{"b":[{"attr":"d", "LABEL":"c"}]}]}
<a><b attr="d">c</b></a> :)

在某些时候——实现具体个案转换所需的 'configuration' 数量变得更复杂,作为策略配置来做,而作为本地 xquery 代码来做则不那么复杂,如 grtjn 所示,当如何'tweek' 为给定用例自定义配置变得过于乏味或不明显时,这是推荐的解决方案。

我发现 json:transform 和 post 预处理的组合最适合我。 YMMV