导出到CSV文件时如何格式化MarkLogic结果

导出到CSV文件时如何格式化MarkLogic结果,csv,formatting,xquery,extract,marklogic,Csv,Formatting,Xquery,Extract,Marklogic,我有一个XML,它的结构类似于下面的示例,我在MarkLogic中编写了一个XQuery来将其导出到CSV(见下面的XML) 我需要的帮助是格式化输出,这样当我打开CSV文件时,我不希望所有输出都跨越1,而是希望它被分组为“列” 假设对于下面的示例,我希望输出所有的DataTime和Source元素值,并将这些值放在它们自己的列中,如下所示: 2012-02-15T00:58:26 a 2012-02-15T00:58:26 b 2012-02-15T00:58:26 c 我该怎么做呢 欢迎任

我有一个XML,它的结构类似于下面的示例,我在MarkLogic中编写了一个XQuery来将其导出到CSV(见下面的XML)

我需要的帮助是格式化输出,这样当我打开CSV文件时,我不希望所有输出都跨越1,而是希望它被分组为“列”

假设对于下面的示例,我希望输出所有的DataTime和Source元素值,并将这些值放在它们自己的列中,如下所示:

2012-02-15T00:58:26 a
2012-02-15T00:58:26 b
2012-02-15T00:58:26 c
我该怎么做呢

欢迎任何参考点或帮助。先谢谢你

以下是示例XML:

<Document xmlns="http://fakeexample.org/schemas">
    <Information>
        <ItemId>1f28cb0c2c4f4eb7b13c4abf998e391e</ItemId>
        <MediaType>Text</MediaType>
        <DocDateTime>2012-02-15T00:58:26</DocDateTime>
    </Information>
    <FilingData>
        <DateTime>2012-02-15T00:58:26</DateTime>
        <Source>a</Source>
        </FilingData>
    <FilingData>
        <DateTime>2012-02-15T00:58:27</DateTime>
        <Source>b</Source>
    </FilingData>
    <FilingData>
        <DateTime>2012-02-15T00:58:28</DateTime>
        <Source>c</Source>
    </FilingData>
</Document>

1f28cb0c2c4f4eb7b13c4abf998e391e
正文
2012-02-15T00:58:26
2012-02-15T00:58:26
A.
2012-02-15T00:58:27
B
2012-02-15T00:58:28
C
下面是示例XQuery:

xquery version "1.0-ml";

declare default function namespace "http://www.w3.org/2005/xpath-functions";
declare namespace xdmp="http://marklogic.com/xdmp";
declare namespace exam="http://fakeexample.org/schemas";

declare function local:getDocument($url)
{

let $response := xdmp:document-get($url, 
       <options xmlns="xdmp:document-get">
           <repair>full</repair>
           <format>xml</format>
       </options>)

return $response
};

xdmp:set-response-content-type("text/csv"),
xdmp:add-response-header(
      "Content-disposition",
      fn:concat("attachment;filename=", "output", fn:current-time(), ".csv")
    ),
(
let $q := cts:element-value-query(xs:QName("exam:ItemId"), ("1f28cb0c2c4f4eb7b13c4abf998e391e"))

let $results := cts:search(fn:doc(), $q)

for $result in $results
return  fn:string-join((xs:string($result//exam:DateTime),
                        xs:string($result//exam:Source)                     
                        ), "," )
)
xquery版本“1.0-ml”;
声明默认函数名称空间“http://www.w3.org/2005/xpath-functions";
声明命名空间xdmp=”http://marklogic.com/xdmp";
声明命名空间检查=”http://fakeexample.org/schemas";
声明函数local:getDocument($url)
{
让$response:=xdmp:document获取($url,
满的
xml
)
返回$response
};
xdmp:设置响应内容类型(“文本/csv”),
xdmp:添加响应头(
“内容处置”,
fn:concat(“附件;文件名=”,“输出”,fn:current-time(),“.csv”)
),
(
let$q:=cts:element值查询(xs:QName(“检查:ItemId”),(“1f28cb0c2c4f4eb7b13c4abf998e391e”))
让$results:=cts:search(fn:doc(),$q)
对于$result,结果为$results
返回fn:string连接((xs:string($result//exam:DateTime),
xs:string($result//exam:Source)
), "," )
)

用以下内容替换for循环:

return

string-join(
    for $result in $results//FilingData
    return  fn:string-join((xs:string($result//exam:DateTime),
                    xs:string($result//exam:Source)                     
                    ), "," )
, "&#10;")
这应该能起作用

编辑:注意我在
$results
后面添加了
//FilingData
。这确保每个FilingData的DateTime和源分别联接,并作为for循环的单独字符串返回。这允许外部字符串联接在它们之间添加所需的行尾


注:
和#10应自动转换为操作系统特定的行尾。

基于@grtjn的答案:

string-join(..., "&#10;")
根据操作系统或应用程序的不同,可以对行尾进行不同的处理。您可以尝试其他字符(一个或两个):


此外,用于查看CSV的应用程序可能会阻碍这一点。例如,大多数版本的Microsoft Excel都会将单元格中的所有空白(包括换行符)转换为纯空格。

您不需要担心从内容中转义字符串、换行符和引号吗?(Fwiw,我希望看到转义的库被化,以便可以重用:)@eric bloch,使用给定的XML,no.;-)感谢您的回复,不幸的是,它仍然在1行中写出了结果,如:date1、date2、date3、source1、source2、source3。现在看看如何使用地图。如果我让它工作,它将发布一个更新。@zrdunlap啊,那个cts:search将返回整个文档,而您希望每个文件数据都在一个单独的行上。你需要选择那些。您可以随意处理cts:search,但在for循环中为它们添加路径可能更容易。我将编辑我的解决方案。就这样!非常感谢。我知道我错过了一些东西。谢谢,我也尝试了这两个,但仍然得到:2012-02-15T00:58:262012-02-15T00:58:262012-02-15T00:58:272012-02-15T00:58:28,a,b,c我肯定我做错了什么,但还没有弄清楚是什么。
"&#x0A;" (LF) 
"&#x0D;" (CR)