我正在尝试使用以下代码保存一个 .ebc 文件:
xquery version "1.0-ml";
let $file := doc("Text.ebc")
return
xdmp:save("TestOutput.txt", $file,
<options xmlns="xdmp:save">
<output-encoding>ascii</output-encoding>
</options>)
我希望在保存时将原始文件的 EBCDIC 内容转换为 ASCII。我在输出文件中得到奇怪的输出,而不是任何 ASCII 内容。
存储在 MarkLogic 中的任何文本或 xml 文档都以 UTF-8 编码存储。因此,您的文档现在可能不是EBCDIC,除非您以二进制格式存储它。您可以使用xdmp:describe(doc($uri)/node())
进行检查:如果它显示二进制节点,则可能是EBCDIC。如果它显示文本或 XML,则为 UTF-8。现在,假设您有一个包含EBCDIC代码点的二进制节点。
xdmp:save
函数的第三个参数采用 XML 选项元素,但任何output-encoding
元素都只对文本或 XML 有意义。二进制是二进制的:它没有已知的编码,所以xdmp:save
不知道如何将其转换为另一种编码。
让我们创建一个非常简单的二进制文档,其中包含单个EBCDIC代码点0xC1
。这相当于 ASCII 代码点 0x41
:"A"。
xdmp:document-insert(
'test.ebc',
binary { xs:hexBinary('C1') })
让我们确认新文档中有一个二进制节点:
xdmp:describe(doc('test.ebc')/node())
=> fn:doc("test.ebc")/binary()
现在让我们尝试保存它:
xdmp:save(
'/tmp/test-binary.txt',
doc('test.ebc'),
<options xmlns="xdmp:save">
<output-encoding>ascii</output-encoding>
</options>)
内容:
$ od -x /tmp/test-binary.txt
0000000 001a
0000001
如果我们省略output-encoding
选项,它仍然是 C1
.所有这些都只是证实了我们不能依赖二进制内容的output-encoding
选项。
那么我们如何在MarkLogic中将EBCDIC转换为ASCII?最好的方法是在我们第一次插入文档时正确编码,无论它来自哪里。xdmp:document-get
等函数支持输入编码选项,支持 HTTP 的函数可以使用 Content-Type
标头。
但是如果你有一大块未解码的二进制文件,你仍然可以用 https://docs.marklogic.com/xdmp:binary-decode 来处理它
xdmp:binary-decode(
doc('test.ebc'),
'ebcdic-xml-us')
EBCDIC 似乎有大约 100 种变体,所以我只选了一个。正如预期的那样,输出是一个xs:string
"A"
。现在,您可以将该字符串包装在某个 XML 或文本节点中,并使用 xdmp:document-insert
或 xdmp:save
将其持久化。
xdmp:save(
'/tmp/test-binary.txt',
text {
xdmp:binary-decode(doc('test.ebc'), 'ebcdic-xml-us') },
<options xmlns="xdmp:save">
<output-encoding>ascii</output-encoding>
</options>)
正如预期的那样,输出文件包含 ASCII 格式的字母A
。我也可以省略output-encoding
选项xdmp:save
,然后它是 UTF-8。在这种情况下,这没有任何区别,但对于真实的文档,它可能会。