我有一个类库项目,它在我的解决方案中包含其他项目之间的一些共享代码。其中一个共享代码涉及针对XSD文件的运行XML验证。 XSD的名称作为参数传递给方法,然后使用Assembly.GetFile()
加载。
问题是XSD文件导入另外两个XSD 。我已经将所有三个作为资源加载到我的类库中但是从我读过的xsd:import不起作用。是否有其他方法可以在我的类库项目中使用这些XSD而不会破坏xsd:import
语句?
修改 - 更新
我在下面实施了Alexander's suggestion,但正如我在评论中所述,每当GetEntity()
'XSD调用xs:import
时,ofObjectToReturn
为null
。这导致xs:import
'd类型的第一个实例抛出异常“未定义的类型”。
为了解决此问题,无论GetEntity()
的值如何,我都将GetManifestResourceStream()
更改为ofObjectToReturn
。现在,这似乎适用于xs:import
语句的第一级,但其中一个原始xs:import
XSD中的辅助xs:import
无效。我已确认正在为此辅助GetEntity()
调用xs:import
,但我收到此辅助XSD中定义的类型的“未定义类型”异常。
在XmlReader.Create()
传递定义架构验证的XmlReaderSettings
期间抛出“未定义类型”异常。
答案 0 :(得分:5)
要解析由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(); }
}
}
}
答案 1 :(得分:2)
如果我们首先将xsd文件读入字符串变量,则可以解决问题。
e.g。
var stream =assembly.GetManifestResourceStream("Namespace.child.xsd");
现在使用流阅读器将其读入字符串
e.g。
string childXSD=new StreamReader(stream).ReadToEnd();
相似得到字符串ParentXSD 然后使用
var xmlReader=XmlReader.Create(new MemoryStream(Encoding.Default.GetBytes(childXSD)));
schemaCollection.Add(null,xmlReader);
var xmlReader=XmlReader.Create(new MemoryStream(Encoding.Default.GetBytes(parentXSD)));
schemaCollection.Add(null,xmlReader);
我认为孩子对父母的顺序很重要,因为我们将儿童XSD引用为父母。