【问题标题】:Formatting Web Service Response格式化 Web 服务响应
【发布时间】:2013-10-24 16:11:31
【问题描述】:

我使用以下函数来检索 Web 服务响应:

private String getSoapResponse (String url, String host, String encoding, String soapAction, String soapRequest) throws MalformedURLException, IOException, Exception {         
    URL wsUrl = new URL(url);     
    URLConnection connection = wsUrl.openConnection();     
    HttpURLConnection httpConn = (HttpURLConnection)connection;     
    ByteArrayOutputStream bout = new ByteArrayOutputStream(); 

    byte[] buffer = new byte[soapRequest.length()];     
    buffer = soapRequest.getBytes();     
    bout.write(buffer);     
    byte[] b = bout.toByteArray();          

    httpConn.setRequestMethod("POST");
    httpConn.setRequestProperty("Host", host);

    if (encoding == null || encoding == "")
        encoding = UTF8;

    httpConn.setRequestProperty("Content-Type", "text/xml; charset=" + encoding);
    httpConn.setRequestProperty("Content-Length", String.valueOf(b.length));
    httpConn.setRequestProperty("SOAPAction", soapAction);

    httpConn.setDoOutput(true);
    httpConn.setDoInput(true);

    OutputStream out = httpConn.getOutputStream();
    out.write(b); 
    out.close();

    InputStreamReader is = new InputStreamReader(httpConn.getInputStream());
    StringBuilder sb = new StringBuilder();
    BufferedReader br = new BufferedReader(is);
    String read = br.readLine();

    while(read != null) {
        sb.append(read);
        read = br.readLine();
    }

    String response = decodeHtmlEntityCharacters(sb.toString());    

    return response = decodeHtmlEntityCharacters(response);
}

但我对这段代码的问题是它返回大量特殊字符并使 XML 的结构无效。
示例响应:

<PLANT>A565</PLANT>
          <PLANT>A567</PLANT>
          <PLANT>A585</PLANT>
          <PLANT>A921</PLANT>
          <PLANT>A938</PLANT>
        </PLANT_GROUP>
      </KPI_PLANT_GROUP_KEYWORD>
      <MSU_CUSTOMERS/>
    </DU>
    <DU> 

所以为了解决这个问题,我使用以下方法并传递整个响应以将所有特殊字符替换为其对应的标点符号。

private final static Hashtable htmlEntitiesTable = new Hashtable();
static {
    htmlEntitiesTable.put("&","&");
    htmlEntitiesTable.put(""","\"");
    htmlEntitiesTable.put("&lt;","<");
    htmlEntitiesTable.put("&gt;",">");  
}

private String decodeHtmlEntityCharacters(String inputString) throws Exception {
    Enumeration en = htmlEntitiesTable.keys();

    while(en.hasMoreElements()){
        String key = (String)en.nextElement();
        String val = (String)htmlEntitiesTable.get(key);

        inputString = inputString.replaceAll(key, val);
    }

    return inputString;
}

但是出现了另一个问题。如果响应包含此段 &amp;lt;VALUE&amp;gt;&amp;lt; 0.5 &amp;lt;/VALUE&amp;lt; 并且如果这将由该方法评估,则输出将是:

&lt;VALUE&gt;&lt; 0.5&lt;/VALUE&gt;

这使得 XML 的结构再次无效。 数据正确且有效“

你能帮忙解决这个问题吗?也许我获得或建立响应的方式可以改进。有没有更好的方法来调用并从 Web 服务获取响应?

如何处理包含“”的元素?

【问题讨论】:

  • 所以您需要一种方法来检测“
  • 我建议在 VALUE 上有一个属性。将属性设为 1 或 0,具体取决于您是否需要小于/大于。 (或 -1、0、1 表示 )
  • 为什么不正确编码?
  • @BrianAgnew 它从一开始就被正确编码,与 xml 的其余部分一起。然后他在解码xml的其余部分时对其进行解码。问题是他需要区分不同的“
  • @Cruncher 嗯,它看起来不像一开始就被正确编码。如果是这样,则不会对实际的 XML 结构进行编码,而只会对数据进行编码。还是您看到了我们看不到的东西?

标签: java xml web-services


【解决方案1】:

你知道如何使用第三方开源库吗?

你应该尝试使用 apache commons-lang:

StringEscapeUtils.unescapeXml(xml)

以下堆栈溢出帖子提供了更多详细信息:

how to unescape XML in java

文档:

http://commons.apache.org/proper/commons-lang/javadocs/api-release/index.html http://commons.apache.org/proper/commons-lang/userguide.html#lang3.

【讨论】:

    【解决方案2】:

    您使用 SOAP 错误。

    特别是,您不需要以下代码行:

         String response = decodeHtmlEntityCharacters(sb.toString());    
    

    只需返回sb.toString()。并且为了 $DEITY,不要使用字符串方法来解析检索到的字符串,使用 XML 解析器或成熟的 SOAP 堆栈...

    【讨论】:

      【解决方案3】:

      > 或

      示例代码,假设其中使用的替换字符串不出现在 XML 的其他任何地方:

      private String decodeHtmlEntityCharacters(String inputString) throws Exception {
          Enumeration en = htmlEntitiesTable.keys();
      
          // Replaces &gt; or &lt; followed by dot or digit (while keeping the dot/digit)
          inputString = inputString.replaceAll("&gt;(\\.?\\d)", "Valuegreaterthan$1");
          inputString = inputString.replaceAll("&lt;(\\.?\\d)", "Valuelesserthan$1");
      
          while(en.hasMoreElements()){
              String key = (String)en.nextElement();
              String val = (String)htmlEntitiesTable.get(key);
      
              inputString = inputString.replaceAll(key, val);
          }
      
          inputString = inputString.replaceAll("Valuelesserthan", "&lt;");
          inputString = inputString.replaceAll("Valuegreaterthan", "&gt;");
      
          return inputString;
      }
      

      请注意,最合适的答案(而且对每个人来说都更容易)是在发送方正确编码 XML(这也会使我的解决方案无法正常工作)。

      【讨论】:

      • ">" 和 "<VALUE><0.5</VALUE> 关于正则表达式,是否有构建它的工具?不熟悉正则表达式。
      • String.replaceAll() 的第一个参数是一个正则表达式。既然我们在这里,让我问一下:&lt;VALUE&gt;&lt;/VALUE&gt; 是否会出现(即空值)?
      • 不,如果一个元素没有内容,标签将只是&lt;VALUE/&gt;
      • 好的。只是为了确定,哪些需要保持编码为&amp;gt;&amp;lt;,属于 XML 元素的封闭字符还是属于值的字符?
      • 是的,但是您指的是
      【解决方案4】:

      很难应对所有情况,但您可以通过添加更多规则来涵盖最常见的情况,假设任何小于后面的空格都是数据,大于前面的空格其中是数据,需要重新编码。

      private final static Hashtable htmlEntitiesTable = new Hashtable();
      static {
          htmlEntitiesTable.put("&amp;","&");
          htmlEntitiesTable.put("&quot;","\"");
          htmlEntitiesTable.put("&lt;","<");
          htmlEntitiesTable.put("&gt;",">");  
      }
      
      private String decodeHtmlEntityCharacters(String inputString) throws Exception {
          Enumeration en = htmlEntitiesTable.keys();
      
          while(en.hasMoreElements()){
              String key = (String)en.nextElement();
              String val = (String)htmlEntitiesTable.get(key);
      
              inputString = inputString.replaceAll(key, val);
          }
      
          inputString = inputString.replaceAll("< ","&lt; ");       
          inputString = inputString.replaceAll(" >"," &gt;");       
      
          return inputString;
      }
      

      【讨论】:

        【解决方案5】:

        '>' 在 XML 中没有转义。所以你不应该有这个问题。关于'

        1. 在 Web 响应中对包含特殊字符的文本使用 CDATA。
        2. 通过颠倒顺序重写文本。例如。如果是 x x。 '>' 不会被转义,除非它是 CDATA 的一部分。
        3. 在 XML 响应中使用另一个属性或元素来指示“”。
        4. 使用正则表达式查找以“

        另外,您不需要这样做:

        String response = decodeHtmlEntityCharacters(sb.toString()); 
        

        在处理完文本中的“

        您可以使用this 站点来测试正则表达式。

        【讨论】:

          【解决方案6】:

          为什么不序列化你的 xml?,它比你正在做的要容易得多。

          举个例子:

          var ser = new XmlSerializer(typeof(MyXMLObject));
          using (var reader = XmlReader.Create("http.....xml"))
          {
               MyXMLObject _myobj = (response)ser.Deserialize(reader);
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-10-10
            • 1970-01-01
            • 1970-01-01
            • 2010-12-28
            • 1970-01-01
            • 2013-08-08
            • 1970-01-01
            相关资源
            最近更新 更多