我正在學習使用 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.xml
我的示例 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>
uj5u.com熱心網友回復:
首先,xsl:for-each不用于“回圈”。它沒有退出條件,也無法將一次迭代的結果傳遞給另一次。
接下來,使用不僅xsl:for-each限于初學者,也不是“糟糕的風格”——盡管您可能在這里或其他任何地方讀到過什么。
該xsl:for-each指令只不過是在特殊情況下使用的快捷方式。一般方法分為兩個階段:
首先,您選擇一組節點并告訴處理器將模板應用于它們;
接下來,處理器找到與所選節點集中的每個節點最匹配的模板并應用它。
在 (1) 您希望對所選集合中的所有節點應用統一處理以及 (2) 無需遞回應用模板或以其他方式重新使用它的情況下,您可以簡單地告訴處理器:獲取這些節點并將這個模板應用到他們身上。
這正是xsl:for-each指令所做的。它具有select選擇要處理的節點的屬性,其內容是要應用于所選節點集的模板。不多也不少。這里沒有范式轉變。沒有“推式”與“拉式”之分。沒有善與惡。
xsl:for-each當它是樣式表作者工具箱中的唯一工具時,就會出現唯一的問題。正如我所說,它是一種可以在特殊情況下使用的快捷方式。當這些情況不適用時,使用它會導致代碼非常糟糕。
uj5u.com熱心網友回復:
我猜你所說的“高級風格”是指使用模板(進行模式匹配)而不是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="geneData" /> <!-- Discard all not matched 'geneData' elements -->
<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:template match="mutation" /> <!-- Discard all not matched 'mutation' elements -->
</xsl:stylesheet>
在上面的代碼中,兩組節點 (.//geneData和.//mutation) 都被傳遞給了xsl:apply-templates這些節點,然后將結果節點傳遞給了所有模板。而那些匹配的人被處決。因此, shortxsl:template與謂詞( 的[...]部分match="...")替換了xsl:when代碼的s 。
這被認為是 XSLT 開發的“標準”方法。在實踐中,有些用例xsl:for-each可能更適合代碼清晰度,但通常這兩種方法是可以互換的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/363083.html
上一篇:決議XML時出現型別錯誤
