5

私は、WSDL から Java を生成するというwsdl2java目標を使用しています。cxf-codegen-plugin次に、私のテストでは、JAXB.unmarshal() を使用して、生の Web サービス XML 結果からクラスを生成します。

典型的な例はGetAllResponseType response = unmarshal("get-all.xml", GetAllResponseType.class)、次の方法を使用した です。

<T> T unmarshal(String filename, Class<T> clazz) throws Exception {
    InputStream body = getClass().getResourceAsStream(filename);
    return javax.xml.bind.JAXB.unmarshal(body, clazz);
}

問題は次のとおりです。生の XML 応答には、wsdl2java によってクラスとして生成されない Envelope タグと Body タグが常に含まれています。

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

したがって、JAXB.unmarshal() を使用するには、

  1. get-all.xml で周囲の Envelope/Body タグを手動で取り除くか
  2. または getAllResponse ノードを抽出し、それを InputStream に再変換します
  3. または Envelope クラスと Body クラスを作成します

現在私は2を行っていますが、それは多くのコードです:

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

私の質問は次のとおりです。

  • 2で抽出する簡単な方法はありますか? 私はただ正規表現をしたいと思っています。XPath を試してみましたが、どういうわけか動作しませんでした。コード例が役立ちます。
  • Body / Envelope クラス ( 3 )を作成するために wsdl2java を入手できますか、それとも自分で簡単に作成できますか?
4

3 に答える 3

2

ノード内のノードは、「生の」JAXBn4:Bodyを使用してアンマーシャリングできます。XMLStreamReaderUnmarshaller

<T> T unmarshal(String filename, Class<T> clazz) throws Exception {
    XMLInputFactory xif = XMLInputFactory.newFactory();
    XMLStreamReader xsr = xif.createXMLStreamReader(getClass().getResourceAsStream(filename));
    xsr.nextTag();
    while (!xsr.getLocalName().equals("Body")) {
        xsr.nextTag();
    }
    xsr.nextTag();
    Unmarshaller unmarshaller = JAXBContext.newInstance(clazz).createUnmarshaller();
    return unmarshaller.unmarshal(xsr, clazz).getValue();
}

この回答を手伝ってくれた Blaise Doughan に感謝します。

于 2013-06-11T12:07:23.787 に答える
1

StAX を使用しXmlStreamReaderて XML を解析し、それをアンマーシャリングする要素に進め、JAXB 実装でそれをアンマーシャリングすることができますXmlStreamReader

詳細については

于 2013-06-10T09:20:24.653 に答える