我打算实施Martin Fowler的Two-Step View Pattern 用于在我正在编写的Web应用程序中呈现HTML。一般的想法是,它不是让应用程序输出原始HTML,而是输出一个自定义中间XML,然后转换为HTML / CSS。这有许多优点,包括减少代码重复和更一致的输出。
Fowler建议将XML转换为最终HTML的方法是使用XSLT。
之前我使用过XSLT,我知道基础知识。但是,我想知道使用XSLT有什么好处。我正在考虑的另一种方法是这样的:
以下是第一个渲染步骤的XML输出示例:
<grid>
<headingRow>
<cell>Product</cell>
<cell>Price</cell>
</headingRow>
<row>
<cell>A product</cell>
<cell type="price">$54.95</cell>
</row>
</grid>
所需的最终HTML输出:
<table class="grid">
<tr>
<th>Product</th>
<th>Price</th>
</tr>
<tr>
<td>A product</td>
<td>
<span class="currency_symbol">$</span>
<span class="decimal_number">54.95</span>
</td>
</tr>
</table>
我正在考虑的方法是每个标签都有一个对象。
class GridTag extends Tag {
...
public void render() {
System.out.println("<table class=\"grid\">");
foreach(Tag child: children) {
child.render();
}
System.out.println("</table>");
}
...
}
通过解析XML将对象构造成树。 render()方法将在根节点上调用。我特别喜欢这种方法,因为它可以让我做很酷的事情。特别是,如果我有一个上面的单元格标签,属性类型=“价格”:
<cell type="price">$54.95</price>
它的关联Tag类可以解析标记的内容,将货币符号和数值分隔成单独的HTML标记,以允许对齐货币符号和小数点,如上面的HTML输出所示。
<td>
<span class="currency_symbol">$</span>
<span class="decimal_number">54.95</span>
</td>
问题:
我应该这样做还是应该使用XSLT? 使用XSLT有什么好处,我可能错过了? 如果我应该使用XSLT,我将如何解析价格标签的内容?
答案 0 :(得分:3)
我真的不能说你为什么要选择其中一个。
我认为这在很大程度上取决于渲染过程的技术细节,无论您是希望它在服务器上还是在浏览器上发生,您对XSLT的适应程度如何,或者分别是XSLT的替代方案。
XSLT的一点肯定是生成格式不正确的XML输出几乎是不可能的(我不是说有效)。在写出字符串时很容易错过。
关于解析问题:毫无疑问,最好的方法是在XML中将数据和格式分开。 XSLT不用于解析,所以我不明白为什么你的XML从一开始就不能采用这种格式:
<cell type="price" symbol="$">54.95</cell>
但是,假设你无法做任何事情,这个XSLT会处理它。
<xsl:template match="cell[@type='price']">
<td>
<xsl:variable name="vNonNumbers" select="translate(., '0123456789.', '')" />
<xsl:variable name="vTheNumbers" select="translate(., $vNonNumbers, '')" />
<span class="currency_symbol">
<xsl:value-of select="$vNonNumbers" />
</span>
<span class="decimal_number">
<xsl:value-of select="$vTheNumbers" />
</span>
</td>
</xsl:template>
我希望你能看出为什么上面的代码本质上是错误的。与替代方案相比(如果您的XML 将分开数据和格式):
<xsl:template match="cell[@type='price']">
<td>
<span class="currency_symbol">
<xsl:value-of select="@symbol" />
</span>
<span class="decimal_number">
<xsl:value-of select="." />
</span>
</td>
</xsl:template>
答案 1 :(得分:1)
您提出的代码存在一些问题。最大的问题是你很难对输出进行标准输出,这使得进行额外的后期处理变得更加困难。通过修改render方法以接受输出流或writer,这不难改变。
无论如何,你提出的是大量的java代码,它基本上将实现一个非常具体的XSLT转换。只是学习和使用XSLT将XML转换为HTML,你会好得多。优点是XSLT是一种通用工具,专为这种转换而设计。
这是一个XSLT的例子,它几乎完成了你想要做的事情。遗憾的是,我不得不用完 关心 关于我必须将货币值解析为数字和符号部分的时间,但这肯定足以让你开始。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/grid">
<table class="grid">
<xsl:apply-templates select="headingRow"/>
<xsl:apply-templates select="row"/>
</table>
</xsl:template>
<xsl:template match="headingRow">
<tr>
<xsl:apply-templates select="cell" mode="heading"/>
</tr>
</xsl:template>
<xsl:template match="row">
<tr>
<xsl:apply-templates select="cell" mode="normal"/>
</tr>
</xsl:template>
<xsl:template match="cell" mode="heading">
<th><xsl:value-of select="."/></th>
</xsl:template>
<xsl:template match="cell" mode="normal">
<xsl:choose>
<xsl:when test="@type='price'">
<td>
<span class="currency_symbol">
<xsl:value-of select="." />
</span>
<span class="decimal_number">
<xsl:value-of select="." />
</span>
</td>
</xsl:when>
<xsl:otherwise>
<td>
<xsl:value-of select="." />
</td>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>