1

这是与MarkLogic 内容泵实用程序相关的第二个问题。

我正在将具有多条记录的单个聚合 XML 文档摄取到 MarkLogic 内容泵中。我希望将聚合 XML 文档转换为不同的格式,并且内容泵实用程序可以从单个输入的大型 xml 文档生成多个 xml 文档。?

示例:聚合输入 xml 文档:

<root>
 <data>Bob</data>
 <data>Vishal></data>
</root>

内容泵的预期输出:两个格式不同的文档:

文件 1:

<data1>Bob</data1>

文件 2

<data1>Vishal</data1>

我正在使用以下 XSLT 将上述文档拆分为两个节点:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
  <xsl:template match="root">
    <xsl:apply-templates select="data"></xsl:apply-templates>
  </xsl:template>
  <xsl:template match="data">
    <data1><xsl:value-of select="."/></data1>
  </xsl:template>
</xsl:stylesheet>

输出:

<?xml version="1.0" encoding="UTF-8"?>
<data1>Bob</data1>
<data1>Vishal</data1>

下面是 XQuery 转换,它调用上面的“XSLT 文件”来生成两个节点:

xquery version "1.0-ml";
module namespace example = "http://marklogic.com/example";

declare function example:transform(
  $content as map:map,
  $context as map:map
) as map:map*
{
  let $attr-value := 
    (map:get($context, "transform_param"), "UNDEFINED")[1]
  let $the-doc := map:get($content, "value")

  let $let-output:=  xdmp:xslt-invoke("/marklogic.rest.transform/simple-xsl/assets/transform.xsl", $the-doc )
  return (map:put(
          $content, "value",
          $let-output
        ),$content)

};

上述 XQuery 转换失败并返回错误。那么,如何修改上述 XQuery 程序,使其从单个文档生成多个转换后的 XML 文档并为其编制索引?

MLCP 命令:

mlcp.sh import -host localhost -port 8040 \
    -username admin -password admin \
    -input_file_path ./parent-form.xml \
    -transform_module /example/parent-transform.xqy \
    -transform_namespace "http://marklogic.com/example" \
    -transform_param "my-value" \
    -output_collections people \
    -output_permissions my-app-role,read,my-app-role,update 
4

2 回答 2

3

您提供的转换返回包含多个根元素的单个文档。转换将起作用,但 MarkLogic 不允许将其插入数据库,并抛出XDMP-MULTIROOT: Document nodes cannot have multiple roots.

有两种方法可以解决这个问题。最简单的就是在/*后面使用xdmp:xslt-invoke。另一种解决方案是<xsl:result-document href="{generate-id()}.xml">在 XSLT 内部使用。两者都将导致$let-output包含一个序列,而不仅仅是一个文档。

但是,如果没有进一步的更改会导致XDMP-CONFLICTINGUPDATES,因为这会在一个数据库 uri 中写入多个结果。为了解决这个问题,你可以用一个小技巧来克隆$content map:map,并提供单独的 uri。例如像这样:

for $let-output at $i in xdmp:xslt-invoke("/marklogic.rest.transform/simple-xsl/assets/transform.xsl", $the-doc )/*
let $extra-content := map:map(document{$content}/*)
let $_ := map:put($extra-content, "value", $let-output)
let $_ := map:put($extra-content, "uri", concat($the-uri, '-', $i, '.xml') )
return
  $extra-content

注意:transform 函数的返回类型为map:map*,这意味着您可以返回零个或多个 map:map 包含的结果。

于 2015-09-30T12:28:13.067 回答
1

您不能使用转换功能来实际拆分文档。相反,这被称为每个被摄取的文档

单个文档的创建是在摄取之前完成的,并由aggregate_flags控制。

https://docs.marklogic.com/guide/ingestion/content-pump#id_65814

于 2015-09-30T05:50:17.063 回答