Was ist die einfachste Möglichkeit zum extrahieren von XML-Knoten für JAXB.unmarshal()?
Ich die wsdl2java
Ziel cxf-codegen-plugin
zum generieren von Java aus einer WSDL. Dann, in meinen tests, ich benutze JAXB.unmarshal() Auffüllen von Klassen aus einem raw-webservice-XML-Ergebnis.
Ein typisches Beispiel ist GetAllResponseType response = unmarshal("get-all.xml", GetAllResponseType.class)
mithilfe der folgenden Methode:
<T> T unmarshal(String filename, Class<T> clazz) throws Exception {
InputStream body = getClass().getResourceAsStream(filename);
return javax.xml.bind.JAXB.unmarshal(body, clazz);
}
Das problem ist dieses: Die rohe XML-Antwort immer umhüllen Envelope-und Body-tags generiert werden und nicht als Klassen von wsdl2java:
<n4:Envelope xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:n="http://www.informatica.com/wsdl/"
xmlns:n4="http://schemas.xmlsoap.org/soap/envelope/" xmlns:n5="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<n4:Body>
<n:getAllResponse xmlns:n="http://www.informatica.com/wsdl/">
<n:getAllResponseElement>
...
</n:getAllResponseElement>
</n:getAllResponse>
</n4:Body>
</n4:Envelope>
So, in Reihenfolge zu verwenden, JAXB.unmarshal() ich
- entweder Streifen entfernt die umliegenden Envelope/Body-tags manuell in get-all.xml
- oder extrahieren Sie die getAllResponse Knoten und re-konvertieren es in ein InputStream
- oder erstellen Sie den Umschlag und Körper-Klassen
Derzeit mache ich 2, aber es ist eine Menge code:
<T> T unmarshal(String filename, Class<T> clazz) throws Exception {
InputStream is = getClass().getResourceAsStream(filename);
InputStream body = nodeContent(is, "n4:Body");
return javax.xml.bind.JAXB.unmarshal(body, clazz);
}
InputStream nodeContent(InputStream is, String name) throws Exception {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(is);
Node node = firstNonTextNode(doc.getElementsByTagName(name).item(0).getChildNodes());
return nodeToStream(node);
}
Node firstNonTextNode(NodeList nl) {
for (int i = 0; i < nl.getLength(); i++) {
if (!(nl.item(i) instanceof Text)) {
return nl.item(i);
}
}
throw new RuntimeException("Couldn't find nontext node");
}
InputStream nodeToStream(Node node) throws Exception {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Source xmlSource = new DOMSource(node);
Result outputTarget = new StreamResult(outputStream);
TransformerFactory.newInstance().newTransformer().transform(xmlSource, outputTarget);
return new ByteArrayInputStream(outputStream.toByteArray());
}
Meine Fragen sind:
- Gibt es ein einfacher Weg, um die Extraktion in 2? Ich bin geneigt, einfach ein regexp. Ich habe versucht, XPath, aber irgendwie konnte ich es nicht zu funktionieren. Code-Beispiele wären hilfreich.
- Kann ich wsdl2java zu erstellen, die die Körper - /Umschlag-Klassen (3), oder ist es einfach zu erstellen Sie selbst?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den Knoten innerhalb der
n4:Body
Knoten kann unmarshallt durch die VerwendungXMLStreamReader
und die "raw" JAXBUnmarshaller
:Dank Blaise Doughan für die Hilfe auf diese Antwort.
Können Sie einen StAX
XmlStreamReader
zum Parsen der XML dann Voraus, dass das element, das Sie möchten unmarshal-und die haben Ihre JAXB-Implementierung unmarshal, dassXmlStreamReader
.Weitere Informationen
Verwenden Sie die
DOMSource
übergeben einen Knoten als Eingabe. Die folgende Methode dauertorg.w3c.dom.Node
als Eingabe und gibt die unmarshallt Klasse.