首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >XSD验证中的SaxParseException未提供元素名称

XSD验证中的SaxParseException未提供元素名称
EN

Stack Overflow用户
提问于 2011-08-19 03:46:19
回答 1查看 11.4K关注 0票数 2

我有一个xsd文件和一个xml文件,我使用以下代码根据xsd文件验证xml文件

代码语言:javascript
复制
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是

代码语言:javascript
复制
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元素的名称,导致此错误的原因。消息看起来像这样

分析XML失败,因为org.xml.sax.SAXException:Error: cvc- minLength -valid:长度为'0‘的值'’相对于类型'null‘的minLength '1’不是方面有效的。

错误消息只有'‘,而不是打印xsd元素的名称。正因为如此,我无法找到并(向用户)显示导致错误的确切元素。

我的xsd元素如下所示

代码语言:javascript
复制
<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>

提前感谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-08-19 05:21:52

首先,我要提一些建议。您不需要仅仅为了进行验证而构建DOM文档。这会导致大量的内存开销,甚至可能会耗尽大型输入XML文档。你可以只使用SAXParser。如果您使用的是Java1.5或更高版本,则甚至不需要这样做。从该版本开始,Java SE中就包含了XML验证API。有关更多信息,请查看package javax.xml.validation。其思想是,首先构建一个Schema对象,然后从中获取一个可用于进行验证的Validator。它接受任何Source实现作为输入。验证器也可以被赋予ErrorHandlers,所以你可以重用你的类。当然,也有可能您实际上需要一个DOM,但在这种情况下,最好创建一个Schema实例并将其注册到您的DocumentBuilderFactory中。

现在,来看一下实际的问题。这并不完全容易,因为SAXParseException没有为您提供太多的上下文信息。你最好的办法是在某个地方挂上一个ContentHandler,并记录你所在的元素,或者其他一些位置信息。然后,您可以在需要时将其提供给错误处理程序。类DefaultHandlerDefaultHandler2是一种组合错误和内容处理的便捷方法。您可以在org.xml.sax.ext包中找到这些类。

我已经做了一个测试,我将在下面发布。现在,我确实得到了两行输出,而不是预期的一行。如果这是因为我正在使用Schema,或者因为我没有抛出异常并继续处理,我不确定。第二行确实包含元素的名称,因此这可能就足够了。您可以在错误上设置一些标志,而不是抛出异常并结束解析。

代码语言:javascript
复制
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;
        }

    }

}

这有点困难,但你可以从这里开始工作,以获得你需要的东西。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7113219

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档