如何解决的.XSD的schemaLocation属性时,我所有的.XSD的是作为资源存储在哪里? [英] How can I resolve the schemaLocation attribute of an .XSD when all of my .XSD's are stored as resources?

查看:1513
本文介绍了如何解决的.XSD的schemaLocation属性时,我所有的.XSD的是作为资源存储在哪里?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我工作的一个项目,我需要根据嵌套XSD的生成XML文件。例如订单引用对人,人有一个参考地址等。

I am working on a project where I need to generate XML files based on nested XSD's. e.g. ORDER has a reference to PERSON, PERSON has a reference to ADDRESS, etc.

我建立一个`XmlReaderSettings实例来验证XSD的,以及验证XML生成后

I am creating an `XmlReaderSettings' instance to validate the XSD's, as well as validate the XML after it is generated.

我添加了XSD的作为参考资料,我的组装。然后,我对每个资源创建一个的XmlSchema 实例,从最低到最高,并把它添加到 XmlReaderSettings.Schemas 集合

I have added the XSD's as Resources to my assembly. I then create an XmlSchema instance for each resource, from lowest to highest, and add it to the XmlReaderSettings.Schemas collection.

但是,失败尝试添加引用另一个模式的架构。我得到一个XmlSchemaException:对于元素声明,名称或裁判属性必须是present。

However, this fails attempting to add a schema that references another schema. I get an XmlSchemaException: "For element declaration, either the name or the ref attribute must be present."

我已经包括样本的XSD的源$ C ​​$以下C:

I have included sample XSD's and source code below:

ADDRESS.xsd - 由PERSON.xsd引用

ADDRESS.xsd - referenced by 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>

样品code - 加载和验证XSD的

Sample Code - Load and validate XSD's

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 并且仍然收到了同样的错误。我也曾尝试过​​(而不是抽样code空)的 XmlSchema.Read 方法 SchemaValidationEventHandler ,和模式似乎要创建好了,但它仍然抛出异常时attemtping将其添加到 XmlReaderSettings.Schemas 集合。

I am not sure if this has anything to do with the ValidationFlags, but I tried removing XmlSchemaValidationFlags.ProcessSchemaLocation and still received the same error. I have also tried passing SchemaValidationEventHandler to the XmlSchema.Read method (instead of null in sample code), and the schema seems to be created OK, but it still throws the exception when attemtping to add it to the XmlReaderSettings.Schemas collection.

编辑 - 2011.11.03

我通过创建叫我自己的 XmlUrlResolver 后代 XmlResourceResolver 解决了这个问题(双关语意),根据< $ C C以下公认的答案>的XmlResolver 类例如$。

I resolved this issue (pun intended) by creating my own XmlUrlResolver descendent called XmlResourceResolver, based on the XmlResolver class example in accepted answer below.

推荐答案

要获得在您PERSON.xsd文件摆脱错误,更改类型=地址来命名=地址的。

To get rid of the error, change type="Addresses" to name="Addresses" in your PERSON.xsd file.

这是更好地去与code以下控件架构编译。最重要的事情是要确保你建立一个基础URI(因为你是从一个流中读取),使用XmlSchemaSet中,而是和自定义解析(读取文件嵌入式资源)。

It is better to go with the code below to get schemas compiled. The important things are to make sure you establish a base uri (since you're reading from a stream), to use an XmlSchemaSet instead, and a custom resolver (to read files as embedded resources).

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

这篇关于如何解决的.XSD的schemaLocation属性时,我所有的.XSD的是作为资源存储在哪里?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆