Saxon下网络路径XSLT转换报URI has an authority component错误
在网络共享位置执行XSLT转换创建文档时触发URI has an authority component错误,本地PC运行同一段脚本无异常,运行环境为Saxon HE 9.7 .Net。
初始版本脚本通过base-uri()获取路径拼接xsl:result-document的输出地址时,本地路径被解析为file:/C:/[somepath]/DITA/Operator%20Manual/om_CSUV_info_en_us.xml,手动做字符串替换调整路径格式后,网络路径被解析为file://[somepath]/Publishing/DITA/Operator%20Manual/om_CSUV_info_en_us.xml,直接触发上述报错。
报错核心是file协议URI的规则限制:
- 本地磁盘路径的file URI格式为
file:/[盘符]/路径,不存在authority(主机/权限标识)组件 - UNC网络共享路径的标准file URI格式为
file://[主机名/共享名]/路径,双斜杠后的主机/共享名部分就是URI规范定义的authority组件
你使用的Saxon HE 9.7 .Net版本默认开启安全限制,禁止直接向带authority组件的file协议URI写入文件,因此本地运行正常、网络路径触发报错。手动替换字符串的操作刚好拼出了符合UNC规范的带authority的URI,直接触发了拦截逻辑。
方案1:升级Saxon版本(成本最低)
Saxon在9.9及之后的稳定版本中已经修复了UNC网络路径写入的兼容问题,直接将Saxon HE升级到9.9+版本,无需修改现有XSLT代码即可正常在网络路径生成输出文件。
方案2:不升级版本的代码调整
如果暂时无法升级Saxon,不要通过字符串替换硬改路径,使用Saxon内置扩展函数自动转换合法路径:
- 首先在XSLT的根标签
xsl:stylesheet上声明Saxon扩展命名空间:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saxon="http://saxon.sf.net/" version="2.0">
- 将原有
directory变量的取值逻辑替换为以下写法,自动将URI转换为.NET环境可识别的合法文件路径:
<xsl:variable name="directory" select="saxon:system-id(substring-before(base-uri(/),'/toc.ditamap'))"/>
其余代码逻辑保持不变即可。
方案3:调整运行配置,无需修改代码
如果不想改动XSLT脚本,可以在调用Saxon执行转换时放开网络路径写入权限:
- 命令行调用Saxon时,追加启动参数
--allow-write-network - 通过.NET代码调用Saxon时,给初始化的Processor对象设置配置:
processor.SetProperty("http://saxon.sf.net/feature/allowWriteNetwork", true);
配置生效后Saxon会跳过对网络路径写入的安全拦截。
注意:不要使用硬编码字符串替换的方式处理路径,不同环境下的盘符、网络共享名格式不固定,硬编码替换的逻辑兼容性极差,换路径就容易再次触发异常,路径处理优先使用内置的URI/路径解析函数。
内容的提问来源于stack exchange,提问作者Diego Schiavon

