将带有中文字符的 XML 发布到 Microsoft Translator API 会引发反序列化异常
POSTing XML with Chinese characters to the Microsoft Translator API raises deserializing exception
我正在尝试使用 Microsoft Translator API.
将中文(简体)翻译成英文
几个要求
我必须使用 HTTP 方法 POST
,而不是 GET
查询字符串,因为我的查询超过了 Microsoft 的 URI 限制 15,845 个字符(请注意,这甚至是可能的当我在中文字符的情况下使用少于 10,000 个字符的限制时。原因是查询字符串必须进行 URL 编码,这会显着增加长度,但它在字符计数之前被 Microsoft 解码确定。
The only translate HTTP method that allows POST
s is the TranslateArrayMethod
,例如TranslateMethod
只允许 GET
。不幸的是,TranslateArrayMethod
只接受 XML 文档,所以我必须使用 XML.
以下是我发送的 XML 文档的示例:
<TranslateArrayRequest>
<AppId/>
<From>es</From>
<Options>
<ContentType xmlns="http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2">text/plain</ContentType>
</Options>
<Texts>
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<![CDATA[Hola]]>
</string>
</Texts>
<To>en</To>
</TranslateArrayRequest>
这很好用,结果是:
<ArrayOfTranslateArrayResponse xmlns="http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<TranslateArrayResponse>
<From>es</From>
<OriginalTextSentenceLengths xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a:int>4</a:int>
</OriginalTextSentenceLengths>
<TranslatedText>Hello</TranslatedText>
<TranslatedTextSentenceLengths xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a:int>5</a:int>
</TranslatedTextSentenceLengths>
</TranslateArrayResponse>
</ArrayOfTranslateArrayResponse>
但是,如果我再添加任何汉字,就像这样:
<TranslateArrayRequest>
<AppId/>
<From>zh-CHS</From>
<Options>
<ContentType xmlns="http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2">text/plain</ContentType>
</Options>
<Texts>
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<![CDATA[南]]>
</string>
</Texts>
<To>en</To>
</TranslateArrayRequest>
我收到一个奇怪的回复:
<html>
<body/>
<h1>System.Runtime.Serialization.SerializationException</h1>
<p>Message: There was an error deserializing the object of type Microsoft.MT.MDistributor.V2.TranslateArrayRequest. Unexpected end of file. Following elements are not closed: TranslateArrayRequest. Line 1, position 298.</p>
</html>
请注意,我也尝试过不使用 CDATA 转义,但没有帮助。更改 From
语言也没有效果。
我正在使用 Node.js (Javascript),尽管因为这是一个通用的 HTTP API 我认为这不重要。
很可能,问题不是中文,而是MS Translator 不喜欢换行符号。当我偶然发现此错误消息时,我更改了以下内容:
- 在
节点的每个内容中,用空字符串替换新行字符。这些字符具有 Unicode 值:0xA、0xB、0xC、0xD、0x85、0x2028、0x2029
在 节点的每个内容中,将 XML 保留字替换为其替代表示:
& → &
< → <
> → >
' → '
" → "
- 将整个 XML 重新排列成一行
之后一切顺利。关于您的特定示例,符号“南”被翻译为 "South"。我没有使用 CDATA 转义。
好的,我在调用来自 Node.js 的 Microsoft Translator POST API 之一时遇到了完全相同的问题。 API 工作正常 - returns 翻译符合预期 - 只要没有 non-ASCII 个字符,但是当我在适当的 [= POST body 的 13=] 部分,它响应错误:
<html><body/><h1>System.Runtime.Serialization.SerializationException</h1>
<p>Message: There was an error deserializing the object of type Microsoft.MT.MDistributor.V2.TranslateArrayRequest. Unexpected end of file. Following elements are not closed: TranslateArrayRequest. Line 1, position 782.</p>
</html>
我发现问题是 Content-Length
header 想要以字节为单位的长度,但我一直在发送以字符为单位的长度。为什么会这样?那么,测量节点 http 请求的 body 长度的典型方法是调用
var length = body.length
并获取字符串的 "length" - 即字符数。这在所有字符都是 ASCII 时有效。然而,事实证明,在 UTF-8 non-ASCII 中,每个字符(包括我的重音符号 'é')可以超过一个字节。所以当 body 包含 non-ASCII 个字符时,字节长度将不再等于字符长度,字符长度不正确。在这种情况下,它导致 Microsoft 服务器过早地停止读取消息,从而生成错误消息。
相反,我们需要通过调用(在 Node.js 中)
来测量字节长度
var length = Buffer.byteLength(body, 'utf8')
并在 Content-Length
header 中发送该长度,Microsoft Translator API 再次工作。
我正在尝试使用 Microsoft Translator API.
将中文(简体)翻译成英文几个要求
我必须使用 HTTP 方法
POST
,而不是GET
查询字符串,因为我的查询超过了 Microsoft 的 URI 限制 15,845 个字符(请注意,这甚至是可能的当我在中文字符的情况下使用少于 10,000 个字符的限制时。原因是查询字符串必须进行 URL 编码,这会显着增加长度,但它在字符计数之前被 Microsoft 解码确定。The only translate HTTP method that allows
POST
s is theTranslateArrayMethod
,例如TranslateMethod
只允许GET
。不幸的是,TranslateArrayMethod
只接受 XML 文档,所以我必须使用 XML.
以下是我发送的 XML 文档的示例:
<TranslateArrayRequest>
<AppId/>
<From>es</From>
<Options>
<ContentType xmlns="http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2">text/plain</ContentType>
</Options>
<Texts>
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<![CDATA[Hola]]>
</string>
</Texts>
<To>en</To>
</TranslateArrayRequest>
这很好用,结果是:
<ArrayOfTranslateArrayResponse xmlns="http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<TranslateArrayResponse>
<From>es</From>
<OriginalTextSentenceLengths xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a:int>4</a:int>
</OriginalTextSentenceLengths>
<TranslatedText>Hello</TranslatedText>
<TranslatedTextSentenceLengths xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a:int>5</a:int>
</TranslatedTextSentenceLengths>
</TranslateArrayResponse>
</ArrayOfTranslateArrayResponse>
但是,如果我再添加任何汉字,就像这样:
<TranslateArrayRequest>
<AppId/>
<From>zh-CHS</From>
<Options>
<ContentType xmlns="http://schemas.datacontract.org/2004/07/Microsoft.MT.Web.Service.V2">text/plain</ContentType>
</Options>
<Texts>
<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<![CDATA[南]]>
</string>
</Texts>
<To>en</To>
</TranslateArrayRequest>
我收到一个奇怪的回复:
<html>
<body/>
<h1>System.Runtime.Serialization.SerializationException</h1>
<p>Message: There was an error deserializing the object of type Microsoft.MT.MDistributor.V2.TranslateArrayRequest. Unexpected end of file. Following elements are not closed: TranslateArrayRequest. Line 1, position 298.</p>
</html>
请注意,我也尝试过不使用 CDATA 转义,但没有帮助。更改 From
语言也没有效果。
我正在使用 Node.js (Javascript),尽管因为这是一个通用的 HTTP API 我认为这不重要。
很可能,问题不是中文,而是MS Translator 不喜欢换行符号。当我偶然发现此错误消息时,我更改了以下内容:
- 在
节点的每个内容中,用空字符串替换新行字符。这些字符具有 Unicode 值:0xA、0xB、0xC、0xD、0x85、0x2028、0x2029 在
节点的每个内容中,将 XML 保留字替换为其替代表示: & → &
< → <
> → >
' → '
" → "
- 将整个 XML 重新排列成一行
之后一切顺利。关于您的特定示例,符号“南”被翻译为 "South"。我没有使用 CDATA 转义。
好的,我在调用来自 Node.js 的 Microsoft Translator POST API 之一时遇到了完全相同的问题。 API 工作正常 - returns 翻译符合预期 - 只要没有 non-ASCII 个字符,但是当我在适当的 [= POST body 的 13=] 部分,它响应错误:
<html><body/><h1>System.Runtime.Serialization.SerializationException</h1>
<p>Message: There was an error deserializing the object of type Microsoft.MT.MDistributor.V2.TranslateArrayRequest. Unexpected end of file. Following elements are not closed: TranslateArrayRequest. Line 1, position 782.</p>
</html>
我发现问题是 Content-Length
header 想要以字节为单位的长度,但我一直在发送以字符为单位的长度。为什么会这样?那么,测量节点 http 请求的 body 长度的典型方法是调用
var length = body.length
并获取字符串的 "length" - 即字符数。这在所有字符都是 ASCII 时有效。然而,事实证明,在 UTF-8 non-ASCII 中,每个字符(包括我的重音符号 'é')可以超过一个字节。所以当 body 包含 non-ASCII 个字符时,字节长度将不再等于字符长度,字符长度不正确。在这种情况下,它导致 Microsoft 服务器过早地停止读取消息,从而生成错误消息。
相反,我们需要通过调用(在 Node.js 中)
来测量字节长度var length = Buffer.byteLength(body, 'utf8')
并在 Content-Length
header 中发送该长度,Microsoft Translator API 再次工作。