c# - xsd:import 在嵌入式资源 XSD 中

标签 c# .net visual-studio-2010 xsd embedded-resource

我有一个类库项目,其中包含我解决方案中其他项目之间的一些共享代码。其中一段共享代码涉及针对 XSD 文件运行 XML 验证。 XSD 的名称作为参数传递给方法,然后使用 Assembly.GetFile() 加载。

问题是 XSD 文件导入了另外两个 XSD。我已经将所有三个作为资源加载到我的类库中,但从我读到的内容来看,xsd:import 将无法工作。是否有其他方法可以在不破坏 xsd:import 语句的情况下使这些 XSD 在我的类库项目中可用?

编辑 - 更新

我实现了 Alexander's suggestion下面但正如我在评论中所述,每当 GetEntity()xs:import 的 XSD 调用时,ofObjectToReturn 就是 。这导致 xs:import 类型的第一个实例抛出异常“type not defined”。

为了解决这个问题,我更改了 GetEntity() 以返回 GetManifestResourceStream(),而不考虑 ofObjectToReturn 的值。现在这似乎适用于第一级 xs:import 语句,但第二级 xs:import 在原始 xs:import XSD 中不管用。我已经确认正在为这个辅助 xs:import 调用 GetEntity() 但我收到了在这个辅助中定义的类型的“类型未定义”异常XSD.

  • TopLevel.xsd - 类型解析良好
    • FirstLevelImport1.xsd - 类型解析良好
    • FirstLevelImport2.xsd - 类型解析良好
      • SecondLevelImport1.xsd - 针对此 XSD 中定义的类型抛出“类型未定义”异常

在通过定义架构验证的 XmlReaderSettingsXmlReader.Create() 期间抛出“类型未定义”异常。

最佳答案

要解析由 xsd:importxsd:include 添加的文件,您可以使用自定义 XmlResolver。您可以在下面找到 ResourceXmlResolver 的示例。它假设程序集的名称是“AYez.EmbeddedXsdTests”。

using System.Xml;
using System.Xml.Schema;
using NUnit.Framework;

namespace AYez.EmbeddedXsdTests
{
    [TestFixture]
    public class EmbeddedXsdTests
    {
        [Test]
        public void SomeEntryPoint()
        {
            var schemaSet = new XmlSchemaSet {XmlResolver = new ResourceXmlResolver()};
            schemaSet.Add("rrn:org.xcbl:schemas/xcbl/v4_0/financial/v1_0/financial.xsd", @"Invoice.xsd");
            schemaSet.Compile();

            var settings = new XmlReaderSettings { ValidationType = ValidationType.Schema, Schemas = schemaSet };

            settings.ValidationEventHandler += delegate(object o, ValidationEventArgs e)
            {
                switch (e.Severity)
                {
                    case XmlSeverityType.Error:
                        Console.Write("Error: {0}", e.Message);
                        break;
                    case XmlSeverityType.Warning:
                        Console.Write("Warning: {0}", e.Message);
                        break;
                }
            };
            var xmlReader = XmlReader.Create(@"d:\temp\Invoice.xml", settings);
            while (xmlReader.Read()) { /*TODO: Nothing*/} // Validation is performed while reading

        }
    }

    public class ResourceXmlResolver: XmlResolver
    {
        /// <summary>
        /// When overridden in a derived class, maps a URI to an object containing the actual resource.
        /// </summary>
        /// <returns>
        /// A System.IO.Stream object or null if a type other than stream is specified.
        /// </returns>
        /// <param name="absoluteUri">The URI returned from <see cref="M:System.Xml.XmlResolver.ResolveUri(System.Uri,System.String)"/>. </param><param name="role">The current version does not use this parameter when resolving URIs. This is provided for future extensibility purposes. For example, this can be mapped to the xlink:role and used as an implementation specific argument in other scenarios. </param><param name="ofObjectToReturn">The type of object to return. The current version only returns System.IO.Stream objects. </param><exception cref="T:System.Xml.XmlException"><paramref name="ofObjectToReturn"/> is not a Stream type. </exception><exception cref="T:System.UriFormatException">The specified URI is not an absolute URI. </exception><exception cref="T:System.ArgumentNullException"><paramref name="absoluteUri"/> is null. </exception><exception cref="T:System.Exception">There is a runtime error (for example, an interrupted server connection). </exception>
        public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
        {   
                // If ofObjectToReturn is null, then any of the following types can be returned for correct processing:
                // Stream, TextReader, XmlReader or descendants of XmlSchema
                var result =  this.GetType().Assembly.GetManifestResourceStream(string.Format("AYez.EmbeddedXsdTests.{0}",
                                                                                             Path.GetFileName(absoluteUri.ToString())));                
                // set a conditional breakpoint "result==null" here
                return result;
        }

        /// <summary>
        /// When overridden in a derived class, sets the credentials used to authenticate Web requests.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Net.ICredentials"/> object. If this property is not set, the value defaults to null; that is, the XmlResolver has no user credentials.
        /// </returns>
        public override ICredentials Credentials
        {
            set { throw new NotImplementedException(); }
        }
    }
}

关于c# - xsd:import 在嵌入式资源 XSD 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5331849/

相关文章:

c# - 使用 Flurl 发布 JSON

c# - C#DirectSound-捕获缓冲区不连续

.net - .NET Framework v4.0.30128是最新版本吗?

c# - 无法将类型 'double' 隐式转换为 'float'

c++ - 无法打开 .cu 中的包含文件

c# - 什么时候去对象池?

c# - 在 C# 的编码端使用粗体

c# - 使用多个工作线程、多个源线程和接收器线程来执行线程 .net 应用程序的优雅方法?

c# - 在运行时添加文本框并保存更改

c# - 在 VS2010 中创建复合键