xml 架构编译的 Full Framework 和 .NET Core 的不同行为
different behavior for Full Framework and .NET Core for xml schema compilation
这是我的验证码:
string xsdPath = "base.xsd";
XDocument doc = XDocument.Load(xmlPath);
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("http://some.domain.org", xsdPath);
schemas.Compile();
bool isValid = true;
doc.Validate(schemas, (o, e) => {
res.AddMessage(MessageSeverities.Error, $"{e.Severity}:{e.Message}");
isValid = false;
});
if ( isValid ) {
res.AddMessage(
MessageSeverities.Notice,
$"{formFile.FileName} is valid!");
}
此代码在桌面应用程序 (.net 4.6) 中使用时运行良好
代码在 .net 核心 asp 2.1 控制器中使用时失败,schemas.Compile();
引发以下异常:
XmlSchemaException: Type 'http://some.domain.org:tAccountingItemTypes' is not declared.
asp 核心应用中似乎没有加载相关的架构文件。如何强制加载相关模式?
架构是:
base.xsd
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema
targetNamespace="http://some.domain.org"
xmlns="http://some.domain.org"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:include id="enums" schemaLocation="enums.xsd"/>
<xs:complexType name="tAccountingLines">
<xs:sequence>
<xs:element name="AccountingLine" type ="tAccountingLine"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tAccountingLine">
<xs:sequence>
<xs:element name="AccountingType" type="tAccountingItemTypes"></xs:element>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
enums.xsd
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema
targetNamespace="http://some.domain.org"
xmlns="http://some.domain.org"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:simpleType name="tAccountingItemTypes">
<xs:restriction base="xs:string">
<xs:enumeration value="V1"/>
<xs:enumeration value="V2"/>
<xs:enumeration value="V3"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
我刚刚试过了,它没有加载包含的架构的原因是它用来加载它的解析器是 null
。这应该可以解决它:
schemas.XmlResolver = new XmlUrlResolver();
我做了一些挖掘,发现这是 Desktop 和 Core 之间已知的行为变化,即 documented here:
If the schema being added imports another schema through external URI, Core does not allow resolving that URI by default while Desktop does. To allow the resolution on Core, the following needs to be called before adding the schema: AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
显然,除了开关之外,您还可以明确设置解析器,这样您就不会使用默认值。
这是我的验证码:
string xsdPath = "base.xsd";
XDocument doc = XDocument.Load(xmlPath);
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("http://some.domain.org", xsdPath);
schemas.Compile();
bool isValid = true;
doc.Validate(schemas, (o, e) => {
res.AddMessage(MessageSeverities.Error, $"{e.Severity}:{e.Message}");
isValid = false;
});
if ( isValid ) {
res.AddMessage(
MessageSeverities.Notice,
$"{formFile.FileName} is valid!");
}
此代码在桌面应用程序 (.net 4.6) 中使用时运行良好
代码在 .net 核心 asp 2.1 控制器中使用时失败,schemas.Compile();
引发以下异常:
XmlSchemaException: Type 'http://some.domain.org:tAccountingItemTypes' is not declared.
asp 核心应用中似乎没有加载相关的架构文件。如何强制加载相关模式?
架构是:
base.xsd
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema
targetNamespace="http://some.domain.org"
xmlns="http://some.domain.org"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:include id="enums" schemaLocation="enums.xsd"/>
<xs:complexType name="tAccountingLines">
<xs:sequence>
<xs:element name="AccountingLine" type ="tAccountingLine"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="tAccountingLine">
<xs:sequence>
<xs:element name="AccountingType" type="tAccountingItemTypes"></xs:element>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
enums.xsd
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema
targetNamespace="http://some.domain.org"
xmlns="http://some.domain.org"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:simpleType name="tAccountingItemTypes">
<xs:restriction base="xs:string">
<xs:enumeration value="V1"/>
<xs:enumeration value="V2"/>
<xs:enumeration value="V3"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
我刚刚试过了,它没有加载包含的架构的原因是它用来加载它的解析器是 null
。这应该可以解决它:
schemas.XmlResolver = new XmlUrlResolver();
我做了一些挖掘,发现这是 Desktop 和 Core 之间已知的行为变化,即 documented here:
If the schema being added imports another schema through external URI, Core does not allow resolving that URI by default while Desktop does. To allow the resolution on Core, the following needs to be called before adding the schema:
AppContext.SetSwitch("Switch.System.Xml.AllowDefaultResolver", true);
显然,除了开关之外,您还可以明确设置解析器,这样您就不会使用默认值。