【问题标题】:Two Step View Pattern: XSLT vs. object graph两步视图模式:XSLT 与对象图
【发布时间】:2010-11-04 15:05:41
【问题描述】:

我打算实现 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() 方法将在根节点上调用。我特别喜欢这种方法,因为它可以让我做一些很酷的事情。特别是,如果我有一个带有属性 type="price":

的单元格标签
<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,我将如何解析价格标签的内容?

【问题讨论】:

    标签: html xml xslt xhtml view


    【解决方案1】:

    我真的不能说你为什么要选择其中一个。

    我认为这在很大程度上取决于您的渲染过程的技术细节,无论您希望它发生在服务器上还是浏览器上,您对 XSLT 或 XSLT 替代方案的舒适程度。

    for XSLT 的一点当然是几乎不可能生成格式不正确的 XML 输出(我不是在说 valid)。写出字符串时很容易漏掉一些东西。

    关于您的解析问题:毫无疑问,最好的方法是在 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>
    

    【讨论】:

      【解决方案2】:

      您提出的代码存在一些问题。最大的问题是您对输出进行硬编码以达到标准输出,这使得进行额外的后处理变得更加困难。通过修改您的渲染方法以接受输出流或写入器来改变这一点并不难。

      尽管如此,您所提议的是大量的 java 代码,它们基本上将实现一个非常具体的 XSLT 转换。学习并使用 XSLT 将 XML 转换为 HTML 会好很多。优点是 XSLT 是专为这种转换而设计的通用工具。

      这是一个 XSLT 示例,它几乎可以完成您想要做的事情。不幸的是,在我不得不将货币价值解析为数字和符号部分的时候,cares 用完了,但这当然足以让你开始。 p>

      <?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>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-11-14
        • 1970-01-01
        • 2011-06-06
        • 2012-12-04
        • 1970-01-01
        • 1970-01-01
        • 2018-08-04
        • 2014-04-03
        相关资源
        最近更新 更多