【问题标题】:Apache Camel to handle encoding declared in XML-FileApache Camel 处理 XML 文件中声明的编码
【发布时间】:2018-03-01 12:48:45
【问题描述】:

我正在尝试使用带有 xtokenize 的 Apache Camel Splitter 解析 UTF-16 编码的文档,这代表 Woodstox (com.ctc.wstx.sr.BasicStreamReader),而且我在阅读之前无法知道文件的编码它,目前有些文件是 UTF-16,有些是 UTF-8:

.split().xtokenize(getToken(), 'w', NAMESPACES)

我遇到的问题是 Camel 告诉 Woodstox 使用哪种编码:

String charset = IOHelper.getCharsetName(exchange);

它将默认 UTF-8 设置为编码,因此 BasicStreamReader 尝试将 BOM 字节读取为 UTF-8 并失败

com.ctc.wstx.exc.WstxUnexpectedCharException: Unexpected character '�' (code 65533 / 0xfffd) in prolog; expected '<'

https://www.w3.org/TR/xml/#sec-guessing 中所述,如果只有 Camel 允许,XML Parser (Woodstox) 应该能够自动检测文件编码。

有没有办法不自己实现编码检测?

【问题讨论】:

  • 你用的是什么版本的骆驼?
  • 2.17.5忘了说

标签: java xml-parsing apache-camel xml-encoding


【解决方案1】:

好的,我可以看到当前源代码将回退并使用平台编码。因此,不支持使用 XML 节中提供的编码的用例。

我不确定 Camel 是否真的需要回退到默认平台编码,因为它在拆分器中使用 java.util.Scanner,并且它支持在不使用特定编码的情况下进行扫描。

也许您可以尝试修补XMLTokenExpressionIterator中的源代码并在本地为您测试,然后在这里报告。

然后我们可能会看看在 Apache Camel 中是否将其设为可选以使用回退编码。

在您当前版本的 Apache Camel 中,您始终可以扩展 XMLTokenExpressionIterator 并覆盖 doEvaluate 方法,然后在没有字符集参数的情况下调用 createIterator 方法。然后将您的自定义迭代器与 Camel 拆分器一起使用。

【讨论】:

  • 回退不是平台编码:它是:String DEFAULT_CHARSET_PROPERTY = "org.apache.camel.default.charset";定义时,否则为 UTF-8,因此默认为 UTF-8。但这比依赖“随机”平台编码要好
  • 我可以查明问题:Camel 的 XmlTokenExpressionIterator 使用了 Reader (RecordableReader),因此说它知道输入的字符集。因此 Woodstox(例如)将使用 ReaderBootstrapper 而不是 StreamBootstrapper。请参阅 ReaderBootstrapper 的 javadoc:Input bootstrap class used when input comes from a Reader; in this case, encoding is already known, and thus encoding from XML declaration (if any) is only double-checked, not really used. StreamBootstrapper 能够识别声明的编码。
  • 我已经修补了XMLTokenExpressionIterator,很容易将同一包中的RecordableReader替换为RecordableInputStream。 createXMLStreamReader(in) 已弃用,另一种方法希望交换选择字符集,但您可以轻松修复它。现在它在 XmlConverter 的下一步中失败了,我出于同样的原因将 xslt 应用于提取的字符串:XMLStreamReader r = new StaxConverter().createXMLStreamReader(new StringReader(source)) 它不知道它是 UTF-16。我认为应该在 EXCHANGE 上设置检测到的编码,以便 Camel 进行下一步。
  • 我要为它创建一个错误报告,它需要在几个地方修复...
  • hmmm 有一条评论:// woodstox's getLocation().etCharOffset() does not return the offset correctly for InputStream, so use Reader instead. 说 InputStream 不起作用?
【解决方案2】:

创建了 Camel JIRA 票证: https://issues.apache.org/jira/browse/CAMEL-11846 从我的 cmets 中,您可以看到在不事先知道它是 UTF-16 的情况下,用 Camel 拆分 UTF-16 XML 没有简单的解决方案。

虽然子类化 XMLTokenExpressionIterator(一个 ExpressionAdapter 并切换到 InputStream)首先是可行的,但在其他几个地方使用 xslt & xpath & 转换为 StaxSource 时也会因为同样的原因而中断。

作为一种解决方法,我认为让 XmlStreamReader 提前找出编码(在初始化时发生)并设置 Exchange.CHARSET_NAME 标头或属性会更容易。

【讨论】:

  • 我用我的解决方法评论了引用的 JIRA 票证。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-28
  • 1970-01-01
相关资源
最近更新 更多