2016-01-21 12 views
7

私が開始する前に:子ノードが親ノードから名前空間を継承していることがわかりました。残念ながら、XMLを送信しているWebサービスは、ネームスペースなしで子ノードを受け入れず、政府機関であるため、部分的な変更はほとんどありません。フレームワークは、フレームワークのペイロード結果に私のペイロードソースを解析するために、変圧器を使用する一つの方法または他ではので、私は、私のアプリケーションとWebサービス間の通信を行うために春-WSを使用しています言われていること親ノードと子ノードに重複した名前空間を保持しないXMLの解析

<enviNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="3.10"> 
    <NFe xmlns="http://www.portalfiscal.inf.br/nfe"> 

は、変換した後、第二のネームスペースを除去する(私が前に言ったように、私はその理由を知っている):ここでは次のようにその変換が行われる前に は

transformer.transform(Source, Result); 

、私のXMLは、これら2つのノードがあります。

<enviNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="3.10"> 
    <NFe> 

私は同じ結果を達成し、パーズコードを自分で書くためにマーシャラーを使用できることにも気づいています。そのアプローチを使用することもOKであり、受け入れられるだろうが、私は同じことを達成するための他の方法を知らない(javax.xml.transform.Sourcejavax.xml.transform.Resultに変換する)。

私は、2つの質問がある:

1 - 私は(マーシャラーを使用せずに)デフォルトのアプローチを持っています動作を回避することはできますか?

2 - 同じ変換を行う他のツールはありますか?

+0

'transformer.transform(Source、Result) 'の呼び出しを制御しますか?つまり、必要に応じて異なるSourceオブジェクトまたはResultオブジェクトを渡すことができますか? – wero

+0

いいえ、私はそれを支配しません。結果は春から来ています。 –

答えて

1

私は同じ問題を抱えてきました。残念ながら、SOAPMessageFactory(SaajSoapMessageFactoryなど)の実装によるWebServiceTemplateは、トランスフォームをソースから結果に結びつけることによって、整形式XMLを要求として送信することを保証するために可能な限りすべてを行います。あなたがすでに親でしたとき、子供たちの中で。あなたは試してみるために、いくつかのエレガントなオプションを持っています - 彼らが最も簡単なものであるとは限りません。 javax.xml.ws.ServiceとDispatchインターフェースを使用してXMLレベルで作業することができます。これは、SSL認証が不要な場合は非常に簡単です。 (最初の1が白金-BRで書かれている)これらのリンクをチェックアウト:

http://www.guj.com.br/t/nfe-v2-00-veja-como-consumir-o-ws/297304

https://alesaudate.wordpress.com/2010/08/09/how-to-dynamically-select-a-certificate-alias-when-invoking-web-services/

また、あなたがそのようなDomPoxMessageFactoryなどの別のメッセージファクトリを、試すことができます。このリンクは便利かもしれません:

http://forum.spring.io/forum/spring-projects/web-services/128221-webservicetemplate-get-it-to-stop-adding-soap-envelope

プロジェクトの構造を変更すると(私の場合でした)オプションではない場合は、私はあなたのための回避策を持っています。 D

HttpComponentsMessageSenderクラスとHttpComponentsConnectionクラスの抽象クラスを作成しました.2番目のメソッドは、最初のメソッドcreateConnection(URI uri)でインスタンス化されていますが、これは例外ではありません。 。だから私はこのように私のWebServiceTemplateを作成することができます。

WebServiceTemplate wst = new WebServiceTemplate(new SaajSoapMessageFactory()); 
wst.setMessageSender(new CustomHttpComponentsMessageSender()); 

悲しいことに、あなただけのカスタム接続をインスタンス化するために、新たな抽象化にcreateConnecion方法を返信する必要があります。私が言ったように、それは回避策です!

@Override 
public WebServiceConnection createConnection(URI uri) throws IOException { 
    HttpPost httpPost = new HttpPost(uri); 
    if (isAcceptGzipEncoding()) { 
     httpPost.addHeader(HttpTransportConstants.HEADER_ACCEPT_ENCODING, 
       HttpTransportConstants.CONTENT_ENCODING_GZIP); 
    } 
    HttpContext httpContext = createContext(uri); 
    return new CustomHttpComponentsConnection(getHttpClient(), httpPost, httpContext); 
} 

メッセージを効果的にIから抽象化していHttpComponentsConnectionクラスのメソッドonSendAfterWrite(WebServiceMessageメッセージ)の内部に送られます。意外にも、 'message'パラメータはメソッド内では使用されません。それは継承ルールのためだけにあります。そして、良いニュース:それは保護された方法です。欠点は、もう一度、このメソッドだけを変更するためにクラス全体をほとんどコピーする必要があります。フィールドには公開されていない可視性がなく、フレームワークで応答処理が必要になると思います。だから、私は私のクラス全体をダウン投稿します:

public class CustomHttpComponentsConnection extends HttpComponentsConnection { 

    private final HttpClient httpClient; 

    private final HttpPost httpPost; 

    private final HttpContext httpContext; 

    private HttpResponse httpResponse; 

    private ByteArrayOutputStream requestBuffer; 

    protected CustomHttpComponentsConnection(HttpClient httpClient, HttpPost httpPost, HttpContext httpContext) { 
     super(httpClient, httpPost, httpContext); 

     Assert.notNull(httpClient, "httpClient must not be null"); 
     Assert.notNull(httpPost, "httpPost must not be null"); 
     this.httpClient = httpClient; 
     this.httpPost = httpPost; 
     this.httpContext = httpContext; 
    } 

    public HttpResponse getHttpResponse() { 
    return httpResponse; 
    } 

    public HttpPost getHttpPost() { 
     return httpPost; 
    } 

    @Override 
    protected OutputStream getRequestOutputStream() throws IOException { 
     return requestBuffer; 
    } 

    @Override 
    protected void onSendBeforeWrite(WebServiceMessage message) throws IOException { 
     requestBuffer = new ByteArrayOutputStream(); 
    } 

    @Override 
    protected void onSendAfterWrite(WebServiceMessage message) throws IOException { 

     OutputStream out = getRequestOutputStream(); 

     String str = out.toString(); 

     str = str.replaceAll("<NFe>", "<NFe xmlns=\"http://www.portalfiscal.inf.br/nfe\">"); 
     ByteArrayOutputStream bs = new ByteArrayOutputStream(); 
     bs.write(str.getBytes()); 

     getHttpPost().setEntity(new ByteArrayEntity(bs.toByteArray())); 

     requestBuffer = null; 
     if (httpContext != null) { 
      httpResponse = httpClient.execute(httpPost, httpContext); 
     } 
     else { 
      httpResponse = httpClient.execute(httpPost); 
     } 
    } 

    @Override 
    protected int getResponseCode() throws IOException { 
     return httpResponse.getStatusLine().getStatusCode(); 
    } 

    @Override 
    protected String getResponseMessage() throws IOException { 
     return httpResponse.getStatusLine().getReasonPhrase(); 
    } 

    @Override 
    protected long getResponseContentLength() throws IOException { 
     HttpEntity entity = httpResponse.getEntity(); 
     if (entity != null) { 
      return entity.getContentLength(); 
     } 
     return 0; 
    } 

    @Override 
    protected InputStream getRawResponseInputStream() throws IOException { 
     HttpEntity entity = httpResponse.getEntity(); 
     if (entity != null) { 
      return entity.getContent(); 
     } 
     throw new IllegalStateException("Response has no enclosing response entity, cannot create input stream"); 
    } 

    @Override 
    public Iterator<String> getResponseHeaderNames() throws IOException { 
     Header[] headers = httpResponse.getAllHeaders(); 
     String[] names = new String[headers.length]; 
     for (int i = 0; i < headers.length; i++) { 
      names[i] = headers[i].getName(); 
     } 
     return Arrays.asList(names).iterator(); 
    } 

    @Override 
    public Iterator<String> getResponseHeaders(String name) throws IOException { 
     Header[] headers = httpResponse.getHeaders(name); 
     String[] values = new String[headers.length]; 
     for (int i = 0; i < headers.length; i++) { 
      values[i] = headers[i].getValue(); 
     } 
     return Arrays.asList(values).iterator(); 
    } 

はやはり、これは、プロジェクト構造を変更する際に私が見つけた最も簡単な方法されていないオプションです。お役に立てれば。

+0

男、あなたは私の命を救った!それはうまくいきました。ありがとう! –

0

あなたの変換には他の方法はありません。あなたが知っているように、これらのシナリオでは、マーシャラーがベストプラクティスです。 JAXBを使う方が良い。

関連する問題