我正在尝试将2个嵌入式XSD编译成单个XSD文件,但我收到错误“无法解析'schemaLocation'属性”。我不确定如何解决这个问题,但我猜测它的命名空间有些如何。
Schema1.xsd对Schema2.xsd执行xsd:include
Schem1.xsd(嵌入式资源)(简化)
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.somedomain.co.uk/application" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.somedomain.co.uk/application" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xsd:include schemaLocation="Schema2.xsd"/>
</xsd:schema>
Schema2.xsd(嵌入式资源)(简化)
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.somedomain.co.uk/application" targetNamespace="http://www.somedomain.co.uk/application" elementFormDefault="qualified" attributeFormDefault="unqualified" id="someId">
</xsd:schema>
代码
using System;
using System.Reflection;
using System.Xml;
using System.Xml.Schema;
namespace Example
{
class Program
{
public static void Main()
{
XmlSchema schema1 = null;
using (XmlTextReader xtr = new XmlTextReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("Example.Schema1.xsd")))
{
schema1 = XmlSchema.Read(xtr, new ValidationEventHandler(XSDValidationEventHandler));
xtr.Close();
}
XmlSchema schema2 = null;
using (XmlTextReader xtr = new XmlTextReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("Example.Schema2.xsd")))
{
schema2 = XmlSchema.Read(xtr, new ValidationEventHandler(XSDValidationEventHandler));
xtr.Close();
}
XmlSchemaSet schemaSet = new XmlSchemaSet();
schemaSet.ValidationEventHandler += new ValidationEventHandler(XSDValidationEventHandler);
schemaSet.Add(schema1); //error writes out to console here
schemaSet.Add(schema2);
schemaSet.Compile();
XmlSchema compiledSchema = null;
foreach (XmlSchema schema in schemaSet.Schemas())
{
compiledSchema = schema;
}
Console.WriteLine("Finished");
Console.ReadKey();
}
public static void XSDValidationEventHandler(object sender, ValidationEventArgs args)
{
Console.WriteLine(args.Message);
}
}
}
注意:我不允许更改XSD内容或将其更改为不是嵌入式资源。
任何问题随时可以提出
由于
凯尔
答案 0 :(得分:1)
当您使用嵌入式文件时,默认的XmlTextReader无法找到引用的文件。创建XmlTextReader后,必须为其提供一个知道处理嵌入文件的XmlResolver。
using (XmlTextReader xtr = new XmlTextReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("Example.Schema1.xsd")))
{
xtr.XmlResolver = new EmbeddedResourceResolver();
schema1 = XmlSchema.Read(xtr, new ValidationEventHandler(XSDValidationEventHandler));
xtr.Close();
}
&#39; EmbeddedResourceResolver&#39;不是现有的Framework类,但可以由您自己创建。您可以在下面找到参考实现。
using System;
using System.Xml;
using System.Reflection;
using System.IO;
namespace MyApp
{
public class EmbeddedResourceResolver : XmlUrlResolver
{
public override object GetEntity(Uri absoluteUri,
string role, Type ofObjectToReturn)
{
Assembly assembly = Assembly.GetExecutingAssembly();
return assembly.GetManifestResourceStream("the.path.to.your.resource");
}
}
}
由于您不允许更改XML,因此您的实施取决于嵌入资源在项目结构中的位置。
您可以在XmlResolver here
上找到更多信息我的最终代码
注意:作为参考,我的嵌入式XSD都位于项目的根目录
using System;
using System.Reflection;
using System.Xml;
using System.Xml.Schema;
namespace Example
{
public class EmbeddedResourceResolver : XmlUrlResolver
{
public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn)
{
Assembly assembly = Assembly.GetExecutingAssembly();
return assembly.GetManifestResourceStream("Example.Schema2.xsd");
}
}
class Program
{
public static void Main()
{
XmlSchema schema1 = null;
using (XmlTextReader xtr = new XmlTextReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("Example.Schema1.xsd")))
{
schema1 = XmlSchema.Read(xtr, new ValidationEventHandler(XSDValidationEventHandler));
xtr.Close();
}
XmlSchemaSet schemaSet = new XmlSchemaSet();
schemaSet.XmlResolver = new EmbeddedResourceResolver();
schemaSet.ValidationEventHandler += new ValidationEventHandler(XSDValidationEventHandler);
schemaSet.Add(schema1);
schemaSet.Compile();
XmlSchema compiledSchema = null;
foreach (XmlSchema schema in schemaSet.Schemas())
{
compiledSchema = schema;
}
Console.WriteLine("Finished");
Console.ReadKey();
}
public static void XSDValidationEventHandler(object sender, ValidationEventArgs args)
{
Console.WriteLine(args.Message);
}
}
}