我尝试解组XML以验证某些值。如果特定值无效,我想知道该值来自的那一行。这是我的代码,灵感来自this answer。
ValidationEventHandler可能会遇到一些错误:
public class XmlErrorHandler implements ValidationEventHandler {
// private fields and methods are omitted,constructor is default
@Override
public boolean handleEvent(ValidationEvent event) {
generateReportObjectsForXsdError(event.getMessage(),event.getLocator().getLineNumber());
return true;
}
}
其他人则需要一些逻辑来检测。因此,我为每个反序列化的对象保存XML行号:
public class LocationListener
extends Unmarshaller.Listener {
private XMLStreamReader xsr;
private Map<Object,Location> locations;
public LocationListener(XMLStreamReader xsr) {
super();
this.xsr = xsr;
this.locations = new HashMap<>();
}
@Override
public void beforeUnmarshal(Object target,Object parent) {
locations.put(target,xsr.getLocation());
}
public Map<Object,Location> getLocations() {
return Collections.unmodifiableMap(locations);
}
}
使用以下代码执行解组动作:
public static <T> T xmlToObject(
XMLStreamReader data,Class factory,Unmarshaller.Listener listener,ValidationEventHandler eventHandler,Schema schema) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(factory);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
unmarshaller.setListener(listener);
unmarshaller.setEventHandler(eventHandler);
unmarshaller.setSchema(schema);
return (T)unmarshaller.unmarshal(data);
}
XMLStreamReader数据与listener.xsr是同一对象。
好吧,代码在我的tomcat上就像一个魅力。
问题是,当我使用IBM WebSphere Application Server 8.5.5.10(目标平台)时,我总是在event.getLocator().getLineNumber()
中以XmlErrorHandler.handleEvent()
的形式获得{-1,在{{1 }}。
问题不依赖于JAXB实现。 (我尝试过IBM WAS,eclipce MOXy和Java参考实现)。
所以,我的问题是我应该怎么做才能获得行号?
谢谢
UPD:我知道文档指出xsr.getLocation().getLineNumber()
在没有可用数字行时返回-1。但是,为什么在WAS上不可用呢?