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

Schxslt与SaxonCS编译Schematron时base-uri()返回空值问题

问题描述

我有一份XML文件和对应的.sch校验文件,校验规则中包含<xsl:param name="dosyaAdi" select="base-uri()"/>,但base-uri()函数返回空值,导致依赖该函数的校验规则全部失效。

我已通过Schxslt的compile-for-svrl.xsl编译.sch文件,再将XML与生成的XSLT传入Saxon进行转换,转换过程正常,但推测Sch中的base-uri()返回空值,致使2条相关校验规则失败。代码示例如下:

string schxsltSvrlXsltResource = @"SchematronSchxsltSaxonCSValidator/schxslt195/compile-for-svrl.xsl";
var schxsltResourceUri = UriUtils.GetLocationUri(schxsltSvrlXsltResource, Assembly.GetExecutingAssembly());

var resolver = new Resolver();

var settings = new XmlReaderSettings() { XmlResolver = resolver };

var processor = new Processor(true);
var xsltCompiler = processor.NewXsltCompiler();

using var schxsltReader = XmlReader.Create(schxsltResourceUri.AbsoluteUri, settings);


var transformer = xsltCompiler.Compile(schxsltReader).Load30();
//var compiledSchxslt = xsltCompiler.Compile(schxsltReader).Load30();

var compiledSchematron = new XdmDestination();
compiledSchematron.BaseUri = new Uri(new FileInfo(inputSch).FullName);

using var schemaStream = File.OpenRead(inputSch);

transformer.Transform(schemaStream, compiledSchematron);

var xsltCompiler2 = processor.NewXsltCompiler();

var schematronValidator = xsltCompiler2.Compile(compiledSchematron.XdmNode).Load30();

var svrlResult = new XdmDestination(); 
using var instanceStream = File.OpenRead(inputXml);
//schematronValidator.Run(svrlResult);
schematronValidator.Transform(instanceStream, svrlResult);

XmlDocument doc = new XmlDocument();
doc.LoadXml(svrlResult.XdmNode.OuterXml);

var failedNodes = doc.GetElementsByTagName("svrl:failed-assert");
foreach (System.Xml.XmlNode node in failedNodes)
{

}
解决方案

原因分析

使用File.OpenRead读取文件流时,Saxon无法获取文件的Base URI元数据,导致base-uri()函数返回空值。无论是编译.sch还是校验XML阶段,仅传递流都会丢失文件的原始路径信息。

修复方案

方案1:传递文件URI而非流

直接基于文件URI创建节点,保留完整的Base URI信息:

  • 编译.sch文件时:
    // 替换原schemaStream相关代码
    var schUri = new Uri(new FileInfo(inputSch).FullName);
    transformer.Transform(new UriXdmNode(processor, schUri), compiledSchematron);
    
  • 校验XML文件时:
    // 替换原instanceStream相关代码
    var xmlUri = new Uri(new FileInfo(inputXml).FullName);
    schematronValidator.Transform(new UriXdmNode(processor, xmlUri), svrlResult);
    

方案2:手动传递参数

如果必须使用流,可以直接向校验XSLT传递dosyaAdi参数,绕过base-uri()函数:

// 在调用Transform前添加参数设置
schematronValidator.SetParameter(new QName("", "", "dosyaAdi"), new XdmAtomicValue(new FileInfo(inputXml).FullName));

关键提示

  • base-uri()的返回值完全依赖节点是否携带URI信息,流模式读取会丢失该元数据。
  • 使用UriXdmNode是最贴合Schxslt设计的解决方案,能完整保留文件的URI上下文。
  • 手动传参适合无法直接获取文件URI的场景,比如处理内存中的XML内容。

内容的提问来源于stack exchange,提问作者Cemal Çelik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 21:43:12