【问题标题】:C++\CLI - How to set a member function as a handler to xmlDocument::Schemas::ValidationEventHandlerC++\CLI - 如何将成员函数设置为 xmlDocument::Schemas::ValidationEventHandler 的处理程序
【发布时间】:2015-06-04 00:05:01
【问题描述】:

我正在尝试将成员函数设置为 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:候选函数不可访问,即使我的“验证”成员函数及其定义的类被指定为公共。

我尝试了多种方法,最近使用 EventArgs 或使用“#pragma make_public (System :: Xml :: Schema :: ValidationEventArgs)”,但无济于事。

我的头发快要拔掉了,因此我们将不胜感激。谢谢大家。

【问题讨论】:

  • 您在哪里将架构加载到架构集合中?您必须指定要验证的架构。
  • 我的类中有一个 XmlDocument 实例,据我了解,其中有一个架构集合作为其组合的一部分(架构和 SchemaInfo 属性)。我需要外部参考吗?
  • 您需要明确指定架构(例如,将.xsd 添加到Schemas 集合中)。仅通过加载 XmlDocument 不会自动解析架构 - 除非您希望类的使用者填充 Schemas 集合。换句话说,你必须告诉 validate 要验证什么。
  • 所以你的意思是在注入事件处理程序之前加载 .xml 文件?如果是这样,我会立即尝试
  • 我添加了更多信息

标签: .net xml visual-c++ c++-cli


【解决方案1】:

首先,您收到编译器错误 C3767 的原因是您需要这样做:

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

而不是gcnew ValidationEventArgs

其次,请注意XmlSchemaSet.ValidationEventHandler 可能不会按照您的想法行事。来自documentation

设置一个事件处理程序,用于在调用 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 时,XmlDocument.Schemas 对象将从阅读器的Schemas 属性(重新)加载.

那么原型实现将如下所示:

#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;
    }
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-27
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    • 1970-01-01
    • 2022-10-04
    相关资源
    最近更新 更多