在Node.js中用Saxon-JS通过参数复用XSLT处理不同XML输入
解决Saxon-JS中XSLT动态参数化XPath的问题
问题背景
需要用同一份XSLT处理结构不同的输入XML,通过参数传递XPath表达式提取对应节点值,但当前代码直接输出XPath字符串而非解析后的值,无法实现XSLT复用。
核心原因
当前XSLT里xsl:value-of select="$xpathId"只是读取参数的字符串值,并没有将其作为XPath表达式解析执行。XSLT 3.0提供的fn:evaluate()函数支持动态计算字符串形式的XPath表达式,正好解决这个问题。
解决方案
1. 修改XSLT代码
使用fn:evaluate()解析参数传递的XPath字符串,同时指定上下文节点为根节点(/),确保XPath能正确定位到目标元素:
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:param name="providerId" /> <xsl:param name="xpathId" /> <xsl:param name="xpathUrl" /> <xsl:template match="/"> <myXml> <provider> <xsl:value-of select="$providerId" /> </provider> <id> <xsl:value-of select="fn:evaluate($xpathId, /)"/> </id> <url> <xsl:value-of select="fn:evaluate($xpathUrl, /)"/> </url> </myXml> </xsl:template> </xsl:stylesheet>
2. 调整Node.js代码
移除XPath参数的引号包裹,直接传递原始XPath字符串即可:
const inputXmlDoc = await SaxonJS.getResource({ text: inputXml, type: "xml", }); const outputXml = SaxonJS.XPath.evaluate( `transform(map { 'stylesheet-text': $xslt, 'stylesheet-params': map { QName('', 'providerId'): $providerId, QName('', 'xpathId'): $xpathId, QName('', 'xpathUrl'): $xpathUrl, }, 'source-node': ., 'delivery-format': 'serialized' })?output`, inputXmlDoc, { params: { xslt: xsltString, providerId: 'some-provider-id', xpathId: '/format1/some_id', xpathUrl: '/format1/the_uri' }, }, );
复用XSLT处理不同输入XML
处理format2结构的XML时,仅需修改参数中的XPath表达式:
params: { xslt: xsltString, providerId: 'provider2', xpathId: '/format2/also_the_id', xpathUrl: '/format2/url_field' }
此时会输出正确的结果:
<myXml> <provider>provider2</provider> <id>9dac9085-99b3-4d52-aa56-fa59fc41e066</id> <url>https://example2.com</url> </myXml>
内容的提问来源于stack exchange,提问作者thomaswr
相关产品推荐
相关产品推荐

