jaxb如何将带有内联模式的XML字符串处理为java对象?
我打电话给WCF。Net服务从Java代理。结果是一个具有内联模式的xml字符串(在流中)。我想使用JAXB将xml中的值解组到Java类。xml字符串如下所示:
<NewDataSet>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:Locale="">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="Table">
<xs:complexType>
<xs:sequence>
<xs:element name="CustomerID" type="xs:int" minOccurs="0" />
<xs:element name="CustomerNme" type="xs:string" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
<Table>
<CustomerID>1111</CustomerID>
<CustomerNme>Customer One</CustomerNme>
</Table>
<Table>
<CustomerID>2222</CustomerID>
<CustomerNme>Customer Two</CustomerNme>
</Table>
</NewDataSet>
由于基本结构将保持不变,我最初的想法是:
- 使用该模式可以使用xjc手动创建JAXB Java类李>
- 在处理过程中,使用嵌入的模式解析xml字符串,并丢弃模式和根节点NewDataSet李>
- 使用JAXB将字符串解组到java对象李>
有更好的方法吗
更新
尝试@Doughans方法。很近,但还没有雪茄。一个复杂的问题是xml被压缩了。下面的代码就是我要做的。我已经将Customer类成员设置为大写,以匹配确切的xml元素,但是对于解组操作的每个实例,我得到的都是null
//everything good to here...
JAXBElement<byte[]> byteRet = searchCustResponse.getSearchCustomersResult();
byte[] gzBytes = byteRet.getValue(); //these are gzipped bytes
//decompress...
ByteArrayInputStream bais = new ByteArrayInputStream(gzBytes);
GZIPInputStream gzipis = new GZIPInputStream(bais);
//InputStreamReader isr = new InputStreamReader(gzipis, "UTF-8");
//convert xml to string...
StringWriter writer = new StringWriter();
IOUtils.copy(gzipis, writer, "UTF-8");
String xmlString = writer.toString();
//read the string...
//StreamSource xml = new StreamSource(xmlString);
Reader reader = new StringReader(xmlString);
XMLInputFactory xif = XMLInputFactory.newFactory();
XMLStreamReader xsr = xif.createXMLStreamReader(reader);
List<WPTSCustomer> wptsCustomers = new ArrayList<WPTSCustomer>();
try {
while (xsr.hasNext()) {
int next = xsr.next();
//xsr.nextTag();
if (next == XMLStreamReader.START_ELEMENT) {
if (xsr.getLocalName().equals("Table")) {
JAXBContext jc = JAXBContext.newInstance(WPTSCustomer.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement<WPTSCustomer> jb = unmarshaller.unmarshal(xsr, WPTSCustomer.class);
WPTSCustomer customer = jb.getValue();
System.out.println(customer.getCustomerID()); //prints null
System.out.println(customer.getCustomerNme()); //prints null
wptsCustomers.add(customer);
}
}
}
} finally {
StreamSource的使用对我不起作用。最后,我对xml字符串进行了遍历,直到它执行解组为止,而解组并没有填充对象
更新2
现在放弃JAXB。下面的代码工作得很好,我将把这些值放到我的POJO中。我确实尝试过从服务返回的完整xml字符串在JDev中创建一个XSD,然后从XSD中创建一个JAXB类。除了来自内联模式的名称冲突外,这几乎起到了作用。也许有办法解决这个问题
int eventType = xsr.getEventType();
while (xsr.hasNext()) {
eventType = xsr.next();
if (xsr.isStartElement() && xsr.getLocalName().equals("Table")) {
xsr.nextTag();
while (xsr.hasNext()) {
if (xsr.isStartElement()) {
if (xsr.getLocalName().equals("CustomerID")) {
System.out.println("id: " + xsr.getElementText());
}
if (xsr.getLocalName().equals("CustomerNme")) {
System.out.println("name: " + xsr.getElementText());
}
}
xsr.next();
}
}
--
# 1 楼答案
我将使用StAX解析整个XML文档,然后将
XMLStreamReader
向下导航到Table
元素,并使用JAXB将其解组了解更多信息
我在我的博客上写了更多关于这个用例的内容:
# 2 楼答案
对于可能再次遇到此问题的人,如果您尝试从xml字符串读取数据,则可能不起作用,但如果您可以在InputStream中获取数据,则可以将其传递给XMLStreamReader,这样就可以了。@Blaise的博客很棒
我使用xjc选择手动创建Javaobject的模式,然后使用XMLStreamReader解析jax rs响应并获取输入流。如果成功,将尝试删除手动步骤并更新post