如何使用 SaxonCS 正确关闭通过 xsl:result-document 生成的文件?

How to close a file produced via xsl:result-document with SaxonCS correctly?

我正在 Windows 机器上编写 C# 控制台应用程序 (.NET 6) 运行 将 XSLT 转换作为批处理:它从 XML 文件中读取参数集(然后作为参数传递给相应的样式表)并使用 SaxonCS 执行转换。 (参数总是包含初始模板和源文件的路径,该路径正在通过所述初始模板中的 doc($path-to-source) 读入变量)。

对于每个转换,都会实例化一个表示 XSL 转换的对象。在诸如控制台输出等其他事情中,关于转换,它是这样做的:

// Instantiate SaxonCS Processor processor = new();
XsltCompiler compiler = processor.NewXsltCompiler(); 
compiler.BaseUri = new Uri(pathToXsl); 
XsltTransformer transformer = compiler.Compile(File.OpenRead(pathToXsl)).Load(); 

// Set params used by the stylesheet, using ExternalParams (a Dictionary populated earlier 
// with values read from the configuration file).
foreach (var parameter in ExternalParams) { transformer.SetParameter(parameter.Key, parameter.Value); } 
transformer.InitialTemplate = new QName(parametrizedInitialTemplate);

// perform transformation
XdmDestination result = new(); // effectively unused
transformer.Run(result); 
transformer.Close(); 
result = null; // result is not needed: The processor already serialized it because of xsl:result-document()

效果很好 - 直到我尝试使用一个文件,该文件是早期转换的结果,在样式表中使用 xsl:result-document href="{filepath}" 编写,作为稍后进行另一个转换的输入。然后这给了我一个

System.IO.IOException: 'The process cannot access the file '..(some file path)..' because it is being used by another process.'

换句话说:

所以我无法释放资源/无法在转换完成后关闭生成的输出文件。

运行 完全相同的配置文件和控制台应用程序,但在其自己的进程中调用 Saxon 9-HE (Java) 工作得很好(但非常慢);那么没有文件访问问题:

Process proc = new();
ProcessStartInfo startInfo = new()
{
   Arguments = @$"-cp {saxonJarPath} net.sf.saxon.Transform {string.Join(" ", XslParams)} -xsl:{XslPath} -it:{InitialTemplate}",
   FileName = "java",
   RedirectStandardOutput = true,
   RedirectStandardError = true,
   UseShellExecute = false,
   CreateNoWindow = true
};            
proc.StartInfo = startInfo;
proc.Start();
proc.WaitForExit();

这显然不是一个理想的解决方案,我真的很想加快整个过程并摆脱 Java 依赖性 - 这就是为什么我试图让它与 SaxonCS 一起工作。

不幸的是,我不能做“真正的流水线”(如 Saxon 附带的代码示例之一所示),因此直接使用结果作为下一个的输入,因为整个事情都必须配置外部(并非每个结果都是下一次转换的输入)。

(因为 explanations regarding ResultDocumentHandler,我试过 processor.SetProperty(Saxon.Api.Feature.ALLOW_MULTITHREADING, false);,但没有用。)

那么:如何防止通过xsl:result-文档生成的文件即使在转换完成后也被锁定?

我想明确设置

transformer.BaseOutputUri = new Uri(pathToXsl);
transformer.ResultDocumentHandler = (href, baseUri) => { 
    var serializer = processor.NewSerializer();
    var fs = File.Open(new Uri(baseUri, href).LocalPath, FileMode.Create, FileAccess.Write);
    serializer.OutputStream = fs;
    serializer.OnClose(() => { fs.Close(); });
    return serializer;
};

避免问题。