如何在不更改目标命名空间的情况下扩展命名空间中的复杂类型

问题描述 投票:0回答:1

参考此:其他帖子 我正在尝试做与另一篇文章中的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”。”

我是否错过了某种重要的步骤?感谢您的时间和回复。

c# xml xsd
1个回答
0
投票

所以问题是

XmlSchemaSet
类的默认解析器实际上并不支持相对文件路径。要使其发挥作用,您可以:

  • 更改 schemaLocation 属性以指向完整文件路径,例如
    <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+ 上使用,因此应该可以立即使用。

© www.soinside.com 2019 - 2024. All rights reserved.