Получить значение из недействительного SOAP 1.1 Сообщение с Java - PullRequest
4 голосов
/ 05 мая 2020

Мой предыдущий вопрос был закрыт и помечен как повторяющийся, но предложенный ответ не отвечает на мою проблему, и, как было предложено, я задаю новый вопрос.

Давайте работать с предложенным ответом .

Вот код:

String strMsg = "<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\">" +
              " <soap:Header>" +
              "  <context xmlns=\"urn:zimbra\"/>" +
              " </soap:Header>" +
              " <soap:Body>" +
              "  <soap:Fault>" +
              "   <soap:Code>" +
              "    <soap:Value>soap:Sender</soap:Value>" +
              "   </soap:Code>" +
              "   <soap:Reason>" +
              "    <soap:Text>no valid authtoken present</soap:Text>" +
              "   </soap:Reason>" +
              "   <soap:Detail>" +
              "    <Error xmlns=\"urn:zimbra\">" +
              "     <Code>service.AUTH_REQUIRED</Code>" +
              "     <Trace>qtp1027591600-6073:1588614639199:4eacbd0257a457b6</Trace>" +
              "    </Error>" +
              "   </soap:Detail>" +
              "  </soap:Fault>" +
              " </soap:Body>" +
              "</soap:Envelope>";

      InputStream is = new ByteArrayInputStream(strMsg.getBytes());
      XMLInputFactory xif = XMLInputFactory.newFactory();
      XMLStreamReader xsr = xif.createXMLStreamReader(is);

      //Envelope
      xsr.nextTag();
      QName name = xsr.getName();

      //Header
      xsr.nextTag();
      name = xsr.getName();

      //Context
      xsr.nextTag();
      name = xsr.getName();

      //Context again
      xsr.nextTag();
      name = xsr.getName();

      //Header again
      xsr.nextTag();
      name = xsr.getName();

      //Body
      xsr.nextTag();
      name = xsr.getName();

      //Fault
      xsr.nextTag();
      name = xsr.getName();

      /* IM COMMENTING THE FOLLOWING CODE BECAUSE I'M INTERESTED IN THE FAULT CONTENT
      * AND EVEN IF IT TRY TO GO DEEPER I CAN'T GO PASS "VALUE" NODE
      *
      //Code
      xsr.nextTag();
      name = xsr.getName();

      //Value
      xsr.nextTag();
      name = xsr.getName();

      //throws exception, no more elements for some reason
      xsr.nextTag();
      name = xsr.getName();
       */

      Transformer transformer = TransformerFactory.newInstance().newTransformer();
      StringWriter stringWriter = new StringWriter();
      transformer.transform(new StAXSource(xsr), new StreamResult(stringWriter));
      StringReader sr = new StringReader(stringWriter.toString());
      JAXBContext jaxbContext = JAXBContext.newInstance(Fault.class);
      Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

      Fault fault = (Fault) unmarshaller.unmarshal(sr); //THROWS EXCEPTION
      //"unexcpected element (URI:"http://www.w3.org/2003/05/soap-envelope", local:"Fault"). Expected elements are <{}Fault>

My Fault class:

  @XmlRootElement(name = "Fault")
  @XmlAccessorType(XmlAccessType.FIELD)
  public static class Fault {
    @XmlElement(name = "Code")
    private String code;
    @XmlElement(name = "Reason")
    private String reason;

    public String getCode() {
      return code;
    }

    public void setCode(String code) {
      this.code = code;
    }

    public String getReason() {
      return reason;
    }

    public void setReason(String reason) {
      this.reason = reason;
    }
  }

Я подозревал, что это не сработает, так как элементы непосредственно внутри "Fault" сами по себе не имеют значений, у них больше элементов внутри, а также все элементы имеют префикс "soap", мой конверт не точно так же, как в предложенном ответе.

Но все же мне не удалось получить узел «Ошибка», так как было выдано исключение:

неожиданный элемент (URI: «http://www.w3.org/2003/05/soap-envelope ", местное:" Неисправность "). Ожидаемые элементы: <{} Fault>

Мне интересно получить значение:

<soap:Text>no valid authtoken present</soap:Text>"

Кроме того, это только для этого типа ошибки, может быть другие ошибки, а также, когда ответ положительный, я получаю совершенно другой ответ.

Что меня действительно интересует, так это найти способ исследовать конверт следующим образом:

//pseudo code
(envelope->body->fault->reason->text != null) {reasonText = envelope->body->fault->reason->text)

Но каким бы способом я ни смог добраться до Reason-> Text, я смогу адаптировать скрипт для других тел.

Заранее спасибо.

1 Ответ

2 голосов
/ 08 мая 2020

Мой друг, который не хотел здесь отвечать, нашел решение, и, что еще лучше, он нашел его, используя способ, которым я хотел:

//pseudo code
(envelope->body->fault->reason->text != null) {reasonText = envelope->body->fault->reason->text)

Для всех, кто в будущем натыкается на эту проблему, вот решение:

String strMsg = "<soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\">" +
              " <soap:Header>" +
              "  <context xmlns=\"urn:zimbra\"/>" +
              " </soap:Header>" +
              " <soap:Body>" +
              "  <soap:Fault>" +
              "   <soap:Code>" +
              "    <soap:Value>soap:Sender</soap:Value>" +
              "   </soap:Code>" +
              "   <soap:Reason>" +
              "    <soap:Text>no valid authtoken present</soap:Text>" +
              "   </soap:Reason>" +
              "   <soap:Detail>" +
              "    <Error xmlns=\"urn:zimbra\">" +
              "     <Code>service.AUTH_REQUIRED</Code>" +
              "     <Trace>qtp1027591600-6073:1588614639199:4eacbd0257a457b6</Trace>" +
              "    </Error>" +
              "   </soap:Detail>" +
              "  </soap:Fault>" +
              " </soap:Body>" +
              "</soap:Envelope>";

      strMsg = strMsg.replaceAll("soap:",""); //Had to replace soap:, not fancy but it works.

      is = new ByteArrayInputStream(strMsg.getBytes());
      InputSource xml = new InputSource(is);

      XPath xPath = XPathFactory.newInstance().newXPath();
      Object exprEval = xPath.compile("/Envelope/Body/Fault/Reason/Text/text()").evaluate(xml, XPathConstants.STRING);
      if ( exprEval != null ) {
        System.out.println( "Fault reason text: " + exprEval );
        // This prints what's expected:
        // Fault reason text: no valid authtoken present
      }

Вот и go.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...