我有一个 xsd 文件和一个 xml 文件,我正在使用以下代码根据 xsd 文件验证 xml 文件
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);
factory.setAttribute(
"http://java.sun.com/xml/jaxp/properties/schemaLanguage",
"http://www.w3.org/2001/XMLSchema");
factory.setAttribute(
"http://java.sun.com/xml/jaxp/properties/schemaSource",
new InputSource(new StringReader(xsd)));
Document doc = null;
try {
DocumentBuilder parser = factory.newDocumentBuilder();
MyErrorHandler errorHandler = new MyErrorHandler();
parser.setErrorHandler(errorHandler);
doc = parser.parse(new InputSource(new StringReader(xml)));
return true;
} catch (ParserConfigurationException e) {
System.out.println("Parser not configured: " + e.getMessage());
} catch (SAXException e) {
System.out.print("Parsing XML failed due to a "
+ e.getClass().getName() + ":");
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println("IOException thrown");
e.printStackTrace();
}
return false;
MyErrorHanlder 是
private static class MyErrorHandler implements ErrorHandler {
public void warning(SAXParseException spe) throws SAXException {
System.out.println("Warning: " + spe.getMessage() + " getColumnNumber is " + spe.getColumnNumber() + " getLineNumber " + spe.getLineNumber() + " getPublicId " + spe.getPublicId() + " getSystemId " + spe.getSystemId());
}
public void error(SAXParseException spe) throws SAXException {
System.out.println("Error: " + spe.getMessage() + " getColumnNumber is " + spe.getColumnNumber() + " getLineNumber " + spe.getLineNumber() + " getPublicId " + spe.getPublicId() + " getSystemId " + spe.getSystemId());
throw new SAXException("Error: " + spe.getMessage());
}
public void fatalError(SAXParseException spe) throws SAXException {
System.out.println("Fatal Error: " + spe.getMessage() + " getColumnNumber is " + spe.getColumnNumber() + " getLineNumber " + spe.getLineNumber() + " getPublicId " + spe.getPublicId() + " getSystemId " + spe.getSystemId());
throw new SAXException("Fatal Error: " + spe.getMessage());
}
}
当 xml 不符合 xsd 时,我得到一个异常..但是这个异常没有 xsd 元素的名称,因为它发生了这个错误..消息看起来像
由于 org.xml.sax.SAXException:Error: cvc-minLength-valid: Value '' with length = '0' is not facet-valid respect to minLength '1' for type 'null '.
错误消息没有打印 xsd 元素的名称,而是只有 ''。因此,我无法找到并(向用户)显示导致错误的确切元素。
我的 xsd 元素看起来像这样
<xs:element name="FullName_FirstName">
<xs:annotation>
<xs:appinfo>
<ie:label>First Name</ie:label>
<ie:html_element>0</ie:html_element>
</xs:appinfo>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
提前致谢
最佳答案
首先,一些建议。您不需要仅仅为了进行验证而构建 DOM 文档。这会导致大量内存开销,甚至可能会耗尽大量输入 XML 文档。您可以只使用 SAXParser
。如果您使用的是 Java 1.5 或更高版本,那甚至没有必要。从那个版本开始,Java SE 中包含了一个 XML 验证 API。检查包裹javax.xml.validation获取更多信息。这个想法是,您首先构建一个 Schema
对象,然后从中获取一个可用于执行验证的 Validator
。它接受任何 Source
实现作为输入。还可以为 validator 提供 ErrorHandlers
,这样您就可以重用您的类。当然,您实际上可能需要一个 DOM,但在这种情况下,最好创建一个 Schema
实例并将其注册到您的 DocumentBuilderFactory
。
现在,针对实际问题。这并不完全容易,因为 SAXParseException
没有为您提供很多上下文信息。最好的办法是在某处连接一个 ContentHandler
并跟踪您所在的元素或其他一些位置信息。然后,您可以在需要时将其提供给错误处理程序。 DefaultHandler
或 DefaultHandler2
类是结合错误和内容处理的便捷方式。您将在包 org.xml.sax.ext 中找到这些类。
我整理了一个测试,我将在下面发布。现在,我确实得到了两行输出而不是预期的输出。如果这是因为我正在使用架构,或者因为我没有抛出异常并继续处理,我不确定。第二行确实包含元素的名称,所以这可能就足够了。您可以在错误上设置一些标志,而不是抛出异常并结束解析。
package jaxb.test;
import java.io.StringReader;
import javax.xml.XMLConstants;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
public class ValidationTest {
public static void main(String[] args) throws Exception {
//Test XML and schema
final String xml = "<?xml version=\"1.0\"?><test><test2></test2></test>";
final String schemaString =
"<?xml version=\"1.0\"?>"
+ "<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" elementFormDefault=\"unqualified\" attributeFormDefault=\"unqualified\">"
+ "<xsd:element name=\"test\" type=\"Test\"/>"
+ "<xsd:element name=\"test2\" type=\"Test2\"/>"
+ "<xsd:complexType name=\"Test\">"
+ "<xsd:sequence>"
+ "<xsd:element ref=\"test2\" minOccurs=\"1\" maxOccurs=\"unbounded\"/>"
+ "</xsd:sequence>"
+ "</xsd:complexType>"
+ "<xsd:simpleType name=\"Test2\">"
+ "<xsd:restriction base=\"xsd:string\"><xsd:minLength value=\"1\"/></xsd:restriction>"
+ "</xsd:simpleType>"
+ "</xsd:schema>";
//Building a Schema instance
final Source schemaSource =
new StreamSource(new StringReader(schemaString));
final Schema schema =
SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(schemaSource);
//Creating a SAXParser for our input XML
//First the factory
final SAXParserFactory factory = SAXParserFactory.newInstance();
//Must be namespace aware to receive element names
factory.setNamespaceAware(true);
//Setting the Schema for validation
factory.setSchema(schema);
//Now the parser itself
final SAXParser parser = factory.newSAXParser();
//Creating an instance of our special handler
final MyContentHandler handler = new MyContentHandler();
//Parsing
parser.parse(new InputSource(new StringReader(xml)), handler);
}
private static class MyContentHandler extends DefaultHandler {
private String element = "";
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if(localName != null && !localName.isEmpty())
element = localName;
else
element = qName;
}
@Override
public void warning(SAXParseException exception) throws SAXException {
System.out.println(element + ": " + exception.getMessage());
}
@Override
public void error(SAXParseException exception) throws SAXException {
System.out.println(element + ": " + exception.getMessage());
}
@Override
public void fatalError(SAXParseException exception) throws SAXException {
System.out.println(element + ": " + exception.getMessage());
}
public String getElement() {
return element;
}
}
}
这有点粗糙,但您可以从这里开始工作以获得您需要的东西。
关于java - XSD 验证中的 SaxParseException 未提供元素名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7113219/