Saxon CS doTransform Windows下无法识别已存在转换输出文件问题
问题根因
Windows环境下Saxon CS无法识别已存在文件,是两个路径处理问题叠加导致的:
- 代码中存在硬编码
/路径分隔符的逻辑,Windows原生路径分隔符为\,虽然.NET的IO接口可兼容识别混合分隔符的路径,但Saxon内置的URI解析器对混合分隔符的Windows路径兼容性极差,归一化处理时会生成错误的目标地址。 - Saxon CS默认会将传入的文件路径按RFC 3986标准解析为URI,直接传入原生Windows路径时,若路径存在未转义特殊字符、分隔符不统一的情况,内部解析逻辑会生成错误的文件URI,最终触发文件不存在异常。
- 第一次转换能正常执行,是因为初始传入的XSL文件路径由解压逻辑通过.NET标准IO接口生成,无分隔符混乱问题;第一次转换生成stage1.out后,后续传参引入的路径格式错误会直接导致第二次转换找不到目标文件。
修复方案
按以下步骤调整即可兼容Mac、Windows双环境:
- 完全移除所有硬编码的路径分隔符,所有路径拼接统一使用
Path.Combine处理,禁止手动拼接/或\。例如代码中
arguments[Constants.SourceDir] + "/" + schematronFile的写法,需要替换为Path.Combine(arguments[Constants.SourceDir], schematronFile) - 所有路径传入Saxon参数前,显式转换为标准file URI格式,不要直接传原生文件路径,避免Saxon内部解析出错。可直接使用.NET内置的
new Uri(filePath).AbsoluteUri方法做转换,该方法会自动适配不同操作系统的路径规则,生成合规的URI字符串:- Mac环境下会生成
file:///var/folders/xxx/xxx格式的标准URI - Windows环境下会生成分隔符统一、转义正确的
file:///C:/Users/xxx/xxx格式URI,不会出现解析偏差
- Mac环境下会生成
修复后代码示例
{ try { var transform = new Transform(); // 移除硬编码斜杠,统一用Path.Combine拼接路径 var stage1SchematronPath = Path.Combine(arguments[Constants.SourceDir], schematronFile); transform.doTransform(GetTransformArguments(arguments[Constants.InStage1File], stage1SchematronPath, arguments[Constants.Stage1Out])); transform.doTransform(GetTransformArguments(arguments[Constants.InStage2File], arguments[Constants.Stage1Out], arguments[Constants.Stage2Out])); transform.doTransform(GetFinalTransformArguments(arguments[Constants.InStage3File], arguments[Constants.Stage2Out], arguments[Constants.Stage3Out])); Log.Information("Stage 3 out file written to : " + arguments[Constants.Stage3Out]); return true; } catch (FileNotFoundException ex) { Log.Warning("Cannot find files" + ex); return false; } } /// <summary> /// 本地路径转Saxon可识别的标准file URI /// </summary> private static string ToSaxonFileUri(string localPath) { // 先解析为全路径,避免相对路径导致的解析偏差 var fullPath = Path.GetFullPath(localPath); return new Uri(fullPath).AbsoluteUri; } private static string[] GetTransformArguments(string xslFile, string inputFile, string outputFile) { return new[] { "-xsl:" + ToSaxonFileUri(xslFile), "-s:" + ToSaxonFileUri(inputFile), "-o:" + ToSaxonFileUri(outputFile) }; } private static string[] GetFinalTransformArguments(string xslFile, string inputFile, string outputFile) { return new[] { "-xsl:" + ToSaxonFileUri(xslFile), "-s:" + ToSaxonFileUri(inputFile), "-o:" + ToSaxonFileUri(outputFile), "allow-foreign=true", "generate-fired-rule=true" }; }
验证注意事项
- 不要手动拼接file URI字符串,不同操作系统的路径转义规则存在差异,交给.NET内置Uri类处理可规避绝大多数跨平台路径问题
- 无需排查临时目录权限:权限问题会触发专门的权限异常,不会返回文件不存在的报错
- 调整后可在Windows环境下打印传入Saxon的URI日志,确认URI以
file:///开头、盘符后路径分隔符统一为/、无未转义特殊字符即可正常运行
内容的提问来源于stack exchange,提问作者Cahir Mc Cullagh
相关产品推荐
相关产品推荐

