首页 > 解决方案 > 在 SaxonEE/dotNet 中针对 xsd 验证 xml 时;如何调用 SetInvalidityHandler?

问题描述

我所拥有的是:“您可以调用 SetInvalidityHandler(IInvalidityHandler inHandler)。这将导致向您提供的处理程序报告每个有效性错误。错误是通过(名称不佳)StaticError 对象报告的。它包装了一个 Java ValidationFailure 对象。”
我试过了:(是的,是vb,c#响应也不错)

Delegate Sub ValidationCallBack(errH As Saxon.Api.IInvalidityHandler)
Dim IIH As Saxon.Api.IInvalidityHandler    'very suss on this line

然后是一个子;

Sub ValidationCallBackEvent(errH As Saxon.Api.IInvalidityHandler)
    dim k as integer
    k=0 'F9 here
End Sub

然后是一个包含的子;

Dim deleg As New ValidationCallBack(AddressOf ValidationCallBackEvent)

Dim processor = New Processor(True)
Dim sXsdPathUri As String = "c:\temp\the.xsd"
Dim sXmlPathUri As String = "c:\temp\the.xml"

processor.SetProperty("http://saxon.sf.net/feature/timing", "true")
processor.SetProperty("http://saxon.sf.net/feature/validation-warnings", "false") 

Dim manager As SchemaManager = processor.SchemaManager     
Dim schemaUri As System.Uri
schemaUri = New System.Uri(sXsdPathUri)

manager.Compile(schemaUri)

Dim validator As SchemaValidator = manager.NewSchemaValidator
Dim settings As System.Xml.XmlReaderSettings = New System.Xml.XmlReaderSettings
settings.DtdProcessing = System.Xml.DtdProcessing.Ignore
Dim inputFileName As String = New Uri(sXmlPathUri).ToString()
Dim xmlReader As System.Xml.XmlReader = System.Xml.XmlReader.Create(inputFileName, settings)
validator.SetSource(xmlReader)

validator.SetInvalidityHandler(IIH)  'suss; but it needs a Saxon.Api.IInvalidityHandler..
validator.Run()
Try
    validator.Run()
    sResult = "Valid!!"
Catch ex As Exception
    Dim err As StaticError
    For Each err In validator.ErrorList 'still goes here

它没有出错,但也没有引发 ValidationCallBackEvent ,所以很明显我的管道不正确。

有任何想法吗?谢谢!

标签: .netxmlxsdsaxon

解决方案


Saxon 支持发布了一个 C# 示例;

public void TestInvalidityHandler()
    {
        XmlReader xsd = XmlReader.Create(Path.GetFullPath(ConfigTest.DATA_DIR + "books.xsd"));
        XmlReader source_xml = XmlReader.Create(new StringReader("<?xml version='1.0'?><request><user_name>ed</user_name><password>sdsd</password><date1>a2009-01-01</date1><date2>b2009-01-01</date2></request>"));
        UriBuilder ub = new UriBuilder();
        ub.Scheme = "file";
        ub.Host = "";
        ub.Path = @"C:\work\tests\";
        Uri baseUri = ub.Uri;

        Processor saxon = new Processor(true);

        SchemaManager manager = saxon.SchemaManager;
        manager.ErrorList = new ArrayList();
        manager.XsdVersion = "1.0";
        try
        {
            DocumentBuilder builder = saxon.NewDocumentBuilder();
            builder.BaseUri = new Uri("http://example.com");
            XdmNode xsdNode = builder.Build(xsd);
            manager.Compile(xsdNode);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Schema compilation failed with " + manager.ErrorList.Count + " errors");
            String errors = "";
            foreach (StaticError error in manager.ErrorList)
            {
                Console.WriteLine("At line " + error.LineNumber + ": " + error.Message);
                errors += error.Message + "\n";
            }
            Assert.Fail("Failed in compile of xsd "+ errors);

        }
        Saxon.Api.SchemaValidator validator = manager.NewSchemaValidator();
        validator.SetInvalidityHandler(new MyInvalidaityHandler());
        validator.SetSource(source_xml);
        try
        {
            validator.Run();
            Assert.True(true);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.StackTrace);
            Assert.Fail(ex.Message);
        }
    }

    public class MyInvalidaityHandler : IInvalidityHandler
    {
        public XdmValue endReporting()
        {
            return currentNode; // this could be the entire  constructedreport
        }
        public void reportInvalidity(StaticError i)
        {
            //TODO - Do something here. Maybe write to a file or throw an exception 
        }
        public void startReporting(string systemId)
        {
            // no action, but can do setup of file
        }
    }
}

这足以让我获得一个工作的 VB.net 版本;

 Function TestInvalidityHandler() As String
    Dim sReturn As String
    Dim processor = New Processor(True)
    Dim sXmlPathUri As String
    Dim sXsdPathUri As String
    sXsdPathUri = "K:\SamplesFinal_ALL\IncludesImports\ALL\DotNetParserErrorTest\orderProd_YYNY_QQ.xsd"
    sXmlPathUri = "K:\SamplesFinal_ALL\IncludesImports\ALL\DotNetParserErrorTest\SampleFile_YYNY_QQ_dotNetValid.xml"
    processor.SetProperty("http://saxon.sf.net/feature/timing", "true")
    processor.SetProperty("http://saxon.sf.net/feature/validation-warnings", "false") ' //Set to true to suppress the exception

    Dim manager As SchemaManager = processor.SchemaManager
    manager.XsdVersion = "1.1"

    Dim schemaUri As System.Uri
    schemaUri = New System.Uri(sXsdPathUri)
    manager.Compile(schemaUri)                  'error handling removed for the moment..
    Dim validator As SchemaValidator = manager.NewSchemaValidator
    validator.SetInvalidityHandler(New MyInvalidityHandler())
    'use dot net objects;
    Dim settings As System.Xml.XmlReaderSettings = New System.Xml.XmlReaderSettings
    settings.DtdProcessing = System.Xml.DtdProcessing.Ignore
    Dim inputFileName As String = New Uri(sXmlPathUri).ToString()
    Dim xmlReader As System.Xml.XmlReader = System.Xml.XmlReader.Create(inputFileName, settings)
    validator.SetSource(xmlReader)
    Try
        validator.Run()
        sReturn = "OK"
    Catch ex As Exception
        sReturn = ex.Message
    End Try
    Return sReturn

End Function

Public Class MyInvalidityHandler

    Implements Saxon.Api.IInvalidityHandler

    Public Sub reportInvalidity(ByVal se As StaticError) Implements Saxon.Api.IInvalidityHandler.reportInvalidity
        'Get path etc from se.Message
    End Sub

    Public Sub startReporting(ByVal systemId As String) Implements Saxon.Api.IInvalidityHandler.startReporting
        'started
    End Sub

    Public Function endReporting() As XdmValue Implements Saxon.Api.IInvalidityHandler.endReporting
        Dim currentNode As XdmValue
        Return currentNode 'what's in xdm?
    End Function

End Class

所以不需要委托或接口,事实上现在我已经得到了答案。最后说明;感谢 Steven Doggart 对 Error 的回答,即即使定义了函数,我也必须在类中实现函数。类 'MyInvalidityHandler' 必须为接口 'Saxon.Api.IInvalidityHandler' 实现 'Function endReporting() As XdmValue' 错误在一段时间内是一个障碍,并且在这种情况下 C# 和 VB.net 之间的主要区别.


推荐阅读