编写有效的XSLT

Pet*_*erg 13 xml xslt

编写有效的XSLT有哪些原则和模式?

当我说"有效"时,我的意思是它

  1. 结构良好,可读性强
  2. 简单,简洁
  3. 高效(即具有良好的性能)

简而言之,我正在寻找XSLT的最佳实践.

我已经看到了关于效率的问题,但如果你无法理解它正在做什么,有效的代码会失去它的价值.

Dim*_*hev 10

I.优雅的XSLT代码


人们经常可以找到漂亮的XSLT代码的例子,特别是当XSLT用作函数式编程语言时.

有关示例,请参阅有关FXSL 2.0的文章 - XSLT 2.0的函数编程库.

作为FP语言,XSLT也是一种声明性语言.除其他外,这意味着一个人声明,指定现有的关系.

这样的定义通常不需要任何额外的代码来产生结果 - 它本身就是它自己的实现,或者是可执行的定义或可执行的规范.

这是一个小例子.

此XPath 2.0表达式定义 " 自然数的最大素数因子 ":

if(f:isPrime($pNum))
  then $pNum
  else
    for $vEnd in xs:integer(floor(f:sqrt($pNum, 0.1E0))),
        $vDiv1 in (2 to $vEnd)[$pNum mod . = 0][1],
        $vDiv2 in $pNum idiv $vDiv1
      return
        max((f:maxPrimeFactor($vDiv1),f:maxPrimeFactor($vDiv2)))
Run Code Online (Sandbox Code Playgroud)

,它的发音在英文,数字的最大素因子pNum是数字本身,如果 pNum 是素数,否则,如果 vDiv1vDiv2是两个因素pNum,则最大素因子pNum是最大素因子的大vDiv1vDiv2.

我们如何使用它来实际计算 XSLT中的最大素数因子?我们简单地将上面的定义包含<xsl:function>...中...得到结果!

 <xsl:function name="f:maxPrimeFactor" as="xs:integer">
  <xsl:param name="pNum" as="xs:integer"/>

  <xsl:sequence select=
   "if(f:isPrime($pNum))
      then $pNum
      else
        for $vEnd in xs:integer(floor(f:sqrt($pNum, 0.1E0))),
            $vDiv1 in (2 to $vEnd)[$pNum mod . = 0][1],
            $vDiv2 in $pNum idiv $vDiv1
          return
            max((f:maxPrimeFactor($vDiv1),f:maxPrimeFactor($vDiv2)))
   "/>
 </xsl:function>
Run Code Online (Sandbox Code Playgroud)

然后,我们可以计算任何自然数的MPF,例如:

f:maxPrimeFactor(600851475143) = 6857

至于效率,这个转换只需0.109秒.

优雅和高效的XSLT代码的其他示例:

II.一些规则


以下是编写"高质量XSLT代码"的一些规则,取自Mukul Ghandi的博客.

可以使用Mukul开发工具检查/执行它们:

  1. DontUseDoubleSlashOperatorNearRoot:避免在大树的根附近使用运算符.

  2. DontUseDoubleSlashOperator:避免在XPath表达式中使用运算符//.

  3. SettingValueOfVariableIncorrectly:如果指定字符串值,则使用'select'语法为变量赋值.

  4. EmptyContentInInstructions:不要将空内容用于'xsl:for-each''xsl:if''xsl:when'等指令.

  5. DontUseNodeSetExtension:如果使用XSLT 2.0,请不要使用节点集扩展功能.

  6. RedundantNamespaceDeclarations:xsl:stylesheet元素中有冗余的名称空间声明.

  7. UnusedFunction:样式表函数未使用.

  8. UnusedNamedTemplate:样式表中的命名模板未使用.

  9. UnusedVariable:样式表中未使用变量.

  10. UnusedFunctionTemplateParameter:函数/模板体中未使用函数或模板参数.

  11. TooManySmallTemplates:样式表中有太多低粒度模板(10个或更多).

  12. MonolithicDesign:在样式表中使用单个模板/函数.您可以模块化代码.

  13. OutputMethodXml:生成HTML代码时使用输出方法'xml'.

  14. NotUsingSchemaTypes:在XSLT 2.0模式下工作时,样式表没有使用任何内置的Schema类型(xs:string等).

  15. UsingNameOrLocalNameFunction:当local-name()适当时使用name()函数(反之亦然).

  16. FunctionTemplateComplexity:函数或模板的大小/复杂度很高.需要重构代码.

  17. NullOutputFromStylesheet:样式表没有生成任何有用的输出.请查看样式表逻辑.

  18. UsingNamespaceAxis:使用不推荐使用的命名空间轴,在XSLT 2.0模式下工作.

  19. CanUseAbbreviatedAxisSpecifier:使用像child ::,attribute ::或parent :: node()这样的冗长轴说明符.

  20. UsingDisableOutputEscaping:已将disable-output-escaping属性设置为"yes".请查看样式表逻辑.

  21. NotCreatingElementCorrectly:直接使用xsl:element指令创建元素节点.

  22. AreYouConfusingVariableAndNode:您可能会将变量引用与节点引用混淆.(由Alain Benedetti提供)

  23. IncorrectUseOfBooleanConstants:错误地将布尔常量用作'true'或'false'.(由Tony Lavinio提供)

  24. ShortNames:为变量/ function/template使用单个字符名称.为这些功能使用有意义的名称.

  25. NameStartsWithNumeric:变量/函数/模板名称以数字字符开头


Pet*_*ter 8

最佳实践1:尽可能使用模板而不是<xsl:for-each>(99%的情况)

(我可以在最佳实践中添加MAINTAINABILITY作为额外成分,即使是最重要的实践也是如此)

为了理解xsl,你真的需要一些练习.
不明白什么...... 当然,做的很亲戚.

这对于XSLT来说是双重的,因为xsl:for-each构造往往是

  • 更具可读性

对于一个新手,但事实上

  • 结构不合理,
  • 不那么简单
  • 不那么简洁
  • 很少可维护

比模板,只有

  • 等于(最好!!)等等.具有最少的模板经验.

永远不要使用<xsl:for-each>元素!

我承认,标题有点夸张,确实存在,我被告知,"xsl for each"可以有它的优点,但这些情况非常非常罕见.

我曾经不得不在不到一周的时间内找到一个相当复杂的xml/xslt客户端站点,并在整个地方使用了for-each元素.现在,几年后,我更加聪明,我花了很多时间重新编写初始代码,仅使用模板.现在代码更清晰,更具适应性.

要么你知道这个,要么你应该:<xsl:template>和<xsl:apply-templates>几乎总是要走的路.如果你是xsl-ing,并且你没有完全理解这些标签,那么现在就停止工作,学习它们,得到一个aha-erlebnis,并继续你的工作作为一个重生(wo)男人.

  • 实际上,*有**必须*使用<xsl:for-each>的情况! (2认同)

Rob*_*ney 5

我认为,回答这个问题的一种好方法是从另一侧着手解决。哪些做法使XSLT 无效,为什么?

我所看到的一些情况导致XSLT无效:

  1. 过度使用for-each 每个人都这么说;我再说一遍。我发现这for-each通常是开发人员尝试以声明性语言使用传统编程技术的标志。

  2. 未充分利用XPath。 我看到的许多不良XSLT纯粹是因为开发人员不了解谓词,轴说明符position()current(),所以他改为使用XSLT构造实现了逻辑。

  3. 未充分利用元数据。通过为您的转换提供元数据, 有时可以消除大量 XSLT。

  4. 未充分利用预处理。 例如,如果XML文档包含必须使用XSLT字符串操作进行解析的数据,则在XSLT之外进行所有解析并将解析后的结果添加到XML或将解析后的结果作为参数传递通常要容易得多。进行转换。我已经看到了一些非常难以维护的XSLT实现业务逻辑,这些逻辑在C#或Python中实现起来很简单。

我在自己的XSLT世界中遇到的最大问题(我正在维护3000多个行转换)是无效代码。我确定我的转换中有一些模板将不再使用,因为它们正在测试的条件将不会再出现。无法以编程方式确定类似的东西<xsl:template match="SomeField[contains(., "some value")]>是存在还是死亡,因为它取决于元数据无法告诉您的东西。

  • Robert,您好,最小化死代码的一种方法是使用函数/模板库,例如FXSL。然后,您可能不必编写3000+行的转换。我写过的最复杂的样式表之一-XPath 2.0的解析器只有657行。当然,许多FXSL函数。用过的 (2认同)