2

我必须使用单个参数(XML 格式的字符串)调用 Web 服务。我正在通过 XSLT 转换来构建它。到现在为止还挺好。

问题在于这个 XSD 片段:

<xs:complexType name="Document">
    <xs:sequence>
        <xs:element name="title" type="xs:string" minOccurs="1"/>
        <xs:element name="content" type="xs:base64Binary" minOccurs="1"/>
    </xs:sequence>
</xs:complexType>

它将(例如)翻译成这个 XML:

<attachment>
    <title>test title</title>
    <content>          
    PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Inllc
    yI/Pg0KPG1zZ3ByYXRpY2E+DQogICAgPHByYXRpY2E+DQogICAgICAgIDxwcm9jZXNzbz
    4NCiAgICAgICAgICAgIDxjb2RQcm9jZXNzbz4xPC9jb2RQcm9jZXNzbz4NCiAgICAgICA
    gICAgIDxjb2RJc3RhbnphUHJvY2Vzc28MzwvY29kSXN0YW56YVByb2Nlc3NvPg0KICAgI
    CAgICAgICAgPGNvZFN0YXRvPjYwPC9jb2RTdGF0bz4NCiAgICAgICAgPC9wcm9jZXNzbz
    4NCiAgICA8L3ByYXRpY2E+DQo8L21zZ3ByYXRpY2E+
    </content>
</attachment>

是的,你没看错:我必须以 base 64 二进制格式将文件内容插入 XML 文档。

我想过用 XSLT 插入一个占位符,然后处理 XML 文档以将其替换为实际的文件内容,但我想知道这些场合是否有任何最佳实践,也许是一些超出我知识的花哨 XSTL 技巧或一些 Java可能派上用场的工具。

你会怎么做?

注意:我不能使用带有附件的 SOAP,而且我很清楚上述方法在附件很大的情况下容易失败,但目前我们的对手不会让步。

4

4 回答 4

2

执行此操作的最佳方法可能是读取文件并通过实例化 XSLT 转换的代码以 base64 对其内容进行编码。base64 字符串可以作为参数传递给转换,或者转换可以通过扩展方法请求它。

原则上 XSLT 可用于对 base64 进行编码,但是某些字节值,例如 0(对于 XML 1.0 和 XML 1.1)和 0x20 以下的 29 个其他代码(对于 XML 1.0)被禁止作为 XML 文档中的字符,并且这使得在 XSLT 中进行这种编码是不可能的。

(见:http ://projects.ischool.washington.edu/tabrooks/545/ContentManagement/PassingParameters.htm )

于 2009-04-01T22:38:03.830 回答
1

如果您的 SOAP 堆栈支持 MTOM,请将其打开。然后要做的就是在内容元素中放置一个“引用”,指向将放置数据的 MIME 附件。该数据可以是完全二进制的,而不是 base64 编码的。

于 2009-04-03T18:45:28.000 回答
0

这并不完全是您正在寻找的答案,但是像 Woodstox链接文本这样的 XML 处理器支持高效读取和写入内联 Base64 编码的内容。在 Woodstox 4.0 中,它使用所谓的 Typed Access API 完成,它是 Stax2 扩展 API 的一部分(在包“org.codehaus.stax2.typed.*”、TypedXMLStreamReader、TypedXMLStreamWriter 下)。

这允许在给定二进制数据的情况下对元素和属性值进行流​​式读/写。

诀窍就是将它与 XSLT 挂钩。另一种可能更简单的方法是确定客户端 API Soap 堆栈(如 CXF aka XFire)是否可以让您通过 XMLStreamReader/Writer 访问内容。大多数新的都基于 Stax,通常嵌入 Woodstox。

于 2009-04-02T18:22:05.723 回答
0

以下是我将如何在 Java 中的 base64Binary 对象(使用 MTOM 或 SwAref)上发送数据,至少用于测试目的(如硬编码数据路径所述)。

obj.setContent(
  新数据处理程序(
    新的 URL 数据源(
      this.getClass().getResource("/someDocument.png")
    ));

虽然正常的操作是使用 FileDataSource 来传递数据。虽然我很确定有人会想到创建自己的数据源。一般来说,我认为这不是一个好主意,因为最有可能的实现是使用 ByteArrayInputStream,它使用 VM 内存,如果你发送一个大文件,它会严重崩溃。

如果您需要传递一个简单的字符串以进行测试,您可以执行以下操作:

obj.setContent(
  new DataHandler("test string", "text/plain");

此外,如果您使用的是 WebSphere 7 运行时,@MTOM如果您注意到正在发送的数据仅包含消息,而没有附件,则可能需要在服务实现中使用注释。

于 2010-09-27T18:44:41.287 回答