【问题标题】:SOAP message with javax.xml.soap - namespace error?带有 javax.xml.soap 的 SOAP 消息 - 命名空间错误?
【发布时间】:2011-08-22 13:18:25
【问题描述】:

以下是我应该从我的 Java Web 应用程序调用的 .NET Web 服务的通用示例 SOAP 请求:

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
 <soap:Body>
  <setAMRequestData xmlns="http://tempuri.org/">
    <id>int</id>
  </setAMRequestData>
 </soap:Body>
</soap:Envelope>

我可以使用这个代码段从 java 控制台应用程序生成类似的东西:

import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
...
SOAPConnectionFactory sfc = SOAPConnectionFactory.newInstance();
SOAPConnection connection = sfc.createConnection();
MessageFactory mf = MessageFactory.newInstance();
SOAPMessage sm = mf.createMessage();

SOAPHeader sh = sm.getSOAPHeader();
SOAPBody sb = sm.getSOAPBody();
sh.detachNode();

QName bodyName = new QName("http://tempuri.org/", "setAMRequestData", XMLConstants.DEFAULT_NS_PREFIX);
SOAPBodyElement bodyElement = sb.addBodyElement(bodyName);
QName n = new QName("id");                                          
SOAPElement quotation = bodyElement.addChildElement(n);
quotation.addTextNode("121152");

结果是以下 XML:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
 <SOAP-ENV:Body>
  <setAMRequestData xmlns="http://tempuri.org/">
   <id>121152</id>
  </setAMRequestData>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

这会调用服务。接下来,我使用 soapUI 来尝试调用该服务,它从 WSDL 生成了类似这样的肥皂消息(它与之前在信封中的命名空间声明中不同,以及前缀):

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:tem="http://tempuri.org/">
 <soapenv:Header/>
  <soapenv:Body>
   <tem:setAMRequestData>
     <tem:id>?</tem:id>
   </tem:setAMRequestData>
  </soapenv:Body>
 </soapenv:Envelope>

这也适用于soapUI。但最后,当我尝试使用此代码序列重新创建这种形式的肥皂消息时:

// factories and stuff, like in the example above
SOAPPart part = sm.getSOAPPart();
SOAPEnvelope envelope = part.getEnvelope();
envelope.addNamespaceDeclaration("tem", "http://tempuri.org/");

SOAPHeader sh = sm.getSOAPHeader();
SOAPBody sb = sm.getSOAPBody();
sh.detachNode();

QName bodyName = new QName(null, "setAMRequestData", "tem");
SOAPBodyElement bodyElement = sb.addBodyElement(bodyName);
QName n = new QName(null, "id", "tem");
SOAPElement quotation = bodyElement.addChildElement(n);
quotation.addTextNode("7028");

我在 SOAPElement quote = bodyElement.addChildElement(n); 行中遇到了以下异常:

org.w3c.dom.DOMException: NAMESPACE_ERR: 试图以不正确的命名空间方式创建或更改对象。

无论我如何尝试,我根本无法为 id 元素设置“tem”前缀......这是怎么回事?

谢谢。

【问题讨论】:

    标签: java asp.net web-services soap soapui


    【解决方案1】:

    您正在将命名空间 uri 绑定到前缀,然后尝试创建一个具有相同前缀但具有空命名空间 uri 的元素:

    envelope.addNamespaceDeclaration("tem", "http://tempuri.org/");
    ...
    QName bodyName = new QName(null, "setAMRequestData", "tem");
    

    元素由命名空间 uri 和本地名称的组合来标识。要解决这个问题,您必须在您创建的每个元素上指定命名空间:

    QName bodyName = new QName("http://tempuri.org/", "setAMRequestData", "tem");
    ...
    QName n = new QName("http://tempuri.org/", "id", "tem");
    

    【讨论】:

    • 是的,这解决了它。显然我遇到了一些 javax.xml.soap 使用的坏例子......谢谢。
    【解决方案2】:

    不要大惊小怪,因为从您的应用发出的 XML 看起来与 SoapUI 发出的请求并不完全相同(尤其是带有命名空间前缀)。将您的代码粘贴到 SoapUI 请求中,右键单击,重新格式化,然后查看 SoapUI 是否理解您的内容(如果您有专业版,请在表单和大纲视图中检查它)。如果看起来没问题,将其关闭并查看是否得到与本机(soapUI)请求相同的响应。如果是这样,你很高兴去。然而,如果事情在错误的地方,命名空间被破坏,SoapUI 无法呈现您的 XML,那么您需要在代码中进行一些调整。

    【讨论】:

    • 来自我的应用程序的 XML 和由 soapUI 生成的 XML 之间的唯一区别现在是信封前缀(SOAP-ENV 与 soapenv),但该前缀的 URI 在两种情况下都是相同的。根据我阅读的内容,只要 URI 相同,前缀应该是无关紧要的?
    • 正确。只要前缀引用相同的 URI,就可以了。
    猜你喜欢
    • 1970-01-01
    • 2013-11-18
    • 1970-01-01
    • 2015-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多