如何使用失败的xsd验证获取和无效xml文件的元素?

时间:2021-07-02 17:17:02

I am currently using my XSD to Validate my xml. This part works fine my porblem is that I want to obtain the element of the tag /value that is invalid.

我现在使用我的XSD来验证我的xml。这部分工作的很好,我的porblem是我想要获得标签/值的元素无效。

    InputSource is = new InputSource();
    is.setCharacterStream(new StringReader(xml));
    XMLStreamReader reader = null;
    SchemaFactory factory=SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    Schema schema = factory.newSchema(xsdschemalocation);
    Validator validator = schema.newValidator(); 
    try
    {
        reader = XMLInputFactory.newInstance().createXMLStreamReader(new StreamSource(new StringReader(xml)));
    } catch (XMLStreamException ex)
    {
        LogController.getLogger().logSEVERE("Unable to create the streamreader from the xml source", ex.getLocalizedMessage());
        return false;
    }
    try
    {
        validator.validate(new StAXSource(reader));
    }
    catch (IOException ex)
    {
        LogController.getLogger().logSEVERE("IOException in the validatation has been caused as the reader has become null", ex.getLocalizedMessage());
        return false;
    }
catch(SAXException saxe)
    {
        LogController.getLogger().logWARNING("Their is a validation error with the xml", saxe.getLocalizedMessage());
        //*****HERE I WANT THE TAG THAT HAS THE ERROR
        ClientCommunication.ErrorMessageForClient(VALIDATION_ERROR, socket);
        CloseClientConnection();
        return;
    }

The idea I had which is not practical is to look in the message for the word "type" or "end-tag" and get the value after it, however I know this is not going to be good practice! I find this frustrating as I can see the tag that is invalid but can't get hold of it!

我的想法是不实用的,那就是查看“type”或“end-tag”这个词的信息,然后得到它的值,但是我知道这不是很好的练习!我发现这令人沮丧,因为我可以看到标签无效,但无法得到它!

Here are some examples of the element I want

这里有一些我想要的元素的例子。

1. Message: Element type "first" must be followed by either attribute specifications, ">" or "/>".

2. javax.xml.stream.XMLStreamException: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 353; cvc-pattern-valid: Value '079e989989' is not facet-valid with respect to pattern '([0-9])+' for type 'phoneNumber'.

3. Message: The element type "firstLine" must be terminated by the matching end-tag "</firstLine>".

2 个解决方案

#1


12  

Below is a way that you could implement your use case using an ErrorHandler:

下面是一种使用ErrorHandler实现用例的方法:

MyErrorHandler

MyErrorHandler

I would recommend implementing an ErrorHandler that maintained a reference to the XMLStreamReader so that when a SAXParseException occurs you could interrogate the XMLStreamReader to get information about the element. If you want the parsing to stop once an exception is thrown simply rethrow the SAXParseException at the end of each of the methods.

我建议实现一个ErrorHandler,它维护对XMLStreamReader的引用,以便当SAXParseException发生时,您可以查询XMLStreamReader来获取有关元素的信息。如果您希望解析在异常被抛出时停止,那么只需在每个方法的末尾重新抛出SAXParseException。

package forum11921190;

import javax.xml.stream.XMLStreamReader;
import org.xml.sax.*;

public class MyErrorHandler implements ErrorHandler {

    private XMLStreamReader reader;

    public MyErrorHandler(XMLStreamReader reader) {
        this.reader = reader;
    }

    @Override
    public void error(SAXParseException e) throws SAXException {
        warning(e);
    }

    @Override
    public void fatalError(SAXParseException e) throws SAXException {
        warning(e);
    }

    @Override
    public void warning(SAXParseException e) throws SAXException {
        System.out.println(reader.getLocalName());
        System.out.println(reader.getNamespaceURI());
        e.printStackTrace(System.out);
    }

}

Demo

演示

You set an instance of ErrorHandler on the Validator.

您在验证器上设置了ErrorHandler的实例。

package forum11921190;

import javax.xml.XMLConstants;
import javax.xml.stream.*;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.*;

public class Demo {

    private static final StreamSource XSD = new StreamSource("src/forum11921190/schema.xsd");
    private static final StreamSource XML = new StreamSource("src/forum11921190/input.xml");

    public static void main(String[] args) throws Exception {
        SchemaFactory factory=SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Schema schema = factory.newSchema(XSD);

        XMLStreamReader reader = XMLInputFactory.newFactory().createXMLStreamReader(XML);

        Validator validator = schema.newValidator();
        validator.setErrorHandler(new MyErrorHandler(reader));
        validator.validate(new StAXSource(reader));

    }

}

schema.xsd

schema.xsd

Below is a sample XML schema I used when writing the demo code.

下面是我在编写演示代码时使用的一个示例XML模式。

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://www.example.com"
    xmlns:tns="http://www.example.com"
    elementFormDefault="qualified">
    <element name="root">
        <complexType>
            <sequence>
                <element name="foo" type="string"/>
                <element name="bar" type="int"/>
            </sequence>
        </complexType>
    </element>
</schema>

input.xml

input.xml

Below is some sample input. The bar element has invalid content.

下面是一些示例输入。bar元素的内容无效。

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="http://www.example.com">
    <foo>valid</foo>
    <bar>invalid</bar>
</root>

Output

输出

Below is the output from running the demo code:

下面是运行演示代码的输出:

bar
http://www.example.com
org.xml.sax.SAXParseException: cvc-datatype-valid.1.2.1: 'invalid' is not a valid value for 'integer'.
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:131)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:384)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:318)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:423)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3188)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.elementLocallyValidType(XMLSchemaValidator.java:3103)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.processElementContent(XMLSchemaValidator.java:3013)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleEndElement(XMLSchemaValidator.java:2156)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.endElement(XMLSchemaValidator.java:824)
    at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorHandlerImpl.endElement(ValidatorHandlerImpl.java:565)
    at com.sun.org.apache.xml.internal.serializer.ToXMLSAXHandler.endElement(ToXMLSAXHandler.java:261)
    at com.sun.org.apache.xalan.internal.xsltc.trax.StAXStream2SAX.handleEndElement(StAXStream2SAX.java:295)
    at com.sun.org.apache.xalan.internal.xsltc.trax.StAXStream2SAX.bridge(StAXStream2SAX.java:167)
    at com.sun.org.apache.xalan.internal.xsltc.trax.StAXStream2SAX.parse(StAXStream2SAX.java:120)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:674)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:723)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:336)
    at com.sun.org.apache.xerces.internal.jaxp.validation.StAXValidatorHelper.validate(StAXValidatorHelper.java:94)
    at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorImpl.validate(ValidatorImpl.java:118)
    at javax.xml.validation.Validator.validate(Validator.java:127)
    at forum11921190.Demo.main(Demo.java:26)
bar
http://www.example.com
org.xml.sax.SAXParseException: cvc-type.3.1.3: The value 'invalid' of element 'bar' is not valid.
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:131)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:384)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:318)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:423)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3188)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.elementLocallyValidType(XMLSchemaValidator.java:3104)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.processElementContent(XMLSchemaValidator.java:3013)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleEndElement(XMLSchemaValidator.java:2156)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.endElement(XMLSchemaValidator.java:824)
    at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorHandlerImpl.endElement(ValidatorHandlerImpl.java:565)
    at com.sun.org.apache.xml.internal.serializer.ToXMLSAXHandler.endElement(ToXMLSAXHandler.java:261)
    at com.sun.org.apache.xalan.internal.xsltc.trax.StAXStream2SAX.handleEndElement(StAXStream2SAX.java:295)
    at com.sun.org.apache.xalan.internal.xsltc.trax.StAXStream2SAX.bridge(StAXStream2SAX.java:167)
    at com.sun.org.apache.xalan.internal.xsltc.trax.StAXStream2SAX.parse(StAXStream2SAX.java:120)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:674)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:723)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:336)
    at com.sun.org.apache.xerces.internal.jaxp.validation.StAXValidatorHelper.validate(StAXValidatorHelper.java:94)
    at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorImpl.validate(ValidatorImpl.java:118)
    at javax.xml.validation.Validator.validate(Validator.java:127)
    at forum11921190.Demo.main(Demo.java:26)

#2


1  

Try this in you catch code:

在你的代码中试试这个:

catch(SAXException saxe) {
    Element invalidElement = (Element) validator.getProperty("http://apache.org/xml/properties/dom/current-element-node");
    System.out.println("Error: " + saxe.getMessage());
    System.out.println("Invalid element: " + invalidElement);
}

#1


12  

Below is a way that you could implement your use case using an ErrorHandler:

下面是一种使用ErrorHandler实现用例的方法:

MyErrorHandler

MyErrorHandler

I would recommend implementing an ErrorHandler that maintained a reference to the XMLStreamReader so that when a SAXParseException occurs you could interrogate the XMLStreamReader to get information about the element. If you want the parsing to stop once an exception is thrown simply rethrow the SAXParseException at the end of each of the methods.

我建议实现一个ErrorHandler,它维护对XMLStreamReader的引用,以便当SAXParseException发生时,您可以查询XMLStreamReader来获取有关元素的信息。如果您希望解析在异常被抛出时停止,那么只需在每个方法的末尾重新抛出SAXParseException。

package forum11921190;

import javax.xml.stream.XMLStreamReader;
import org.xml.sax.*;

public class MyErrorHandler implements ErrorHandler {

    private XMLStreamReader reader;

    public MyErrorHandler(XMLStreamReader reader) {
        this.reader = reader;
    }

    @Override
    public void error(SAXParseException e) throws SAXException {
        warning(e);
    }

    @Override
    public void fatalError(SAXParseException e) throws SAXException {
        warning(e);
    }

    @Override
    public void warning(SAXParseException e) throws SAXException {
        System.out.println(reader.getLocalName());
        System.out.println(reader.getNamespaceURI());
        e.printStackTrace(System.out);
    }

}

Demo

演示

You set an instance of ErrorHandler on the Validator.

您在验证器上设置了ErrorHandler的实例。

package forum11921190;

import javax.xml.XMLConstants;
import javax.xml.stream.*;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.*;

public class Demo {

    private static final StreamSource XSD = new StreamSource("src/forum11921190/schema.xsd");
    private static final StreamSource XML = new StreamSource("src/forum11921190/input.xml");

    public static void main(String[] args) throws Exception {
        SchemaFactory factory=SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Schema schema = factory.newSchema(XSD);

        XMLStreamReader reader = XMLInputFactory.newFactory().createXMLStreamReader(XML);

        Validator validator = schema.newValidator();
        validator.setErrorHandler(new MyErrorHandler(reader));
        validator.validate(new StAXSource(reader));

    }

}

schema.xsd

schema.xsd

Below is a sample XML schema I used when writing the demo code.

下面是我在编写演示代码时使用的一个示例XML模式。

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://www.example.com"
    xmlns:tns="http://www.example.com"
    elementFormDefault="qualified">
    <element name="root">
        <complexType>
            <sequence>
                <element name="foo" type="string"/>
                <element name="bar" type="int"/>
            </sequence>
        </complexType>
    </element>
</schema>

input.xml

input.xml

Below is some sample input. The bar element has invalid content.

下面是一些示例输入。bar元素的内容无效。

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="http://www.example.com">
    <foo>valid</foo>
    <bar>invalid</bar>
</root>

Output

输出

Below is the output from running the demo code:

下面是运行演示代码的输出:

bar
http://www.example.com
org.xml.sax.SAXParseException: cvc-datatype-valid.1.2.1: 'invalid' is not a valid value for 'integer'.
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:131)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:384)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:318)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:423)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3188)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.elementLocallyValidType(XMLSchemaValidator.java:3103)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.processElementContent(XMLSchemaValidator.java:3013)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleEndElement(XMLSchemaValidator.java:2156)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.endElement(XMLSchemaValidator.java:824)
    at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorHandlerImpl.endElement(ValidatorHandlerImpl.java:565)
    at com.sun.org.apache.xml.internal.serializer.ToXMLSAXHandler.endElement(ToXMLSAXHandler.java:261)
    at com.sun.org.apache.xalan.internal.xsltc.trax.StAXStream2SAX.handleEndElement(StAXStream2SAX.java:295)
    at com.sun.org.apache.xalan.internal.xsltc.trax.StAXStream2SAX.bridge(StAXStream2SAX.java:167)
    at com.sun.org.apache.xalan.internal.xsltc.trax.StAXStream2SAX.parse(StAXStream2SAX.java:120)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:674)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:723)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:336)
    at com.sun.org.apache.xerces.internal.jaxp.validation.StAXValidatorHelper.validate(StAXValidatorHelper.java:94)
    at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorImpl.validate(ValidatorImpl.java:118)
    at javax.xml.validation.Validator.validate(Validator.java:127)
    at forum11921190.Demo.main(Demo.java:26)
bar
http://www.example.com
org.xml.sax.SAXParseException: cvc-type.3.1.3: The value 'invalid' of element 'bar' is not valid.
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:131)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:384)
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:318)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:423)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3188)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.elementLocallyValidType(XMLSchemaValidator.java:3104)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.processElementContent(XMLSchemaValidator.java:3013)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleEndElement(XMLSchemaValidator.java:2156)
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.endElement(XMLSchemaValidator.java:824)
    at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorHandlerImpl.endElement(ValidatorHandlerImpl.java:565)
    at com.sun.org.apache.xml.internal.serializer.ToXMLSAXHandler.endElement(ToXMLSAXHandler.java:261)
    at com.sun.org.apache.xalan.internal.xsltc.trax.StAXStream2SAX.handleEndElement(StAXStream2SAX.java:295)
    at com.sun.org.apache.xalan.internal.xsltc.trax.StAXStream2SAX.bridge(StAXStream2SAX.java:167)
    at com.sun.org.apache.xalan.internal.xsltc.trax.StAXStream2SAX.parse(StAXStream2SAX.java:120)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:674)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:723)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:336)
    at com.sun.org.apache.xerces.internal.jaxp.validation.StAXValidatorHelper.validate(StAXValidatorHelper.java:94)
    at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorImpl.validate(ValidatorImpl.java:118)
    at javax.xml.validation.Validator.validate(Validator.java:127)
    at forum11921190.Demo.main(Demo.java:26)

#2


1  

Try this in you catch code:

在你的代码中试试这个:

catch(SAXException saxe) {
    Element invalidElement = (Element) validator.getProperty("http://apache.org/xml/properties/dom/current-element-node");
    System.out.println("Error: " + saxe.getMessage());
    System.out.println("Invalid element: " + invalidElement);
}