java - marshal - ¿Cómo separar la respuesta SOAP usando JAXB si la declaración del espacio de nombres está en el sobre SOAP?
marshaller java example (2)
Podría analizar todo el mensaje SOAP utilizando un analizador DOM, que podría resolver todos los espacios de nombres en tiempo de análisis. A continuación, extraiga el elemento que necesita del árbol DOM resultante y páselo al unmarshaller.
DomDemo
package forum11465653;
import java.io.File;
import javax.xml.bind.*;
import javax.xml.parsers.*;
import javax.xml.transform.dom.DOMSource;
import org.w3c.dom.*;
public class DomDemo {
public static void main(String[] args) throws Exception{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document d = db.parse(new File("src/forum11465653/input.xml"));
Node getNumberResponseElt = d.getElementsByTagNameNS("http://example.com/", "getNumberResponse").item(0);
JAXBContext jc = JAXBContext.newInstance(Response.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement<Response> je = unmarshaller.unmarshal(new DOMSource(getNumberResponseElt), Response.class);
System.out.println(je.getName());
System.out.println(je.getValue());
}
}
Salida
{http://example.com/}getNumberResponse
forum11465653.Response@19632847
JAXB solo puede deshacer un XML si el sobre de jabón ya se ha eliminado. Sin embargo, la respuesta SOAP que trato de deshacer tiene su declaración de espacio de nombres en el sobre del jabón. Si elimino el sobre de jabón, también se eliminará la declaración del espacio de nombres. Como tal, el prefijo de las etiquetas se referirá a none. Esto hace que JAXB arroje un error. ¿Cómo puedo deshacer una respuesta SOAP utilizando JAXB si el espacio de nombres está declarado en el sobre SOAP?
Una muestra similar del XML que necesito deshacer es la siguiente:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://example.com/">
<soapenv:Body>
<ns:getNumberResponse>
<number>123456789</number>
</ns:getNumberResponse>
</soapenv:Body>
</soapenv:Envelope>
Esto es lo que sucede si elimino el sobre de jabón:
<ns:getNumberResponse>
<number>123456789</number>
</ns:getNumberResponse>
Si eliminé el sobre del jabón, la declaración del espacio de nombres también desaparecerá. JAXB no podrá deshacer el xml anterior porque falta la definición de espacio de nombres para el prefijo "ns". Como tal, devolverá un "The prefix "ns" for element "ns:getNumberResponse" is not bound."
mensaje de error. ¿Cómo lo arreglo?
Tenga en cuenta que estoy usando JDK 1.5. No estoy seguro si hay una manera de resolver esto en JDK 1.6. Pude usar JAXB porque descargué los archivos necesarios para usar JAXB.
Puede usar un analizador StAX para analizar el mensaje SOAP y luego avanzar el XMLStreamReader
al elemento getNumberResponse
y usar el método unmarshal que toma un parámetro de clase. Un analizador StAX está incluido en Java SE 6, pero deberá descargar uno para Java SE 5. Woodstox es un analizador StAX popular.
Respuesta
package forum11465653;
public class Response {
private long number;
public long getNumber() {
return number;
}
public void setNumber(long number) {
this.number = number;
}
}
Manifestación
Un XMLStreamReader
tiene un NamespaceContext
. NamespaceContext
conoce todas las declaraciones activas del espacio de nombres para el nivel actual. Su implementación JAXB (JSR-222) podrá aprovechar esto para obtener la información necesaria.
package forum11465653;
import java.io.FileReader;
import javax.xml.bind.*;
import javax.xml.stream.*;
public class Demo {
public static void main(String[] args) throws Exception{
XMLInputFactory xif = XMLInputFactory.newFactory();
XMLStreamReader xsr = xif.createXMLStreamReader(new FileReader("src/forum11465653/input.xml"));
xsr.nextTag(); // Advance to Envelope tag
xsr.nextTag(); // Advance to Body tag
xsr.nextTag(); // Advance to getNumberResponse tag
System.out.println(xsr.getNamespaceContext().getNamespaceURI("ns"));
JAXBContext jc = JAXBContext.newInstance(Response.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement<Response> je = unmarshaller.unmarshal(xsr, Response.class);
System.out.println(je.getName());
System.out.println(je.getValue());
}
}
Salida
http://example.com/
{http://example.com/}getNumberResponse
forum11465653.Response@781f6226