【问题标题】:Encode String in XQuery在 XQuery 中编码字符串
【发布时间】:2017-10-26 08:56:52
【问题描述】:

在我的基于 eXist-db 的 Web 应用程序中编写了一个函数,以使用 XQuery 将一些 xml 元素导出到 csv。一切正常,但我的元素中有一些变音符号,如 ü、ä 或 ß,它们在我的 csv 中以错误的方式显示。我尝试使用 fn:normalize-unicode 对内容进行编码,但这不起作用。 这是我的代码 sn-p 的最小化示例:

let $input =
    <root>
        <number>1234</number>
        <name>Aufmaß</name>
    </root>

let $csv := string-join(
    for $ta in $input
        return concat($ta/number/text(), fn:normalize-unicode($ta/name/text())))

let $csv-ueber-string := concat($csv-ueber, string-join($massnahmen, $nl))

let $set-content-type := response:set-header('Content-Type', 'text/csv')
let $set-accept := response:set-header('Accept', 'text/csv')
let $set-file-name := response:set-header('Content-Disposition', 'attachment; filename="export.csv"')

return response:stream($csv, '')

【问题讨论】:

  • 那么,您在哪里/如何运行 XQuery,如何保存或存储结果,如何查看结果,您希望 CSV 采用哪种编码方式?
  • 我在基于 eXist-db 的 Web 应用程序中使用 XQuery。我使用函数 response:stream() 存储结果(我已经编辑了我的第一篇文章)。下载 csv 后,我在 Excel 中打开它,发现编码并没有真正起作用。好吧,我是编码字符串的新手,但 utf-8 或 cp1250 应该可以完成这项工作。
  • 您可能需要为 eXist 添加标签,因为我确信解决方案的一部分是在 response:set-headerresponse:stream 等函数上使用正确的选项或设置。
  • 什么版本的 eXist? (Martin,我已按照您的建议添加了 eXist 标签。)
  • 您确定它们没有正确序列化,并且不是文本编辑器吗?像 Nodepad 这样的编辑器可能会假设它是 ASCII。可能需要确保 CSV 输出被读取为 UTF-8。尝试在其他编辑器中查看,例如 Nodepad++ ?

标签: csv xquery encode exist-db


【解决方案1】:

您的查询确实不太可能有任何问题,或者您可以在查询中做任何事情来纠正这个问题。

问题很可能是要么

(a) 传递给查询的输入数据与查询处理器认为的字符编码不同

(b) 查询的输出数据与输出接收者认为的字符编码不同。

快速浏览一下您的查询表明,除了查询源代码本身之外,它实际上没有任何外部输入。但是源代码是输入之一,这可能是错误的来源。消除这种可能性的一个好方法可能是看看如果你替换会发生什么

<name>Aufmaß</name>

通过

<name>Aufma{codepoints-to-string(223)}</name>

如果这样可以解决问题,那么您的查询源文本不在查询编译器认为的编码中。

另一种可能性是问题出在输出端,坦率地说,这似乎更有可能。您似乎正在生成一个 HTTP 响应流作为输出,并自己构建 HTTP 标头。我没有看到任何证据表明您在 HTTP 响应标头中设置了任何特定的编码。 response:stream() 函数是特定于供应商的,我不熟悉它的细节,但我怀疑你需要确保它以 UTF-8 编码内容,并且 HTTP 标头说它是 UTF-8;这可能是函数的额外参数,也可能是外部配置选项。

【讨论】:

    【解决方案2】:

    如您所料,eXist 将 CSV 序列化为 Unicode (UTF-8)。但是当您直接在 Excel 中打开生成的export.csv 文件时(即通过File &gt; Open),Excel 会尽力猜测 CSV 文件的编码。但是 CSV 文件缺乏任何声明其编码的方式,因此应用程序很可能会猜错,就像 Excel 在您的情况下所做的那样。在我的电脑上,Excel 也猜错了,将Aufmaß 的编码修改为Aufmaß。这是强制 Excel 使用 UTF-8 编码的 CSV 文件的编码的方法,例如您的查询生成的文件。

    • 在 Excel 中,通过File &gt; New 开始一个新的电子表格
    • 选择File &gt; Import 会弹出一系列对话框,让您指定如何导入 CSV 文件。
    • 在第一个对话框中,选择“CSV 文件”作为文件类型。
    • 在下一个对话框中,标题为“文本导入向导 - 第 1 步,共 3 步”,选择“Unicode (UTF-8)”作为“文件来源”。(至少这些是我的 MS Excel for Mac 2016 副本中的标题/顺序)。
    • 继续完成其余的对话框,保持默认值。
    • 然后 Excel 会将您的 export.csv 的内容放入新的电子表格中。

    最后,让我提供以下查询,我用于测试并确认 eXist 生成的 CSV 文件在遵循上述说明时确实按预期打开。该查询与您的查询基本相同,但修复了您的查询中的一些问题,这些问题使我无法直接运行它。我将此查询保存在/db/csv-test.xq 并通过http://localhost:8080/exist/rest/db/csv-test.xq 调用它,

    xquery version "3.1";
    
    let $input :=
        <root>
            <number>1234</number>
            <name>Aufmaß</name>
        </root>
    let $cell-separator := ","
    let $column-headings := $input/*/name()
    let $header-row := string-join($column-headings, $cell-separator)
    let $body-row := string-join($input/*/string(), $cell-separator)
    let $newline := '&#10;'
    let $csv := string-join(($header-row, $body-row), $newline)
    return
        response:stream-binary(
            util:string-to-binary($csv),
            "text/csv", 
            "export.csv"
        )
    

    【讨论】:

      猜你喜欢
      • 2010-09-10
      • 1970-01-01
      • 1970-01-01
      • 2013-12-29
      • 2014-02-26
      • 2016-07-15
      • 2013-11-01
      • 1970-01-01
      • 2015-08-25
      相关资源
      最近更新 更多