2017-01-10 62 views
1

我想顯示服務器向我發送的響應,但是在解析它時向我顯示了空字符串。我試着解析服務器響應,如其他教程中所示,但它不起作用。有誰知道我做錯了嗎?在JAVA中解析XML命名空間(服務器響應)

Java代碼

import java.io.StringWriter; 
import java.util.HashMap; 
import java.util.Map; 
import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.xpath.XPath; 
import javax.xml.xpath.XPathConstants; 
import javax.xml.xpath.XPathExpression; 
import javax.xml.xpath.XPathFactory; 
import org.apache.http.HttpResponse; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.entity.StringEntity; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.w3c.dom.Document; 
import freemarker.template.Configuration; 
import freemarker.template.Template; 
public class ClienteSoap { 
    public static void main(String[] args) { 
     HttpClient httpClient = null; 

      try { 
      Configuration cfg = new Configuration(); 

      // Cargar plantilla 
      Template template = cfg.getTemplate("src/main/resources/templates/template.ftl"); 

      // Modelo de datos 
      Map<String, Object> data = new HashMap<String, Object>(); 
      data.put("token", "u757Ric6542ytu6Ricgtr0"); 
      data.put("branch", "1"); 
      data.put("app", "S-04600"); 
      data.put("folio", "4345Ric67"); 
      data.put("temp", "False"); 


      // Crear mensaje SOAP HTTP 
      StringWriter out = new StringWriter(); 
      template.process(data, out); 
      String strRequest = out.getBuffer().toString(); 
      System.out.println(strRequest); 

      // Crear la llamada al servidor 
      httpClient = new DefaultHttpClient(); 
      HttpPost postRequest = new 
      HttpPost("http://127.0.0.1:30005/PCIServicioConciliadorCore-web"); //direccion de la pagina 
      StringEntity input = new StringEntity(strRequest); 
      input.setContentType("text/xml"); 
      postRequest.setEntity(input); 

      // Tratar respuesta del servidor 
      HttpResponse response = httpClient.execute(postRequest); 
      if (response.getStatusLine().getStatusCode() != 200) { 
       throw new RuntimeException("Error : Código de error HTTP : " + response.getStatusLine().getStatusCode()); 
      } 

      //Obtener información de la respuesta 
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
      System.out.println(factory); 
      Document XMLDoc = factory.newDocumentBuilder().parse(response.getEntity().getContent()); 
      XPath xpath = XPathFactory.newInstance().newXPath(); 
      XPathExpression expr = xpath.compile("/AddToken2DBResponseType/Token"); 
      String result = String.class.cast(expr.evaluate(XMLDoc, XPathConstants.STRING)); 
      System.out.println("\nEl resultado es: " + result.length()); 
     }catch (Exception e) { 
      e.printStackTrace(); 
     } finally { 
      // Cierre de la conexión 
      if (httpClient != null) httpClient.getConnectionManager().shutdown(); 
     } 
    } 
} 

WSDL響應

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
    <SOAP-ENV:Header/> 
    <SOAP-ENV:Body> 
     <ns2:AddToken2DBResponse xmlns:ns2="http://www.example.com/edit/example"> 
     <ns2:Token>u757Ric6542ytu6Ricgtr0</ns2:Token> 
     <ns2:HandlerError> 
      <ns2:statusCode>true</ns2:statusCode> 
      <ns2:errorList> 
       <ns2:error> 
        <ns2:code>OK</ns2:code> 
        <ns2:origin>JBOSS</ns2:origin> 
        <ns2:userMessage>Primer registro insertado</ns2:userMessage> 
        <ns2:developerMessage>Primer registro insertado</ns2:developerMessage> 
       </ns2:error> 
      </ns2:errorList> 
     </ns2:HandlerError> 
     </ns2:AddToken2DBResponse> 
    </SOAP-ENV:Body> 
</SOAP-ENV:Envelope> 

我感謝你的幫助

+0

而不是'String.class.cast(x)',你應該使用'(String)x'。只有在編譯時不知道要投射的類時,才應該使用'cast'方法。 – VGR

回答

2

你的XPath表達式是錯誤的,如果它與一個單一的/這意味着該元素應該是開始一個/根元素(顯然它不會找到任何東西,因爲根元素是SOAP-ENV:Envelope)。到目前爲止,它應該是//AddToken2DBResponseType/Token

第二個問題是命名空間;你有兩個選擇(我知道):

  • 解析它的名稱空間感知和重寫xpath是容忍朝着命名空間。
  • 解析它的名稱空間並不知道,並在xpath中使用名稱空間前綴。

第二個選項是相當不穩定所以這裏是第一:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
factory.setNamespaceAware(true); 
// ... 
XPathExpression expr = xpath.compile("//*[local-name='AddToken2DBResponseType']/*[local-name='Token']"); 

//*[local-name='abc']是指具有ABC的地方姓名(名稱沒有命名空間)的任何元素(正是你想要/需要什麼) 。

+1

還有另一種選擇:解析名稱空間感知並在'XPath'上設置名稱空間上下文來定義自己的前綴映射。 – teppic

+0

@teppic謝謝你知道這個選項;它是否適用於XPath 1. *還是需要XPath 2? –

+0

它適用於XPath 1.它有點煩瑣。沒有'NamespaceContext'的默認實現,所以需要添加一個依賴項或者編寫你自己的。 – teppic