【发布时间】:2017-11-20 17:28:41
【问题描述】:
我一直在尝试使用 XSD 文件的层次结构来验证 XML 文件,其中一些文件包含 dtd 文件。通过设置验证标志ProcessInlineSchema 和ProcessSchemaLocation,我成功地根据XML 文件中通过schemaLocation 引用的架构完成了此操作。
但是,对于我的场景,我需要将 XSD 文件与我正在构建的应用程序一起提供,因此应该忽略 schemaLocation(因为它将指向 Web 上的某个位置)。 XML 文件是标准的。
我创建了一个简单的示例来测试我的问题 - 我有以下文件:
main.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="ro:sopa:main" xmlns:main="ro:sopa:main" xmlns:inc="ro:sopa:inc" >
<xs:import namespace="ro:sopa:inc" schemaLocation="included.xsd"/>
<xs:element name="test" type="main:testType"/>
<xs:complexType name="testType">
<xs:sequence>
<xs:element name="test1" type="inc:testInc" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
包含的.xsd
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xs:schema [
<!ENTITY % inc.dtd SYSTEM "inc.dtd">
%inc.dtd;
]>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="ro:sopa:inc">
<xs:simpleType name="testInc">
<xs:restriction base="xs:string">
<xs:pattern value="&test;"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
inc.dtd
<!ENTITY digit "[0-9]{1}">
<!ENTITY alnum "[A-Z]{1}">
<!ENTITY test "&alnum;-&digit;">
示例 XML 文件:
<main:test xsi:schemaLocation="ro:sopa:main D:\schemas\main.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:main="ro:sopa:main">
<test1>A-4</test1>
</main:test>
如果我直接验证 XML 文件中指向的架构,它可以正常工作:
List<string> report = new List<string>();
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.DtdProcessing = DtdProcessing.Parse;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
settings.ValidationEventHandler += new ValidationEventHandler(delegate(object snd, ValidationEventArgs e2)
{
report.Add(e2.Message);
});
XmlReader reader = XmlReader.Create(fileName, settings);
while (reader.Read());
reader.Close();
但是,如果我尝试手动设置 XmlSchemaSet,它将不起作用。
public static string schemaUrl = @"D:\schema\main.xsd";
public static string fileName = @"D:\somewhere\testProd1.xml";
public static void Main(string[] args)
{
List<string> report = new List<string>();
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.DtdProcessing = DtdProcessing.Parse;
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
settings.Schemas = ProvideSchemaSet(report);
settings.ValidationEventHandler += new ValidationEventHandler(delegate(object snd, ValidationEventArgs e2)
{
report.Add(e2.Message);
});
XmlReader reader = XmlReader.Create(fileName, settings);
while (reader.Read()) ;
reader.Close();
}
public static XmlSchemaSet ProvideSchemaSet(List<string> schemaLoadErrors)
{
XmlSchemaSet schemas = new XmlSchemaSet();
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Parse;
XmlReader schemaReader = XmlReader.Create(schemaUrl, settings);
XmlSchema schema = XmlSchema.Read(schemaReader, delegate(object sender, ValidationEventArgs e)
{
schemaLoadErrors.Add(e.Message);
});
schemas.Add(schema);
schemaReader.Close();
schemas.Compile();
return schemas;
}
这将在 schemas.Compile() 上崩溃,说明对象 test1 不存在。仅当我使用 dtd 时才会发生这种情况 - 如果我将 DTD 从架构中取出,它就会正常工作。
我在互联网上搜索的所有内容都是关于 XSD 验证或 DTD 验证的 - 但是我没有找到任何解决方案。有什么建议吗?
注意:我必须使用的模式和 DTD 是标准化的,因此我无法以任何方式更改它们。
【问题讨论】:
标签: c# validation xsd schema dtd