如何为内存中的XSLT样式表设置SystemId?
XSLT中
document('')在String类型StreamSource下的失效问题 我有一些XSLT样式表,通过匿名document('')函数实现内部查找表,示例代码如下:
<!-- example the lookup table data --> <ref:data xmlns:ref="urn:inline-data"> <phrasebook> <!-- English --> <lang code="en"> <phrase code="USD_PREFIX">$ </phrase> <phrase code="GBP_PREFIX">£</phrase> <phrase code="EUR_PREFIX">€</phrase> <phrase code="JPY_PREFIX">¥</phrase> </lang> ... </phrasebook> </ref:data> <!-- the lookup table variable I can use elsewhere --> <xsl:variable name="phrasebook" select="document('')/xsl:stylesheet/ref:data/phrasebook" xmlns:ref="urn:inline-data"/>
(注:ref命名空间实际在样式表定义中,此处为简洁单独列出)
问题是:使用String类型的StreamSource运行这类样式表会失败,但用File类型的StreamSource则正常。已知原因是Transformer无法获取StreamSource上未设置的SystemId,但对于内存中的String,应该将SystemId设置为什么值?
解决方案
当使用内存中的String作为XSLT源时,你需要给StreamSource设置一个虚拟的合法URI,这个值不需要对应真实存在的文件,只要符合URI格式规范即可。
核心逻辑
document('')的作用是加载当前样式表本身作为文档节点,XSLT处理器需要一个基准URI来解析这个相对引用(空字符串代表当前文档)。即使是内存中的字符串,设置虚拟SystemId就能让处理器完成这个解析逻辑。
具体设置示例
可以选择以下任意一种合法URI:
- 虚拟文件路径:
"file:///dummy.xsl" - URN格式:
"urn:xslt:internal-stylesheet" - 甚至自定义的字符串格式(只要符合URI规范)
Java代码示例
String xsltContent = "...你的XSLT字符串内容..."; StreamSource xsltSource = new StreamSource(new StringReader(xsltContent)); // 设置虚拟SystemId xsltSource.setSystemId("file:///dummy.xsl"); TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer = factory.newTransformer(xsltSource); // 后续转换逻辑...
补充说明
- 这个虚拟SystemId不需要指向真实文件,处理器仅用它确定当前样式表的基准URI,从而正确解析
document('')引用。 - 若不设置SystemId,处理器无法定位基准URI,会导致
document('')无法找到样式表内部的ref:data节点,最终引发错误。
内容的提问来源于stack exchange,提问作者Ben Ketteridge
相关产品推荐
相关产品推荐

