如何用xdmp:save导出MarkLogic数据到CSV?CSV无法换行追加排查
Hey there! I see you're trying to generate a CSV file in MarkLogic using XQuery but hitting a wall with appending rows instead of overwriting the file each time. Let's work through this together.
First, here's your code snippet formatted properly for clarity:
xquery version "1.0-ml"; let $filename := "D:\csv-reports\test.csv" let $directory-query := cts:directory-query("/searcdoc/") let $uris := cts:uris((), (), $directory-query) for $uri in $uris let $additional := doc($uri)/searcdoc/access/additional/text() let $des := doc($uri)/searcdoc/std/text() let $option := <options xmlns="xdmp:save"> <!-- Your existing options here --> </options> <!-- I assume you're calling xdmp:save here but missing append config -->
The Core Problem
By default, xdmp:save overwrites the target file entirely every time it runs. That means in your loop, each iteration is replacing the CSV with just the current row, instead of adding it to the end. You're missing the critical append configuration in your xdmp:save options.
The Fix: Enable Append Mode
To make xdmp:save append content instead of overwriting, you need to add the <append>true</append> element to your save options. Also, you'll want to handle the CSV header only once (when the file is first created) to avoid repeating it on every append.
Here's an updated, working version of your code:
xquery version "1.0-ml"; let $filename := "D:\csv-reports\test.csv" let $directory-query := cts:directory-query("/searcdoc/") let $uris := cts:uris((), (), $directory-query) // Check if the CSV file already exists to handle header logic let $file-exists := xdmp:file-exists($filename) // Define your CSV header (write this only once) let $csv-header := "additional,description" || xdmp:newline() // Configure save options to enable append mode let $save-options := <options xmlns="xdmp:save"> <append>true</append> </options> // Write header if the file is new let $_ := if (not($file-exists)) then xdmp:save($filename, $csv-header, $save-options) else () // Loop through URIs and append each row to the CSV for $uri in $uris let $additional := doc($uri)/searcdoc/access/additional/text() let $des := doc($uri)/searcdoc/std/text() // Escape special characters (like commas/quotes) for valid CSV let $escaped-additional := '"' || fn:replace($additional, '"', '""') || '"' let $escaped-des := '"' || fn:replace($des, '"', '""') || '"' let $csv-row := $escaped-additional || "," || $escaped-des || xdmp:newline() return xdmp:save($filename, $csv-row, $save-options)
Key Details to Note:
<append>true</append>: This is the missing piece—it tells MarkLogic to add content to the end of the file instead of replacing it.- Header Handling: Using
xdmp:file-existsensures we only write the header once when the file is first created, so you don't get duplicate headers in your CSV. - CSV Escaping: I added logic to wrap values in quotes and escape internal quotes (replacing
"with"")—this is crucial for valid CSV if your data contains commas or quotes.
This should resolve your issue—now each row will be appended to the CSV instead of overwriting the entire file!
内容的提问来源于stack exchange,提问作者subsoft

