当我的所有. xsd 's都作为资源存储时,我如何解析. xsd的schemaLocation属性?
本文关键字:xsd 存储 属性 schemaLocation 资源 何解析 我的 | 更新日期: 2023-09-27 18:13:20
我正在处理一个需要基于嵌套XSD生成XML文件的项目。例如:ORDER有一个PERSON的引用,PERSON有一个ADDRESS的引用,等等。
我正在创建一个' XmlReaderSettings'实例来验证XSD,以及在生成XML后验证XML。
我已经将XSD作为资源添加到我的程序集。然后,我为每个资源从低到高创建一个XmlSchema
实例,并将其添加到XmlReaderSettings.Schemas
集合中。
但是,尝试添加引用另一个模式的模式失败。我得到一个XmlSchemaException:"对于元素声明,必须存在名称或ref属性。"
我在下面包含了示例XSD和源代码:
地址。xsd -由PERSON.xsd
引用<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="ADDRESS.xsd" attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ADDRESS" >
<xs:complexType>
<xs:sequence>
<xs:element name="ADDRESS1" type="xs:string"/>
<xs:element name="ADDRESS2" type="xs:string"/>
<xs:element name="CITY" type="xs:string"/>
<xs:element name="STATE" type="xs:string"/>
<xs:element name="ZIP" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
PERSON.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="PERSON.xsd" attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:include schemaLocation="ADDRESS.xsd"/>
<xs:element name="PERSON" >
<xs:complexType>
<xs:sequence>
<xs:element name="L_NAME" type="xs:string"/>
<xs:element name="F_NAME" type="xs:string"/>
<xs:element name="Addresses">
<xs:complexType>
<xs:sequence>
<xs:element ref="ADDRESS" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
示例代码 -加载并验证XSD的
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using SchemaTest.Properties;
namespace SchemaTest
{
class Program
{
static void Main(string[] args)
{
// create validation settings instance
var xmlReaderSettings = new XmlReaderSettings
{
ValidationType = ValidationType.Schema,
ValidationFlags = XmlSchemaValidationFlags.ProcessInlineSchema |
XmlSchemaValidationFlags.ProcessSchemaLocation |
XmlSchemaValidationFlags.ReportValidationWarnings
};
xmlReaderSettings.ValidationEventHandler += SchemaValidationEventHandler;
// added XmlResourceResolver, per the accepted answer below
xMLReaderSettings.Schemas.XmlResolver = new XmlResourceResolver();
// load schemas into validation settings instance
LoadSchema(xmlReaderSettings, Resources.PERSON);
// validate schemas
xmlReaderSettings.Schemas.Compile();
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
private static void LoadSchema(XmlReaderSettings xmlReaderSettings, string schemaString)
{
using (var schemaStream = new MemoryStream(Encoding.Default.GetBytes(schemaString)))
{
var schema = XmlSchema.Read(schemaStream, null);
try
{
xmlReaderSettings.Schemas.Add(schema);
}
catch (Exception ex)
{
Console.WriteLine("EXCEPTION: {0}", ex.Message);
}
}
}
private static void SchemaValidationEventHandler(object sender, ValidationEventArgs e)
{
Console.WriteLine("{0}: {1}", e.Severity, e.Message);
}
}
}
我不确定这是否与ValidationFlags
有关,但我试图删除XmlSchemaValidationFlags.ProcessSchemaLocation
,仍然收到同样的错误。我还尝试将SchemaValidationEventHandler
传递给XmlSchema.Read
方法(而不是示例代码中的null),并且模式似乎可以创建,但当试图将其添加到XmlReaderSettings.Schemas
集合时,它仍然抛出异常。
EDIT - 2011.11.03
我解决了这个问题(双关语)通过创建我自己的XmlUrlResolver
后代称为XmlResourceResolver
,基于XmlResolver
类的例子在接受的答案下面。
要消除错误,请将PERSON中的type="Addresses"更改为name="Addresses"。xsd文件。
最好使用下面的代码来编译模式。重要的是要确保建立了一个基本uri(因为要从流中读取)、使用XmlSchemaSet和自定义解析器(将文件作为嵌入式资源读取)。
using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Schema;
namespace ConsoleApplication3
{
class Program
{
class XmlResolver : XmlUrlResolver
{
internal const string BaseUri = "schema://";
public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
{
if (absoluteUri.Scheme == "schema")
{
switch (absoluteUri.LocalPath)
{
case "/ADDRESS.xsd":
return new MemoryStream(Encoding.UTF8.GetBytes(Resource.ADDRESS));
case "/PERSON.xsd":
return new MemoryStream(Encoding.UTF8.GetBytes(Resource.PERSON));
}
}
return base.GetEntity(absoluteUri, role, ofObjectToReturn);
}
}
static void Main(string[] args)
{
using (XmlReader reader = XmlReader.Create(new StringReader(Resource.PERSON), new XmlReaderSettings(), XmlResolver.BaseUri))
{
XmlSchemaSet xset = RetrieveSchemaSet(reader);
Console.WriteLine(xset.IsCompiled);
}
}
private static XmlSchemaSet RetrieveSchemaSet(XmlReader reader)
{
XmlSchemaSet xset = new XmlSchemaSet() { XmlResolver = new XmlResolver() };
xset.Add(XmlSchema.Read(reader, null));
xset.Compile();
return xset;
}
}
}