我有一个类库项目,其中包含我解决方案中其他项目之间的一些共享代码。其中一段共享代码涉及针对 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 中定义的类型抛出“类型未定义”异常
在通过定义架构验证的 XmlReaderSettings
的 XmlReader.Create()
期间抛出“类型未定义”异常。
最佳答案
要解析由 xsd:import
或 xsd: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/