将具有相同名称的XML元素转换为同名的JSON属性

时间:2017-12-01 22:43:57

标签: json xquery marklogic marklogic-8

同名的XML元素和JSON属性可能是兄弟姐妹。即:

<container>
  <value>value1</value>
  <value>value2</value>
</container>

object-node {
  "value" : "value1",
  "value" : "value2"
}

都有效,但我没有找到将一个转换为另一个的有效方法。在object-node构造函数中动态构建属性是无效的,即:

object-node {
  for $v in $values
  return 'value' : $v
}

使用地图不起作用,因为重复的键名称已折叠:

xdmp:to-json(map:new((
  map:entry("value", "value1"), 
  map:entry("value", "value2")))
  )

=> {"value":"value2"}

使用json:object时,最后一个键值是重复的:

json:object(<json:object>
  <json:entry key="value">
    <json:value>value1</json:value>
  </json:entry>
  <json:entry key="value">
    <json:value>value2</json:value>
  </json:entry>
</json:object>)

=> {"value":"value2", "value":"value2"}

使用+运算符连接地图更好,但它将重复的键合并为一个带有值数组({"value":["value1", "value2"]})的键,这仍然不是我想要的。有没有办法在XQuery中动态构建同名的兄弟JSON属性?

2 个答案:

答案 0 :(得分:3)

您的JSON示例:

object-node {
  "value" : "value1",
  "value" : "value2"
}

不是真的有效:或者无论如何,最好避免。 RFC 7159说:

  

当对象中的名称不唯一时,行为   接收这样一个对象的软件是不可预测的。许多   实现仅报告姓氏/值对。其他   实现报告错误或无法解析对象,和   一些实现报告所有名称/值对,包括   重复。

答案 1 :(得分:2)

我不相信可以在object-node()构造函数中嵌入FLWOR。

您可以构建一个字符串,并使用xdmp:eval()xdmp:value()进行评估:

let $container := 
    <container>
      <value>value1</value>
      <value>value2</value>
    </container>

return
  xdmp:value(
   "object-node {" || 
     fn:string-join($container/value ! ('"' || local-name() || '": "' || . || '"'), ",") || 
   " }"
  )

或者构建JSON字符串并使用xdmp:unquote()

let $container := 
    <container>
      <value>value1</value>
      <value>value2</value>
    </container>

return
  xdmp:unquote(
   "{" || 
     fn:string-join($container/value ! ('"' || local-name() ||'": "' || . || '"'), ",") || 
   "}"
  )