[英]<xsl:apply-templates> usage with <xsl:for-each> using XSLT1.0 transformations
[英]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.