我需要使用SAX解析巨大的xml,并使用jaxb解组单个已知元素。
如果我用List
解组具有@XmlAnyElement(lax=true)
的根bean,一切都很好:已知标签被转换为JAXBContext已知的类,未知标签成为DOM Element
的实例。
但是,如果我跳过根元素并取消编组单个对象,则第一个未知标记会导致unexpected element
异常。如果我使用显式unmarshal()
调用Object.class
,那么即使是已知标签也会变成JAXBElement
。
输出:
<Root>
<Header/>
<Product/>
<Product/>
<Product/>
<Product/>
<Product/>
<Unknown/>
</Root>
class com.common.config.Problem$Header
class com.common.config.Problem$Product
class com.common.config.Problem$Product
class com.common.config.Problem$Product
class com.common.config.Problem$Product
class com.common.config.Problem$Product
Exception in thread "main" javax.xml.bind.UnmarshalException
- with linked exception:
[com.sun.istack.internal.SAXParseException2; lineNumber: 8; columnNumber: 15; unexpected element (uri:"", local:"Unknown"). Expected elements are <{}Header>,<{}Product>]
我希望它回退到JAXBElement
或Element
。可能吗?代码:
import java.io.StringReader;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
//@XmlRootElement(name = "Root")
//@XmlAccessorType(XmlAccessType.FIELD)
public class Problem {
//@XmlAnyElement(lax = true)
//protected final List<Object> accounts = new ArrayList<Object>();
public static void main(final String[] args) throws Exception {
System.err.println(XML);
final JAXBContext jaxbContext = JAXBContext.newInstance(Header.class, Product.class);
final Unmarshaller unm = jaxbContext.createUnmarshaller();
XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(new StringReader(XML));
boolean skipNext = false;
int event = 0;
boolean rootElSkipped = false;
while (reader.hasNext()) {
if (!skipNext) {
event = reader.next();
}
if (event == XMLStreamReader.START_ELEMENT) {
if (rootElSkipped) {
Object obj = unm.unmarshal(reader);
System.err.println(obj.getClass());
} else {
}
rootElSkipped = true;
}
}
}
static final String XML = "<Root>\r\n" + " <Header/>\r\n" + " <Product/>\r\n" + " <Product/>\r\n"
+ " <Product/>\r\n" + " <Product/>\r\n" + " <Product/>\r\n" + " <Unknown/>\r\n" + "</Root>\r\n"
+ "\r\n" + "";
@XmlRootElement(name = "Header")
public static class Header {
}
@XmlRootElement(name = "Product")
public static class Product {
}
}