繁体   English   中英

XSL 风格:使用<xsl:for-each select>或者<xsl:template match>或 XSLT 中的其他解决方案?</xsl:template></xsl:for-each>

[英]XSL style: using <xsl:for-each select> or <xsl:template match> or other solutions in XSLT?

我正在学习使用 XSL 将 XML 解析为 HTML/XHTML。

XLST <xsl:for-each>元素是允许循环的语言的核心元素。 然而,这里和其他地方的帖子建议使用这对初学者来说很常见(我就是。)而且风格很差。

我的问题是: <xsl:for-each>循环有哪些更好的(如更高效/优雅/更好的风格)选项,为什么?

在下面的示例中,我使用嵌套<xsl:for-each><xsl:choose>元素通过条件<xsl:when>测试循环遍历所需的节点。 这工作正常并选择我需要的节点,但感觉相当笨重......

您的智慧和见解将不胜感激!

我的示例 XML 是由斯坦福 HIVdb 数据库查询生成的报告: https://hivdb.stanford.edu/hivdb/by-sequences/

XSD 架构在这里: https://hivdb.stanford.edu/DR/schema/sierra.xsd

我的示例 XML 报告在这里: https://github.com/delfair/xml_examples/blob/main/Resistance_1636677016671.Z0F635D0E0F3874CFF8AZ58E

我的示例 XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">

<html>
<head>
    <title>Example Report</title>
</head>
<body>

<h3>Significant mutations</h3>

<xsl:for-each select=".//geneData">
    <xsl:choose>
        <xsl:when test="gene='HIV1PR'">
        Protease inhibitor mutations<br/><br/>
        </xsl:when>
        <xsl:when test="gene='HIV1RT'">
        Reverse transcriptase inhibitor mutations<br/><br/>
        </xsl:when>
        <xsl:when test="gene='HIV1IN'">
        Integrase inhibitor mutations<br/><br/>
        </xsl:when>
    </xsl:choose>
<table>
<xsl:for-each select=".//mutation">
    <xsl:choose>
        <xsl:when test="classification='PI_MAJOR' or classification='PI_MINOR' or classification='NRTI' or classification='NNRTI' or classification='INI_MAJOR' or classification='INI_MINOR'">
        <tr>
        <td>Class</td>
        <td>Mutation</td>
        </tr>
        <tr>
            <td><xsl:value-of select="classification"/></td>
            <td><xsl:value-of select="mutationString"/></td>
        </tr>
        </xsl:when>
    </xsl:choose>
</xsl:for-each>
</table><br/>
</xsl:for-each>

</body>
</html>

</xsl:template>
</xsl:stylesheet>

结果 HTML:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Example Report</title>
</head>
<body>
<h3>Significant mutations</h3>
Protease inhibitor mutations<br><br><table></table>
<br>
Reverse transcriptase inhibitor mutations<br><br><table>
<tr>
<td>Class</td>
<td>Mutation</td>
</tr>
<tr>
<td>NNRTI</td>
<td>K103N</td>
</tr>
</table>
<br>
Integrase inhibitor mutations<br><br><table></table>
<br>
</body>
</html>

我猜您所说的“高级样式”是指使用模板(进行模式匹配)而不是xsl:for-each “循环”。

您的代码的核心功能可以转换如下:

...
      <h3>Significant mutations</h3>

      <xsl:apply-templates select=".//geneData" />
      <table>
        <xsl:apply-templates select=".//mutation" />
      </table><br/>
    </body>
  </html>
</xsl:template>
<!-- End of main template matching "/" -->

<xsl:template match="geneData[gene='HIV1PR']">Protease inhibitor mutations<br/><br/></xsl:template>
<xsl:template match="geneData[gene='HIV1RT']">Reverse transcriptase inhibitor mutations<br/><br/></xsl:template>
<xsl:template match="geneData[gene='HIV1IN']">Integrase inhibitor mutations<br/><br/></xsl:template>

<xsl:template match="mutation[classification='PI_MAJOR' or classification='PI_MINOR' or classification='NRTI' or classification='NNRTI' or classification='INI_MAJOR' or classification='INI_MINOR']">
        <tr>
            <td>Class</td>
            <td>Mutation</td>
        </tr>
        <tr>
            <td><xsl:value-of select="classification"/></td>
            <td><xsl:value-of select="mutationString"/></td>
        </tr>
</xsl:template>

</xsl:stylesheet>

在上面的代码中,两组节点( .//geneData.//mutation )都被传递给xsl:apply-templates ,后者将结果节点传递给所有模板。 那些匹配的人将被处决。 因此,简短的xsl:template带有谓词( match="..."[...]部分),它们替换了代码的xsl:when

这应该是 XSLT 开发的“标准”方法。 在实践中,在某些用例中, xsl:for-each可能更适合代码清晰,但通常这两种方法是可以互换的。

首先, xsl:for-each不用于“循环”。 它没有退出条件,也无法将一次迭代的结果传递给另一次迭代。

接下来,使用xsl:for-each不仅限于初学者,也不是“糟糕的风格”——尽管您可能在这里或其他任何地方读过。

xsl:for-each指令只不过是在特殊情况下使用的快捷方式。 一般方法分为两个阶段:

  • 首先,您 select 一组节点并告诉处理器将模板应用于它们;

  • 接下来,处理器找到与所选节点集中的每个节点最匹配的模板并应用它。

如果 (1) 您想对所选集中的所有节点应用统一处理,并且 (2) 不需要递归应用模板或重新使用它,您可以简单地告诉处理器:获取这些节点并将此模板应用于他们。

这正是xsl:for-each指令的作用。 它有一个select属性到 select 要处理的节点,其内容是要应用于所选节点集的模板 不多也不少。 这里没有范式转变。 没有“推式”与“拉式”。 没有善与恶。

xsl:for-each是样式表作者工具箱中的唯一工具时,就会出现唯一的问题。 正如我所说,它是一种可以在特殊情况下使用的捷径。 当这些情况不适用时,使用它会导致代码非常糟糕。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM