参考此:其他帖子 我正在尝试做与另一篇文章中的OP基本相同的事情;使用我自己添加的属性扩展复杂类型,而不更改主命名空间。我尝试尽可能严格地遵循答案,但没有成功。
在上一篇文章之后,我创建了 4 个文件:3 个 xsd 和 1 个 xml。
原版.xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://bookshop.com"
targetNamespace="http://bookshop.com"
elementFormDefault="qualified">
<xs:complexType name="Book">
<xs:sequence>
<xs:element name="Author" type="String32"
minOccurs="1" maxOccurs="1" />
<xs:element name="Title" type="String32"
minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
<xs:element name="Book" type="Book"/>
<xs:simpleType name="String32">
<xs:restriction base="xs:string"></xs:restriction>
</xs:simpleType>
</xs:schema>
添加.xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
xmlns="http://custombookshop.com"
xmlns:bs="http://bookshop.com"
targetNamespace="http://custombookshop.com">
<xs:import namespace="http://bookshop.com" schemaLocation="original.xsd"/>
<xs:element name="Publisher" type="bs:String32" />
</xs:schema>
新主文件.xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
xmlns="http://bookshop.com"
targetNamespace="http://bookshop.com"
xmlns:cs="http://custombookshop.com">
<xs:import schemaLocation="added.xsd" namespace="http://custombookshop.com"/>
<xs:redefine schemaLocation="original.xsd">
<xs:complexType name="Book">
<xs:complexContent>
<xs:extension base="Book">
<xs:sequence>
<xs:element ref="cs:Publisher" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:redefine>
</xs:schema>
测试.xml
<?xml version="1.0"?>
<Book xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
xmlns="http://bookshop.com"
targetNamespace="http://bookshop.com"
xs:schemaLocation="newMainfile.xsd"
xmlns:cs="http://custombookshop.com">
<Author>Frank Herbert</Author>
<Title>Dune</Title>
<cs:Publisher>Ace</cs:Publisher>
</Book>
但是,这不会产生我可以验证的东西。将 xml 和 xsd 添加到我的 c# 项目的工作目录后,运行以下代码不起作用。
var path = @"test.xml";
XmlSchemaSet schema = new XmlSchemaSet();
schema.Add("", "newMainfile.xsd");
XmlReader rd = XmlReader.Create(path);
XDocument doc = XDocument.Load(rd);
doc.Validate(schema, ValidationEventHandler);
出现异常情况
“System.Xml.Schema.XmlSchemaException:'targetNamespace 参数 '' 应该与 targetNamespace 的值相同 架构的“http://bookshop.com”。'"
用命名空间“http://bookshop.com”替换 schema.Add("", "newMainfile.xsd"); 中的“”; 也不会验证,而是会产生错误。
System.Xml.Schema.XmlSchemaException:“如果 <'redefine'> 包含除 <'annotation'> 之外的任何子级,则必须成功解析“SchemaLocation”。”
我是否错过了某种重要的步骤?感谢您的时间和回复。
所以问题是
XmlSchemaSet
类的默认解析器实际上并不支持相对文件路径。要使其发挥作用,您可以:
<xs:redefine schemaLocation="C:\temp\whatever\original.xsd">
或 XmlSchema
的实例预加载所有必需的 XmlPreloadedResolver
。void Main()
{
// put all your XSD files to a single folder path
var basePath = @"C:\temp\so76168480";
var path = Path.Combine(basePath, @"test.xml");
// see method definition below
var preloader = PreLoadXmlSchemas(basePath);
XmlSchemaSet schemaSet = new XmlSchemaSet() {
XmlResolver = preloader
};
schemaSet.Add("http://bookshop.com", Path.Combine(basePath, "newMainfile.xsd"));
XmlReader rd = XmlReader.Create(path);
XDocument doc = XDocument.Load(rd);
doc.Validate(schemaSet, (i, e) => {
// should be ok
});
}
public static XmlPreloadedResolver PreLoadXmlSchemas(string directoryPath)
{
if (directoryPath == null) throw new ArgumentNullException(nameof(directoryPath));
var directoryInfo = new DirectoryInfo(directoryPath);
FileInfo[] additionalXsds = directoryInfo.GetFiles("*.xsd");
var xmlPreloadedResolver = new XmlPreloadedResolver();
foreach (FileInfo xsd in additionalXsds)
{
xmlPreloadedResolver.Add(new Uri($"file://{xsd.FullName}"), File.OpenRead(xsd.FullName));
}
return xmlPreloadedResolver;
}
XmlPreloadedResolver 可在 .NET Framework、.NET Core 和 .NET 5+ 上使用,因此应该可以立即使用。