简体   繁体   中英

Get value from non valid SOAP 1.1 Message with Java

My previous question was closed and marked as duplicate, but the suggested asnwer does not answer my problem, and as suggested, I'm asking a new question.

Let's work with the suggested answer .

Here's the code:

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;
    }
  }

I suspected it wasn't going to work, since the elements directly inside "Fault" don't have values themselves, they have more elements inside, and also all elements are prefixed with "soap", my envelope isn't exactly structured as the one in the suggested answer.

But still, I couldn't fetch the "Fault" node, as an exception was thrown:

unexcpected element (URI:" http://www.w3.org/2003/05/soap-envelope ", local:"Fault"). Expected elements are <{}Fault>

I'm interested in getting the value of:

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

Also, this is only for this type of error, there might be other errors, also, when the answer is positive, I get a whole different response.

What I'm really insterested in is, finding a way to explore the envelope in the following way:

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

But whatever way I'm able to reach Reason->Text will do, then I can adapt script to other bodies.

Thank you in advance.

A friend of mine who didn't want to answer here, found a solution, and even better, he found it using the way I wanted to:

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

For anyone else in the futures who stumbles upon this problem, here it is a solution:

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
      }

There you go.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM