这是一个XSD:
<?xml version="1.0"?>
<xsd:schema
elementFormDefault='unqualified'
attributeFormDefault='unqualified'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
>
<xsd:simpleType name='TheSimpleType'>
<xsd:restriction base='xsd:string' />
</xsd:simpleType>
</xsd:schema>
这是第二个包含上述XSD的XSD:
<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema
elementFormDefault='unqualified'
attributeFormDefault='unqualified'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
targetNamespace='a'
xmlns='a'
>
<xsd:include schemaLocation='Include.xsd' />
<xsd:element name = "TheElement" >
<xsd:complexType>
<xsd:attribute name="Code" type="TheSimpleType" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>
我需要将(第二个)XSD读入C#并且:
以下是一些要在架构中阅读的C#:
XmlSchemaSet schemaSet = new XmlSchemaSet();
foreach (string sd in Schemas)
{
using (XmlReader r = XmlReader.Create(new FileStream(sd, FileMode.Open)))
{
schemaSet.Add(XmlSchema.Read(r, null));
}
}
schemaSet.CompilationSettings = new XmlSchemaCompilationSettings();
schemaSet.Compile();
.Compile()失败,因为“类型'a:未声明TheSimpleType',或者不是简单类型。”
但是,如果有:
问题是:如何在不编辑架构的情况下让C#接受它?
我怀疑问题是虽然我已将两个schemata都放入XmlSchemaSet中,但我仍然需要告诉C#一个被包含在另一个中,即它没有为自己解决问题。实际上,如果我只告诉XmlSchemaSet关于主XSD(而不是包含)(两者都没有(或带有)名称空间),那么“类型'TheSimpleType'未声明,或者不是简单类型。”
因此,这似乎是一个关于解决的问题包括:如何?!
答案 0 :(得分:25)
问题在于打开架构以便在线上阅读的方式:
XmlReader.Create(new FileStream(sd, FileMode.Open)
在我看到包含文件的路径如何解析之前,我必须编写自己的XmlResolver
:它来自可执行文件的目录,而不是来自父模式的目录。问题是父模式没有设置其BaseURI。以下是必须打开架构的方法:
XmlReader.Create(new FileStream(pathname, FileMode.Open, FileAccess.Read),null, pathname)
答案 1 :(得分:5)
您可以使用XmlSchema.Includes
将它们链接在一起。然后,您只需要将主模式添加到模式集:
var includeSchema = XmlSchema.Read(XmlReader.Create(...), null);
var mainSchema = XmlSchema.Read(XmlReader.Create(...), null);
var include = new XmlSchemaInclude();
include.Schema = includeSchema;
mainSchema.Includes.Add(include);
var schemaSet = new XmlSchemaSet();
schemaSet.Add(mainSchema);
schemaSet.Compile();
答案 2 :(得分:1)
试试这个:D
public static XmlSchema LoadSchema(string pathname)
{
XmlSchema s = null;
XmlValidationHandler h = new XmlValidationHandler();
using (XmlReader r = XmlReader.Create(new FileStream(pathname, FileMode.Open)))
{
s = XmlSchema.Read(r, new ValidationEventHandler(h.HandleValidationEvent));
}
if (h.Errors.Count > 0)
{
throw new Exception(string.Format("There were {1} errors reading the XSD at {0}. The first is: {2}.", pathname, h.Errors.Count, h.Errors[0]));
}
return s;
}
public static XmlSchema LoadSchemaAndResolveIncludes(string pathname)
{
FileInfo f = new FileInfo(pathname);
XmlSchema s = LoadSchema(f.FullName);
foreach(XmlSchemaInclude i in s.Includes)
{
XmlSchema si = LoadSchema(f.Directory.FullName + @"\" + i.SchemaLocation);
si.TargetNamespace = s.TargetNamespace;
i.Schema = si;
}
return s;
}
public static List<ValidationEventArgs> Validate(string pathnameDocument, string pathnameSchema)
{
XmlSchema s = LoadSchemaAndResolveIncludes(pathnameSchema);
XmlValidationHandler h = new XmlValidationHandler();
XmlDocument x = new XmlDocument();
x.Load(pathnameDocument);
x.Schemas.Add(s);
s.Compile(new ValidationEventHandler(h.HandleValidationEvent));
x.Validate(new ValidationEventHandler(h.HandleValidationEvent));
return h.Errors;
}
请特别注意si.TargetNamespace = s.TargetNamespace;
。
显然,这假设包含被指定为相对于包含它们的模式的文件路径。
答案 3 :(得分:0)
这是我编写的用于处理xsd验证的方法。希望这对某人有所帮助。
/// <summary>
/// Ensure all xsd imported xsd documented are in same folder as master xsd
/// </summary>
public XsdXmlValidatorResult Validate(string xmlPath, string xsdPath, string xsdNameSpace)
{
var result = new XsdXmlValidatorResult();
var readerSettings = new XmlReaderSettings {ValidationType = ValidationType.Schema};
readerSettings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
readerSettings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
readerSettings.Schemas.Add(null, xsdPath);
readerSettings.ValidationEventHandler += (sender, args) =>
{
switch (args.Severity)
{
case XmlSeverityType.Warning:
result.Warnings.Add(args.Message);
break;
case XmlSeverityType.Error:
result.IsValid = false;
result.Warnings.Add(args.Message);
break;
}
};
var reader = XmlReader.Create(xmlPath, readerSettings);
while (reader.Read()) { }
return result;
}