如何在 xpath 表达式中实现具有名称的用户定义函数?
Posted
技术标签:
【中文标题】如何在 xpath 表达式中实现具有名称的用户定义函数?【英文标题】:How can I implement a user-defined function with a name in the xpath expression? 【发布时间】:2020-04-17 03:08:16 【问题描述】:我正在使用 XSLT。我知道Inline Function Expressions,有没有办法在 xpath 表达式中声明一个命名函数?因为我需要函数名来实现递归调用。
【问题讨论】:
使用 XSLT 和xsl:function
可以轻松完成,在纯 XPath 中使用 let
。
如何在纯 XPath 中做到这一点?你想给我看一个代码 sn-p 吗?
@cmf41013 这是一个更新的例子:***.com/questions/58101443/…
【参考方案1】:
在 XSLT 中,我只是建议使用 xsl:function
,因为这样您的函数就有了一个名称,并且您可以在函数体内递归地调用它。
至于纯 XPath 3,Dimitre 几年前在 https://dnovatchev.wordpress.com/2012/10/15/recursion-with-anonymous-inline-functions-in-xpath-3-0-2/ 中使用 let
和高阶函数(不幸的是,Saxon 9 HE 不支持该特性)探索了这条路径,我认为他的代码使用函数类型语法与最终规范不太一致,因此他的示例需要
let $f :=
function($n as xs:integer,
$f1 as function(xs:integer, function(*)) as xs:integer) as xs:integer
if ($n eq 0)
then 1
else $n * $f1($n -1, $f1)
,
$F := function($n as xs:integer) as xs:integer
$f($n, $f)
return $F(5)
可以简写为
let $f :=
function($n as xs:integer,
$f1 as function(xs:integer, function(*)) as xs:integer) as xs:integer
if ($n eq 0)
then 1
else $n * $f1($n -1, $f1)
,
$F := $f(?, $f)
return $F(5)
我认为考虑到最新允许的语法。
【讨论】:
@cmf41013 有关更新的示例,请参阅此答案:***.com/questions/58101443/… Martin,$F := $f(?, $f)
的表达太棒了!然而,这使得F()
的定义不可读——对于读者来说F()
的参数类型是什么并不明显,他必须研究其他函数才能理解这些类型是什么...... - - 与显式定义相比,有些东西相当耗时且容易出错。即使我们设计了一个可以生成 F() 完整签名的工具,这仍然很耗时且难以执行——换句话说,不方便.
@DimitreNovaatchev,我明白你的意思,但我只是想提供一个最新的 XPath 版本提供的选项,我并不打算支持我引用的代码。总的来说,我认为这取决于角度,例如在 C# 中,当他们引入 var
来声明变量而不输入变量时,我最初的想法是我不需要它并且永远不会使用它;但现在我认为它在 C# 中使用 Saxon 并深入研究其复杂的 API 时很有帮助。
是的,但是我正在编写一个函数库,其中每个函数都必须有一个明确定义的签名——否则我们将如何向目标受众解释函数采用什么类型的参数以及它们的含义是什么?另一方面,“内部”或“工作者”函数旨在保持不可见——也就是说,应该隐藏已发布函数的实际实现。【参考方案2】:
没有办法在 XPath 中声明命名函数; XPath 3.1 只允许匿名内联函数,并且这些函数不能递归。有人告诉我,有一种方法可以使用一种称为 Y-combinators 的技术在匿名函数中实现递归,但它相当令人难以置信,我从来没有想过它。正如 Martin 所建议的,您最好的方法是将这部分逻辑放在 XSLT 级别。
【讨论】:
回复:“这真是令人难以置信,我从来没有想过它。” ...引用上面@martin_honnen 的评论:“你可以很容易地用纯XPath 做到这一点”:) 你们说的是同一件事吗? 当我试图理解 Y 组合子时,我确实发现它令人难以置信;我发现 Dimitre 的方法非常简单,但我一直不明白为什么一种容易遵循而另一种则不然。 (所以:我认为 MK 和 MH 说的是同一件事,但我可能是错的。)以上是关于如何在 xpath 表达式中实现具有名称的用户定义函数?的主要内容,如果未能解决你的问题,请参考以下文章