Вариант использования
Мне нужно связаться с внешней службой 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>
, который является единственным дочерним элементомmy <soapenv:Body>
.
Для информации вышеупомянутый Мыльный конверт (пока не 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));
Проблема, однако, состоит в том, что все символы <
и >
XmlDocument
, отображаемые как String
, экранируются методом addTextNode
.Другими словами, я вижу, что мое тело имеет правильное содержимое, но <
заменяется на <
, а >
заменяется на >
, что делает запрос SOAP недействительным для целевой службы.
Попытка 2 - добавление документа в качестве дочернего узла
Другая попытка, которую я сделал, - вернуть Node
вместо String
из моей функции:
private static Node createXmlProductFromDealingDocument(Document dealings)
и добавьте это Node
как потомок pricingWrapper
:
pricingWrapper.appendChild(createXmlProductFromDealingDocument(dealingFile));
Выше приведено исключение типа:
org.w3c.dom.DOMException: WRONG_DOCUMENT_ERR: Узел используется в документе, отличном от того, который его создал.
Хорошо, достаточно справедливо.Вчера я опубликовал вопрос (вскоре удаленный, поскольку я хотел углубиться в свои исследования), и пользователь любезно предложил мне в комментарии проверить, как клонировать узлы 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
, насколько это правильно и особенно, насколько это работает :) Кто-нибудь, пожалуйста, напишите мне, как я могу исправить мойвышеуказанные вопросы?