.net C++\CLI-如何将成员函数设置为xmlDocument::Schemas::ValidationEventHandler的处理程序

.net C++\CLI-如何将成员函数设置为xmlDocument::Schemas::ValidationEventHandler的处理程序,.net,xml,visual-c++,c++-cli,.net,Xml,Visual C++,C++ Cli,我试图在Visual Studio 2012中,在C++/CLI中将成员函数设置为XmlDocument数据成员的处理程序。处理程序函数如下所示 void Validate ( System :: Object ^ sender, System :: Xml :: Schema :: ValidationEventArgs ^ xmlException ) { switch ( xmlException->Severity ) {

我试图在Visual Studio 2012中,在C++/CLI中将成员函数设置为XmlDocument数据成员的处理程序。处理程序函数如下所示

void Validate ( System :: Object ^ sender, System :: Xml :: Schema :: ValidationEventArgs ^ xmlException ) {

            switch ( xmlException->Severity ) {

                case System :: Xml :: Schema :: XmlSeverityType :: Error : {

                    System :: Console :: WriteLine ( "Object: {0}", sender->ToString () );
                    System :: Console :: WriteLine ( " Error: {0}", xmlException->Message );

                } break;

                case System :: Xml :: Schema :: XmlSeverityType :: Warning : {

                    System :: Console :: WriteLine ( " Object: {0}", sender->ToString () );
                    System :: Console :: WriteLine ( "Warning: {0}", xmlException->Message );

                } break;

                default : {

                    System :: Console :: WriteLine ( "An unknown XML Exception has occured:\n\n   Object: {0}", sender->ToString () );
                    System :: Console :: WriteLine ( "Exception: {0}", xmlException->Message );

                } break;

            }

        };
…这没什么特别的

这就是我的数据成员的外观

System :: Xml :: XmlDocument ^ xmlDocument;
…这就是我试图在类构造函数中设置它的方式:

xmlDocument->Schemas->ValidationEventHandler += gcnew System :: Xml :: Schema :: ValidationEventArgs ( this, & MyClass :: Validate );
我的问题是我收到错误C3767:候选函数不可访问,即使我的“验证”成员函数及其定义的类被指定为public

我尝试了很多方法,最近使用了EventArgs或使用“#pragma make_public(System::Xml::Schema::ValidationEventArgs)”,但都没有效果


我的头发快用完了,想把头发拔出来,所以任何帮助都将不胜感激。谢谢大家。

首先,出现编译器错误C3767的原因是您需要执行以下操作:

schemas->ValidationEventHandler += gcnew System::Xml::Schema::ValidationEventHandler(this, &MyClass::Validate); 
而不是
gcnew ValidationEventArgs

其次,请注意,
XmlSchemaSet.ValidationEventHandler
可能不会按您的想法执行。从:

设置事件处理程序,用于在调用XmlSchemaSet的Add或Compile方法时接收有关架构验证错误的信息

因此,如果您希望为无效的XML文档添加事件处理程序,那么就不是这样了。这是针对模式本身的错误

如果您希望创建一个类来包装
XmlDocument
,但也允许调用者加载架构并根据它验证
XmlDocument
,您可以执行以下操作:

public ref class MyClass
{
public:
    MyClass()
    {
        xmlDocument = gcnew System::Xml::XmlDocument();
        schemas = gcnew System::Xml::Schema::XmlSchemaSet();
        // Set the callback for errors in the schema itself.
        schemas->ValidationEventHandler += gcnew System::Xml::Schema::ValidationEventHandler(this, &MyClass::ValidateSchema);   
        xmlDocument->Schemas = schemas;
    }

    // Adds a schema to the current schema set.
    void AddSchema(System::String ^targetNamespace, System::String ^schemaUri);

    // Loads the specified document, validating it against the current schema set.
    void LoadDocument(System::String ^inputUri);

    // Validates the current document against the current schema set.
    void ValidateDocument();

    System::Xml::XmlDocument ^ GetDocument() { return xmlDocument; }

private:
    // Validation callback for errors in the schema itself.
    void ValidateSchema ( System :: Object ^ sender, System :: Xml :: Schema :: ValidationEventArgs ^ xmlException );

    // Validation callback for errors in the XML document.
    void ValidateXml ( System :: Object ^ sender, System :: Xml :: Schema :: ValidationEventArgs ^ xmlException );

    // Lower level callback for both schema and XML errors.
    void Validate ( System :: Object ^ sender, System :: Xml :: Schema :: ValidationEventArgs ^ xmlException, System::String ^ prefix );

    System::Xml::XmlDocument ^ xmlDocument;

    System::Xml::Schema::XmlSchemaSet ^schemas;
};
单独缓存
XmlSchemaSet
很方便,因为当使用
XmlReader
中的XML数据初始化
XmlDocument
时,会从读取器的
schemaset
属性(重新)加载对象

然后,原型实现将如下所示:

#include "stdafx.h"

#using <mscorlib.dll>
#using <System.dll>
#using <System.Xml.dll>

using namespace System;
using namespace System::Xml;
using namespace System::Xml::Schema;

void MyClass::AddSchema(System::String ^targetNamespace, System::String ^schemaUri)
{
    try
    {
        schemas->Add(targetNamespace, schemaUri);
        xmlDocument->Schemas = schemas;
    }
    catch (Exception ^ex)
    {
        Console::WriteLine(ex->ToString());
        // Possibly rethrow.
    }
}

void MyClass::LoadDocument (System::String ^inputUri)
{
    XmlReader^ reader = nullptr;
    try
    {
        ValidationEventHandler^ eventHandler = gcnew System::Xml::Schema::ValidationEventHandler(this, &MyClass::ValidateXml);  

        XmlReaderSettings^ settings = gcnew XmlReaderSettings();

        settings->Schemas = schemas;
        settings->ValidationType = ValidationType::Schema;
        settings->ValidationEventHandler += eventHandler;

        reader = XmlReader::Create(inputUri, settings);

        xmlDocument->Load(reader);
        reader->Close();
    }
    catch (Exception ^ex)
    {
        Console::WriteLine(ex->Message);
        // Possibly rethrow.
    }
    finally
    {
        // Make sure the reader is closed in the event of an exception.
        delete reader;
    }
}

void MyClass::ValidateDocument()
{
    ValidationEventHandler^ eventHandler = gcnew System::Xml::Schema::ValidationEventHandler(this, &MyClass::ValidateXml);

    xmlDocument->Validate(eventHandler);
}

void MyClass::ValidateSchema ( System :: Object ^ sender, System :: Xml :: Schema :: ValidationEventArgs ^ xmlException)
{
    Validate(sender, xmlException, gcnew System::String("Schema: "));
}

void MyClass::ValidateXml ( System :: Object ^ sender, System :: Xml :: Schema :: ValidationEventArgs ^ xmlException )
{
    Validate(sender, xmlException, System::String::Empty);
}

void MyClass::Validate ( System :: Object ^ sender, System :: Xml :: Schema :: ValidationEventArgs ^ xmlException, System::String ^ prefix )
{
    switch ( xmlException->Severity ) 
    {
    case System :: Xml :: Schema :: XmlSeverityType :: Error : 
        {
            System :: Console :: WriteLine ( prefix + "Object: {0}", sender->ToString () );
            System :: Console :: WriteLine ( prefix + " Error: {0}", xmlException->Message );

        } break;

    case System :: Xml :: Schema :: XmlSeverityType :: Warning : 
        {
            System :: Console :: WriteLine ( prefix + " Object: {0}", sender->ToString () );
            System :: Console :: WriteLine ( prefix + "Warning: {0}", xmlException->Message );

        } break;

    default : 
        {
            System :: Console :: WriteLine ( prefix + "An unknown XML Exception has occured:\n\n   Object: {0}", sender->ToString () );
            System :: Console :: WriteLine ( prefix + "Exception: {0}", xmlException->Message );

        } break;
    }
};
#包括“stdafx.h”
#使用
#使用
#使用
使用名称空间系统;
使用名称空间系统::Xml;
使用名称空间System::Xml::Schema;
void MyClass::AddSchema(系统::字符串^targetNamespace,系统::字符串^schemaUri)
{
尝试
{
模式->添加(targetNamespace,schemaUri);
xmlDocument->Schemas=Schemas;
}
捕获(异常^ex)
{
控制台::WriteLine(ex->ToString());
//可能是重新命名。
}
}
void MyClass::LoadDocument(系统::字符串^inputUri)
{
XmlReader^reader=nullptr;
尝试
{
ValidationEventHandler^eventHandler=gcnew System::Xml::Schema::ValidationEventHandler(this,&MyClass::ValidateXml);
XmlReaderSettings^settings=gcnew XmlReaderSettings();
设置->模式=模式;
设置->验证类型=验证类型::模式;
设置->验证eventHandler+=eventHandler;
reader=XmlReader::Create(输入URI,设置);
xmlDocument->Load(读卡器);
读卡器->关闭();
}
捕获(异常^ex)
{
控制台::写线(ex->Message);
//可能是重新命名。
}
最后
{
//确保在发生异常时关闭读卡器。
删除阅读器;
}
}
void MyClass::validatedDocument()
{
ValidationEventHandler^eventHandler=gcnew System::Xml::Schema::ValidationEventHandler(this,&MyClass::ValidateXml);
xmlDocument->Validate(eventHandler);
}
void MyClass::ValidateSchema(系统::对象^sender,系统::Xml::架构::ValidationEventArgs ^xmlException)
{
验证(发送方、xmlException、gcnew System::字符串(“模式:”);
}
void MyClass::ValidateXml(系统::对象^sender,系统::Xml::架构::ValidationEventArgs^xmlException)
{
验证(发送方、xmlException、系统::字符串::空);
}
void MyClass::Validate(系统::对象^sender,系统::Xml::架构::ValidationEventArgs ^xmlException,系统::字符串^prefix)
{
开关(xmlException->严重性)
{
案例系统::Xml::架构::XmlSeverityType::错误:
{
System::Console::WriteLine(前缀+“对象:{0}”,发送方->ToString());
System::Console::WriteLine(前缀+“Error:{0}”,xmlException->Message);
}中断;
案例系统::Xml::架构::XmlSeverityType::警告:
{
System::Console::WriteLine(前缀+“对象:{0}”,发送方->ToString());
System::Console::WriteLine(前缀+“警告:{0}”,xmlException->Message);
}中断;
违约:
{
System::Console::WriteLine(前缀+“发生未知XML异常:\n\n对象:{0}”,发件人->ToString());
System::Console::WriteLine(前缀+“异常:{0}”,xmlException->Message);
}中断;
}
};

首先,出现编译器错误C3767的原因是您需要执行以下操作:

schemas->ValidationEventHandler += gcnew System::Xml::Schema::ValidationEventHandler(this, &MyClass::Validate); 
而不是
gcnew ValidationEventArgs

其次,请注意,
XmlSchemaSet.ValidationEventHandler
可能不会按您的想法执行。从:

设置事件处理程序,用于在调用XmlSchemaSet的Add或Compile方法时接收有关架构验证错误的信息

因此,如果您希望为无效的XML文档添加事件处理程序,那么就不是这样了。这是针对模式本身的错误

如果您希望创建一个类来包装
XmlDocument
,但也允许调用者加载架构并根据它验证
XmlDocument
,您可以执行以下操作:

public ref class MyClass
{
public:
    MyClass()
    {
        xmlDocument = gcnew System::Xml::XmlDocument();
        schemas = gcnew System::Xml::Schema::XmlSchemaSet();
        // Set the callback for errors in the schema itself.
        schemas->ValidationEventHandler += gcnew System::Xml::Schema::ValidationEventHandler(this, &MyClass::ValidateSchema);   
        xmlDocument->Schemas = schemas;
    }

    // Adds a schema to the current schema set.
    void AddSchema(System::String ^targetNamespace, System::String ^schemaUri);

    // Loads the specified document, validating it against the current schema set.
    void LoadDocument(System::String ^inputUri);

    // Validates the current document against the current schema set.
    void ValidateDocument();

    System::Xml::XmlDocument ^ GetDocument() { return xmlDocument; }

private:
    // Validation callback for errors in the schema itself.
    void ValidateSchema ( System :: Object ^ sender, System :: Xml :: Schema :: ValidationEventArgs ^ xmlException );

    // Validation callback for errors in the XML document.
    void ValidateXml ( System :: Object ^ sender, System :: Xml :: Schema :: ValidationEventArgs ^ xmlException );

    // Lower level callback for both schema and XML errors.
    void Validate ( System :: Object ^ sender, System :: Xml :: Schema :: ValidationEventArgs ^ xmlException, System::String ^ prefix );

    System::Xml::XmlDocument ^ xmlDocument;

    System::Xml::Schema::XmlSchemaSet ^schemas;
};
单独缓存
XmlSchemaSet
很方便,因为当使用
XmlReader
中的XML数据初始化
XmlDocument
时,会从读取器的
schemaset
属性(重新)加载对象

然后,原型实现将如下所示:

#include "stdafx.h"

#using <mscorlib.dll>
#using <System.dll>
#using <System.Xml.dll>

using namespace System;
using namespace System::Xml;
using namespace System::Xml::Schema;

void MyClass::AddSchema(System::String ^targetNamespace, System::String ^schemaUri)
{
    try
    {
        schemas->Add(targetNamespace, schemaUri);
        xmlDocument->Schemas = schemas;
    }
    catch (Exception ^ex)
    {
        Console::WriteLine(ex->ToString());
        // Possibly rethrow.
    }
}

void MyClass::LoadDocument (System::String ^inputUri)
{
    XmlReader^ reader = nullptr;
    try
    {
        ValidationEventHandler^ eventHandler = gcnew System::Xml::Schema::ValidationEventHandler(this, &MyClass::ValidateXml);  

        XmlReaderSettings^ settings = gcnew XmlReaderSettings();

        settings->Schemas = schemas;
        settings->ValidationType = ValidationType::Schema;
        settings->ValidationEventHandler += eventHandler;

        reader = XmlReader::Create(inputUri, settings);

        xmlDocument->Load(reader);
        reader->Close();
    }
    catch (Exception ^ex)
    {
        Console::WriteLine(ex->Message);
        // Possibly rethrow.
    }
    finally
    {
        // Make sure the reader is closed in the event of an exception.
        delete reader;
    }
}

void MyClass::ValidateDocument()
{
    ValidationEventHandler^ eventHandler = gcnew System::Xml::Schema::ValidationEventHandler(this, &MyClass::ValidateXml);

    xmlDocument->Validate(eventHandler);
}

void MyClass::ValidateSchema ( System :: Object ^ sender, System :: Xml :: Schema :: ValidationEventArgs ^ xmlException)
{
    Validate(sender, xmlException, gcnew System::String("Schema: "));
}

void MyClass::ValidateXml ( System :: Object ^ sender, System :: Xml :: Schema :: ValidationEventArgs ^ xmlException )
{
    Validate(sender, xmlException, System::String::Empty);
}

void MyClass::Validate ( System :: Object ^ sender, System :: Xml :: Schema :: ValidationEventArgs ^ xmlException, System::String ^ prefix )
{
    switch ( xmlException->Severity ) 
    {
    case System :: Xml :: Schema :: XmlSeverityType :: Error : 
        {
            System :: Console :: WriteLine ( prefix + "Object: {0}", sender->ToString () );
            System :: Console :: WriteLine ( prefix + " Error: {0}", xmlException->Message );

        } break;

    case System :: Xml :: Schema :: XmlSeverityType :: Warning : 
        {
            System :: Console :: WriteLine ( prefix + " Object: {0}", sender->ToString () );
            System :: Console :: WriteLine ( prefix + "Warning: {0}", xmlException->Message );

        } break;

    default : 
        {
            System :: Console :: WriteLine ( prefix + "An unknown XML Exception has occured:\n\n   Object: {0}", sender->ToString () );
            System :: Console :: WriteLine ( prefix + "Exception: {0}", xmlException->Message );

        } break;
    }
};
#包括“stdafx.h”
#使用
#使用
#使用
使用名称空间系统;
乌辛