You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在C#中使用XSL文件进行Schematron XML验证报错求助

在C#中实现Schematron验证:解决“Operation is not allowed”错误及相关疑问

首先,咱们拆解你遇到的两个核心问题:一是validator.Validate(xmlStream)报错的原因,二是微软文档为何侧重XSD而非Schematron的疑问。

一、分析“Operation is not allowed”错误的可能原因

你用的第三方Schematron库出现这个报错,大概率是以下两个细节没处理到位:

  • 内存流位置未重置:当你把字符串转成MemoryStream后,流的指针默认停在末尾,库加载时会读不到任何内容。
  • 输入的XSL文件类型不对:有些Schematron库要求输入的是编译后的XSLT文件(由原始.sch Schematron schema转换而来),而不是直接用.sch源文件。

修复现有代码的小调整

先试试给内存流加上位置重置,修改你的代码:

public static bool SchemaTronValidation(string xml, string xsl) { 
    // 创建XSL流并重置位置
    var xslBytes = Encoding.UTF8.GetBytes(xsl ?? "");
    var xslStream = new MemoryStream(xslBytes);
    xslStream.Position = 0; // 关键:重置流指针到开头
    
    Schema schematronSchema = new Schema(); 
    schematronSchema.Load(xslStream); 
    Validator validator = new Validator(); 
    validator.AddSchema(schematronSchema); 
    
    // 创建XML流并重置位置
    var xmlBytes = Encoding.UTF8.GetBytes(xml ?? "");
    var xmlStream = new MemoryStream(xmlBytes);
    xmlStream.Position = 0; // 同样重置指针
    
    var res = validator.Validate(xmlStream); 
    return res.IsValid; // 注意:应该返回验证结果的IsValid,而非固定true
}

如果还是报错,检查你的xsl参数是不是编译后的XSLT——如果是原始.sch文件,需要先把它转换成XSLT格式(后面会讲转换方法)。

二、微软文档为何用XSD而非Schematron?

这个疑问很合理:.NET原生完全支持XSD(XML Schema Definition),因为XSD是W3C标准的XML结构验证方案,适合校验元素、属性的类型、结构、必填性等基础规则。而Schematron是基于XSLT的规则型验证,可以实现更灵活的自定义逻辑(比如跨节点的关联校验),但.NET并没有原生提供Schematron的API,所以微软文档里主要讲解原生支持的XSD用法。

三、更可靠的C# Schematron实现方案:用XslCompiledTransform手动实现

第三方库可能存在版本兼容问题,用.NET自带的XslCompiledTransform实现Schematron验证反而更可控——本质上Schematron验证就是把.sch文件转换成XSLT,再用XSLT处理XML生成验证报告。

步骤1:编译Schematron Schema到XSLT

首先需要用ISO官方的Schematron骨架样式表(比如iso_schematron_skeleton_for_xslt1.xsl)把你的.sch文件转换成XSLT。你可以把这个骨架文件嵌入到项目中,然后用代码动态转换:

// 把Schematron(.sch)编译成XSLT
public static string CompileSchematronToXslt(string schematronContent)
{
    using var schematronStream = new MemoryStream(Encoding.UTF8.GetBytes(schematronContent));
    var xsltTransform = new XslCompiledTransform();
    // 加载ISO Schematron骨架样式表(确保文件路径正确)
    xsltTransform.Load("iso_schematron_skeleton_for_xslt1.xsl");
    
    using var outputStream = new MemoryStream();
    xsltTransform.Transform(schematronStream, null, outputStream);
    outputStream.Position = 0;
    
    using var reader = new StreamReader(outputStream);
    return reader.ReadToEnd();
}

步骤2:用XSLT执行验证并解析结果

拿到编译后的XSLT后,就可以用它处理XML,生成验证报告,然后解析报告判断是否验证通过:

// 定义Schematron结果的命名空间
private static readonly XNamespace SchematronNs = "http://purl.oclc.org/dsdl/schematron";

public static bool ValidateXmlWithSchematron(string xmlContent, string compiledXslt)
{
    using var xmlStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlContent));
    using var xsltStream = new MemoryStream(Encoding.UTF8.GetBytes(compiledXslt));
    
    var xsltTransform = new XslCompiledTransform();
    xsltTransform.Load(xsltStream);
    
    using var resultStream = new MemoryStream();
    xsltTransform.Transform(xmlStream, null, resultStream);
    resultStream.Position = 0;
    
    // 加载验证结果文档
    var resultDoc = XDocument.Load(resultStream);
    // 检查是否有失败的断言或报告
    var failedAsserts = resultDoc.Descendants(SchematronNs + "failed-assert");
    var errorReports = resultDoc.Descendants(SchematronNs + "report");
    
    // 没有失败项则验证通过
    return !failedAsserts.Any() && !errorReports.Any();
}

使用示例

// 读取Schematron schema文件内容
var schematronContent = File.ReadAllText("your-schema.sch");
// 编译成XSLT
var compiledXslt = CompileSchematronToXslt(schematronContent);
// 读取要验证的XML
var xmlContent = File.ReadAllText("your-document.xml");
// 执行验证
bool isValid = ValidateXmlWithSchematron(xmlContent, compiledXslt);

这种实现方式完全依赖.NET原生API,没有第三方库的兼容问题,可控性也更强。

内容的提问来源于stack exchange,提问作者Joseph

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:04:36