您好我正在使用JAXB和Marshal / Unmarshal Schema验证。我有一个XML文件和XSD架构用于验证。代码是这样的:
Validation.java
try{
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new File("./src/main/resources/validation.xsd"));
JAXBContext jc = JAXBContext.newInstance(AddCustomer.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setSchema(schema);
unmarshaller.setEventHandler(new MyValidationEventHandler());
AddCustomer addCustomer_Validation= (AddCustomer) unmarshaller.unmarshal(new File("./src/main/resources/AddCustomer.xml"));
logger.info("AddCustomer passed validation.");
} catch(UnmarshalException ex) {
logger.info("linked ex: " + ex.getLinkedException().toString());
String str = ex.getLinkedException().toString();
int lineNumberIndex = str.indexOf("lineNumber:");
int lineNumber = Integer.parseInt(str.substring(lineNumberIndex+12,lineNumberIndex+13));
logger.info("lineNumber:" +lineNumber);
int columnIndex = str.indexOf("columnNumber:");
int columNumber = Integer.parseInt(str.substring(columnIndex+14,columnIndex+16));
logger.info("columnNumber: " + columNumber);
}
某些XML文件是这样的:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AddCustomer xmlns="http://...">
<Customer>
<DirectoryInformation>
<PortalID>32 4 5</PortalID>
<AccountID>2732</AccountID>
从上面的代码中,我可以验证XML对XSD是否有效。记录器文件是这样的:
INFO [main] Validation- linked ex: org.xml.sax.SAXParseException; systemId: file:/C:.../src/main/resources/AddCustomer.xml; lineNumber: 5; columnNumber: 41; cvc-pattern-valid: Value '32 4 5' is not facet-valid with respect to pattern '[ !-~]*' for type 'an..35'.
INFO [main] Validation- lineNumber: 5
INFO [main] Validation- columnNumber: 41
验证是正确的,在xml文件中,PortalID的值对XSD架构无效,日志文件可以告诉我位置是“lineNumber 5和ColumNumber 41”,这正是PortalID的位置。
但我想要的是使用此 lineNumber 5和ColumNumber 41 打印输出XML中的元素 PortalID 无效。有没有办法做到这一点? 非常感谢你!
答案 0 :(得分:0)
要获取解析的最后一个元素的名称,可以放置一个自定义ContentHandler,记录SAXParser和JAXB处理程序之间的最后一个元素。
为此,您必须使用SAXSource并创建扩展XMLFilter的自定义XMLFilterImpl实施
SAXSource
传递给Unmarshaller
而不是File
,并SAXSource
配置XMLReader
。这在Unmarshalling from a javax.xml.transform.sax.SAXSource using a client specified validating SAX2.0 parser 请勿使用&#34; real&#34;配置SAXSource
{JACadoc链接代码中的XMLReader
实现,但使用包含&#34; real&#34;的自定义XMLFilter。 XMLReader
。
XMLReader xmlReader = saxParser.getXMLReader();
RecordingXMLFilter xmlFilter = new RecordingXMLFilter(xmlReader);
SAXSource source =
new SAXSource(xmlFilter, new InputSource(new FileInputStream(new File("./src/main/resources/AddCustomer.xml")));
自定义过滤器RecordingXMLFilter
可以是:
private static final class RecordingXMLFilter extends XMLFilterImpl
{
String lastElement;
private RecordingXMLFilter(XMLReader parent)
{
super(parent);
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
{
lastElement = qName;
super.startElement(uri, localName, qName, attributes);
}
}
xmlFilter.lastElement
来获取解析的最后一个元素的QName。 BTW要以这种方式获取行号,消息可能在不同的语言环境中有所不同,或者在不同版本之间发生变化。
try
{
..........
}
catch(UnmarshalException ex) {
Throwable linked = ex.getLinkedException();
if (linked instanceof SAXParseException)
{
SAXParseException t = (SAXParseException) linked;
int lineNumber = t.getLineNumber();
int columNumber = t.getColumnNumber();
logger.info("lineNumber:" +lineNumber);
logger.info("columnNumber: " + columNumber);
}
}