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

时间:2014-10-02 01:52:34

标签: java soap encoding

我试图从我的Java客户端调用基于DotNet的SOAP Web服务,并且SOAP请求XML包含CDATA xml作为<ser:answerFile>标记中的值。理想的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声明为字符串,并在调用Webservice时使用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;在&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####");

    }
}

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

1 个答案:

答案 0 :(得分:2)

您有两种方法可以解决此问题。

首先是完全从XML片段中删除<![CDATA[ ... ]]>转义。似乎库类PlatformSoap已经转义了内容中的XML符号。

由于PlatformSoap在将字符串放入XML文档时会将字符串展开,如果从字符串中删除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部分的方法/机制,并在PlatformSoap
  3. 上为该新方法提供未包装的字符串

    总结:

    • CDATA纯粹是一个方便的包装器,允许您使用未转义的内容。
    • 转义它而不是使用CDATA在语义上是相同的,XML的逻辑含义/内容没有区别。
    • 服务的远端是否符合XML约定是不确定的
    • 如果是,则只使用转义版本(无CDATA)
    • 如果没有,那么改变远方。
    • 如果没有,并且您无法更改远端,请在PlatformSoap
    • 中更改您的代码