gpt4 book ai didi

java - 为 JAXB.unmarshal() 提取 XML 节点的最简单方法是什么?

转载 作者:搜寻专家 更新时间:2023-10-31 20:12:47 24 4
gpt4 key购买 nike

我使用 cxf-codegen-pluginwsdl2java 目标从 WSDL 生成 Java。然后,在我的测试中,我使用 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 响应总是包含封闭的 Envelope 和 Body 标记,它们不是由 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>

所以,为了使用 JAXB.unmarshal() 我必须

  1. 在 get-all.xml 中手动去除周围的信封/正文标签
  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,但不知何故我无法让它工作。代码示例会有所帮助。
  • 我可以使用 wsdl2java 来创建 Body/Envelope 类 (3),还是我自己创建它们很容易?

最佳答案

使用DOMSource 将节点作为输入传递。以下方法将 org.w3c.dom.Node 作为输入并返回未编码的类。

private <T> T unmarshal(Node node, Class<T> clazz) throws JAXBException {
XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
Source xmlSource = new DOMSource(node);
Unmarshaller unmarshaller = JAXBContext.newInstance(clazz).createUnmarshaller();
return unmarshaller.unmarshal(xmlSource, clazz).getValue();
}

关于java - 为 JAXB.unmarshal() 提取 XML 节点的最简单方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17018714/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com