如何在Java SOAP客户端中避免对<和>进行编码

3

我想从我的Java客户端调用一个基于DotNet的SOAP Webservice,SOAP请求XML包含在<ser:answerFile>标记中作为值的CDATA xml。理想的SOAP请求应该看起来像下面这样:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://services.intel.com/">
   <soapenv:Header>
      <ser:SessionHeader>
         <ser:SessionId>6fdd74d0-3405</ser:SessionId>
      </ser:SessionHeader>
   </soapenv:Header>
   <soapenv:Body>
      <ser:SaveProgressForUser>
         <!--Optional:-->
         <ser:userName>TestUser</ser:userName>
         <!--Optional:-->
         <ser:answerFile><![CDATA[<AnswerFile Version="2"><HeaderInfo></HeaderInfo><ps><p pid="e32ae8d7-017b-4d36-9c4c-09f6822362b3"><qs><q qid="b4c31241-c6c9-4013-9740-4cbc520dd10a" SelectedValue="" /><repeat c="2" guid="32418f0a-7e13-40db-872d-a42e220bfc15"><qs i="0" guid="b2f16b48-ca3d-4a06-85e8-7373ead7ccfe"><q qid="7834cb57-ba6f-4063-8a02-4925079d7e04" SelectedValue="" /></qs><qs i="1" guid="cb9e34a2-ecd8-4e06-8072-a6cb682fb655"><q qid="7834cb57-ba6f-4063-8a02-4925079d7e04" SelectedValue="" /></qs></repeat></qs></p></ps></AnswerFile>]]>
         </ser:answerFile>
      </ser:SaveProgressForUser>
   </soapenv:Body>
</soapenv:Envelope>

在我的Java客户端中,我将AnswerFile声明为一个字符串,并在调用Web服务时使用setter方法来设置该字符串。

String answerFile = "<![CDATA[<AnswerFile Version="2"><HeaderInfo></HeaderInfo><ps><p pid="e32ae8d7-017b-4d36-9c4c-09f6822362b3"><qs><q qid="b4c31241-c6c9-4013-9740-4cbc520dd10a" SelectedValue="" /><repeat c="2" guid="32418f0a-7e13-40db-872d-a42e220bfc15"><qs i="0" guid="b2f16b48-ca3d-4a06-85e8-7373ead7ccfe"><q qid="7834cb57-ba6f-4063-8a02-4925079d7e04" SelectedValue="" /></qs><qs i="1" guid="cb9e34a2-ecd8-4e06-8072-a6cb682fb655"><q qid="7834cb57-ba6f-4063-8a02-4925079d7e04" SelectedValue="" /></qs></repeat></qs></p></ps></AnswerFile>]]>"

然而,虽然 Java 聪明绝顶,它在字符串中编码了 < 和 > 为 &lt;&gt;,我的生成请求包含了一个带有编码值的 <ser:answerFile>,如以下示例:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://services.intel.com/">
   <soapenv:Header>
      <ser:SessionHeader>
         <ser:SessionId>6fdd74d0-3405</ser:SessionId>
      </ser:SessionHeader>
   </soapenv:Header>
   <soapenv:Body>
      <ser:SaveProgressForUser>
         <!--Optional:-->
         <ser:userName>TestUser</ser:userName>
         <!--Optional:-->
         <ser:answerFile>&lt;![CDATA[&lt;AnswerFile Version="2"&gt;&lt;HeaderInfo&gt;&lt;ps&gt;&lt;p pid="e32ae8d7-017b-4d36-9c4c-09f6822362b3"&gt;&lt;qs&gt;&lt;q qid="b4c31241-c6c9-4013-9740-4cbc520dd10a" SelectedValue="" /&gt;&lt;repeat c="2" guid="32418f0a-7e13-40db-872d-a42e220bfc15"&gt;&lt;qs i="0" guid="b2f16b48-ca3d-4a06-85e8-7373ead7ccfe"&gt;&lt;q qid="7834cb57-ba6f-4063-8a02-4925079d7e04" SelectedValue="" /&gt;&lt;/qs&gt;&lt;qs i="1" guid="cb9e34a2-ecd8-4e06-8072-a6cb682fb655"&gt;&lt;q qid="7834cb57-ba6f-4063-8a02-4925079d7e04" SelectedValue="" /&gt;&lt;/qs&gt;&lt;/repeat&gt;&lt;/qs&gt;&lt;/p&gt;&lt;/ps&gt&lt;/AnswerFile&gt;]]&gt;
         </ser:answerFile>
      </ser:SaveProgressForUser>
   </soapenv:Body>
</soapenv:Envelope>

所以,我如何避免这种编码并将answerFile值原样传递(包括<>)。 我无法创建文档元素对象结构并设置,因为setter根据WSDL只接受字符串。
如果问题描述中缺少任何信息,请大声告诉我,我会感激任何帮助。
就像我说的那样,我没有使用文档构建器方法,而是使用了一个微不足道的String对象来表示CDATA XML。下面是该类的一部分。
public static void main(String[] args) throws Exception {

    try {
            String username = "ServiceUser";
            String password = "Help#";

            String masquaradeUsername = "TestUser";

            NtlmAuthenticator authenticator = new NtlmAuthenticator(username, password);
            Authenticator.setDefault(authenticator);

            Platform platform = new Platform();
            PlatformSoap client = platform.getPlatformSoap();

            String answerXML = "<![CDATA[<AnswerFile Version=\"2\"><HeaderInfo></HeaderInfo><ps><p pid=\"e32ae8d7-017b-4d36-9c4c-09f6822362b3\"><qs><q qid=\"b4c31241-c6c9-4013-9740-4cbc520dd10a\" SelectedValue=\"\" /><repeat c=\"2\" guid=\"32418f0a-7e13-40db-872d-a42e220bfc15\"><qs i=\"0\" guid=\"b2f16b48-ca3d-4a06-85e8-7373ead7ccfe\"><q qid=\"7834cb57-ba6f-4063-8a02-4925079d7e04\" SelectedValue=\"\" /></qs><qs i=\"1\" guid=\"cb9e34a2-ecd8-4e06-8072-a6cb682fb655\"><q qid=\"7834cb57-ba6f-4063-8a02-4925079d7e04\" SelectedValue=\"\" /></qs></repeat></qs></p></ps></AnswerFile>]]>";

            String saveGUID = client.saveProgressForUser(masquaradeUsername, answerXML);

        } catch(Exception e) {
            LOGGER.info("Exception encountered####");

    }
}

希望这些信息能帮助您更好地理解我的问题。

这不仅是您正在编码的字符串的问题,还涉及到您将其发送给创建SOAP文档的库的方式。请包含构建文档的周围代码。 - rolfl
你好,感谢您的关注。请查看更新后的问题。 - user3579926
1个回答

4
您有两个解决此问题的选项。
第一个是完全删除XML片段中的<![CDATA[ ... ]]>转义。似乎库类PlatformSoap已经在内容中转义XML符号。
由于当您将其放入XML文档时,PlatformSoap会对字符串进行转义,因此如果从字符串中删除CDATA,则应将文档转义为:
<ser:answerFile>&lt;AnswerFile Version="2"&gt;&lt; ......... &lt;/repeat&gt;&lt;/qs&gt;&lt;/p&gt;&lt;/ps&gt&lt;/AnswerFile&gt;
</ser:answerFile>

这是有效的XML,在连接的另一端,它应该正确解析XML,恢复原始内容,并且不需要使用CDATA。

如果连接的另一端表现良好,上述方法就能正常工作。

另一方面,连接的另一端可能希望找到实际的CDATA部分,在这种情况下,您应该做两件事:

  1. 对不符合XML标准的人员提出错误报告
  2. 修改PlatformSoap类以提供一个强制在内容周围放置CDATA部分并将未包装的字符串提供给该新方法的方法/机制。

总而言之:

  • CDATA只是一种方便的包装方式,允许您拥有未经转义的内容。
  • 转义而不是使用CDATA在语义上是相同的,XML的逻辑含义/内容没有任何区别。
  • 服务的远程一方是否遵循XML约定是不确定的。
  • 如果它这样做了,那么只需使用转义版本(没有CDATA)。
  • 如果它没有这样做,请更改远程一方。
  • 如果它没有这样做,并且您无法更改远程一方,则请更改PlatformSoap中的代码。

去掉CDATA包装就解决了问题。非常感谢您的帮助 :-)。非常感激。干杯。 - user3579926

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接