如何将XML请求附加到SOAP主体的唯一SOAPElement子级?

时间:2019-02-20 09:27:39

标签: java xml soap

用例

我需要以编程方式联系外部SOAP服务。为此,我需要创建一个如下所示的SOAP请求:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:pric="http://myURI/">
   <soapenv:Header/>
   <soapenv:Body>
      <pric:myAPI>
        <XmlDocument>
            <OtherXmlContent>
            </OtherXmlContent>
        </XmlDocument>
      </pric:myAPI>
   </soapenv:Body>
</soapenv:Envelope>

我受阻的任务

我设法创建以下SOAP信封:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:pric="http://myURI/">
   <soapenv:Header/>
   <soapenv:Body>
      <pric:myAPI>

      </pric:myAPI>
   </soapenv:Body>
</soapenv:Envelope>

提供输入,我需要做的是添加XML请求:

<XmlDocument>
    <OtherXmlContent>
    </OtherXmlContent>
</XmlDocument>

...作为<pric:myAPI>的孩子,这是我<soapenv:Body>的唯一孩子。

有关信息,上述Soap信封(尚无XmlDocument)是由以下代码创建的:

MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope envelope = soapPart.getEnvelope();
envelope.addNamespaceDeclaration(pricingNamespace, pricingNamespaceURI);
SOAPBody soapBody = envelope.getBody();
SOAPElement pricingWrapper = soapBody.addChildElement(pricingAction, pricingNamespace);

...因此,我需要做的是将一个孩子附加到pricingWrapper上。我选择如何创建这个孩子,我完全控制生成这个孩子的功能:

private static String createXmlProductFromDealingDocument(Document dealings) 

尝试1-将文档添加为文本

我尝试将XmlDocument添加为pricingWrapper的文本。 这是我的方法:

pricingWrapper.addTextNode(createXmlProductFromDealingDocument(dealingFile));

但是,问题是,<中呈现为>的{​​{1}}的所有字符XmlDocumentString都被方法addTextNode转义。换句话说,我可以看到我的身体内容正确,但是<替换为&lt;>替换为&gt;,因此使SOAP请求对于目标服务。

尝试2-将文档添加为子节点

我所做的另一种尝试是从函数中返回Node而不是String

private static Node createXmlProductFromDealingDocument(Document dealings) 

并将此Node附加为pricingWrapper的子代:

pricingWrapper.appendChild(createXmlProductFromDealingDocument(dealingFile));

上面引发了一个类型异常:

  

org.w3c.dom.DOMException:WRONG_DOCUMENT_ERR:一个节点在与创建它的节点不同的文档中使用。

好的,很公平。昨天,我发布了一个问题(由于想进一步深入研究而删除),一位用户在评论中建议我,以检查如何通过引用this answer来克隆DOM节点。

我尝试这样做,如下所示:

Node pricingRequest = createXmlProductFromDealingDocument(dealingFile);
Node soapPricingRequest = pricingRequest.cloneNode(true);
pricingWrapper.getOwnerDocument().adoptNode(soapPricingRequest);
pricingWrapper.appendChild(soapPricingRequest);

但是,这引发了一个新的异常:

  

org.w3c.dom.DOMException:NOT_SUPPORTED_ERR:该实现不支持所请求的对象或操作类型。

...在以下行上:

pricingWrapper.getOwnerDocument().adoptNode(soapPricingRequest);

...而且我真的不知道我可以怎样追加孩子而不是上面的工作。

我的问题是什么

我只是想以正确的方式完成我的SOAP请求。我不希望通过将XML作为文本或Node注入的方式来完成此操作,只要适当的方式,尤其是在可行的范围内:) 谁能给我小费我如何解决以上问题?

1 个答案:

答案 0 :(得分:1)

读取acceptNode()的javadoc:

  

DOMException-NOT_SUPPORTED_ERR:如果源节点的类型为DOCUMENT,DOCUMENT_TYPE,则引发。 “

因此,您可以检查soapPrincingRequest是否确实是DOCUMENT类型的节点(使用getNodeType())吗?

如果是这样,我建议您将soapPrincingRequest转换为Document,然后使用NODE访问其根getDocumentElement(),并尝试adopt() NODE,而不是DOCUMENT

XML API在争取正确性时总是很难使用,Document及其root element之间的区别实际上很重要。因此,这有点痛苦,但是我们最终还是做到了。