FXSL带序列参数的柯里化函数问题:序列空项丢失
柯里化后序列空项丢失的问题分析与解决思路
嘿,我之前也碰到过类似的情况,咱们来拆解下这个问题。你参考FXSL的testFunc-curry.xsl里的t:mult3示例做了修改,把前两个参数改成了序列,结果柯里化之后序列里的空项全没了对吧?先把你贴的代码片段放出来方便大家参考:
<xsl:function name="foo:bar" as="xs:anyAtomicType"> <xsl:param name="headers" as="xs:string*"/> <xsl:param name="row" as="xs:anyAtomicType*"/> <xsl:param name="column" as="xs:string"/> <xsl:message select="$column"/> <xsl:message select="count($row)"/> <xsl:value-...
为什么空项会丢失?
FXSL的柯里化实现里,很多时候会默认对传入的序列做“清理”——比如过滤掉空原子值、空节点这类内容。这是因为早期XSLT处理逻辑里,空项经常会导致后续函数调用出现意外行为,所以柯里化工具的内部模板可能加了类似[.!='']或者显式过滤空值的逻辑,把这些空项直接丢掉了。另外,如果柯里化过程中把序列拆解成单个参数传递,空项也会被自动忽略,因为XSLT的参数列表不会保留空的位置。
怎么解决这个问题?
这里给你几个可行的思路:
- 修改FXSL柯里化的核心逻辑:找到FXSL里负责柯里化的模板(比如
curry相关的模板),检查里面有没有过滤空项的代码。如果有,把那部分过滤条件去掉,或者调整成只过滤你真正不需要的空内容,保留你需要的序列空项。 - 用占位符替换空项:在把序列传给柯里化函数之前,先把空项替换成一个特殊的占位符(比如
'__EMPTY__'或者空字符串'',只要和你的有效数据不冲突就行),然后在目标函数foo:bar内部再把占位符还原为空项。示例代码如下:<!-- 传递参数前预处理序列 --> <xsl:variable name="processed-row" select=" for $item in $row return if ($item instance of xs:empty) then '__EMPTY__' else $item "/> <!-- 把处理后的序列传给柯里化函数 --> <!-- 在foo:bar里还原空项 --> <xsl:function name="foo:bar" as="xs:anyAtomicType"> <xsl:param name="headers" as="xs:string*"/> <xsl:param name="row" as="xs:anyAtomicType*"/> <xsl:param name="column" as="xs:string"/> <xsl:variable name="actual-row" select=" for $item in $row return if ($item eq '__EMPTY__') then () else $item "/> <!-- 后续用$actual-row代替$row进行处理 --> <xsl:message select="$column"/> <xsl:message select="count($actual-row)"/> <xsl:value-... </xsl:function> - 用数组包装序列(XSLT 3.0+):如果你的环境支持XSLT 3.0,可以把序列包装成数组传递。数组会完整保留所有元素,包括空项,不会被柯里化工具拆解或过滤。示例:
<!-- 把序列包装成数组 --> <xsl:variable name="row-array" as="array(xs:anyAtomicType?)" select="array{$row}"/> <!-- 传递数组给柯里化函数 --> <!-- 在foo:bar里解开数组 --> <xsl:function name="foo:bar" as="xs:anyAtomicType"> <xsl:param name="headers" as="xs:string*"/> <xsl:param name="row-array" as="array(xs:anyAtomicType?)"/> <xsl:param name="column" as="xs:string"/> <xsl:variable name="row" select="$row-array?*"/> <!-- 现在$row里就包含所有原始项,包括空项了 --> <xsl:message select="$column"/> <xsl:message select="count($row)"/> <xsl:value-... </xsl:function>
你可以根据自己的XSLT版本和项目限制选择合适的方案,大概率调整参数传递方式或者修改柯里化的过滤逻辑就能解决问题。
内容的提问来源于stack exchange,提问作者Phil
相关产品推荐
相关产品推荐

