避免在XSL模板中重复

时间:2019-01-03 21:30:35

标签: xml xslt dry

我一直在使用XML + XSL作为生成HTML电子邮件的工具。由于电子邮件代码非常依赖于过时的标记和内联样式,因此我认为从格式化其所需的所有疯狂中提取实际内容会很好。

但是随着我走的更远,制作更多的模板,我发现自己越来越在重复自己。有没有一种方法可以使XSL样式表变干,或者是否必须用表示性元素阻塞XML文件?让我们以这个XML块为例:

<root>
  <headline>Hello</headline>
  <button>Click me</button>
</root>

标题和按钮都需要一些html(例如H1div),但是由于我们在谈论电子邮件,因此它们还需要一个表格单元格,一个表格行,以及表格,如下所示:

<table>
  <tr>
    <td>
      <h1>Hello</h1>
    </td>
  </tr>
</table>

<table>
  <tr>
    <td>
      <div>Hello</div>
    </td>
  </tr>
</table>

因此,朴素的解决方案是在每个元素的样式表中包含该表标记,如下所示:

<xsl:template match="headline">
  <table>
    <tr>
      <td>
        <h1>
          <xsl:apply-templates/>
        </h1>
      </td>
    </tr>
  </table>
</xsl:template>

但是说在测试期间,我发现Outlook 2007中存在一个错误,这意味着所有这些包装器表都需要一个附加属性:cell-padding=0;。如果我已经对表标记进行了硬编码,则可能必须转到数十个模板来传播该修补程序。

是否可以创建包装器表的“部分”模板,并在标题和按钮的单个模板中引用这些模板?

我知道我可以将标记更改如下:

<root>
  <table>
    <headline>Hello</headline>
  </table>
  <table>
    <button>Click me</button>
  </table>
</root>

但是那感觉就像是在踢罐子。如果我发现由于Gmail移动应用程序中的错误而导致所有td需要自己的特殊样式声明怎么办?那么解决方案是进入并更改标记,以使其与最终输出没有区别,此时,XSL模板实际上在做什么?

我尝试了call-template的解决方案,但没有解决。任何建议将不胜感激!

1 个答案:

答案 0 :(得分:1)

例如,您可以像这样合并table模板

<xsl:template match="headline|button">
    <table cell-padding="0">
      <tr>
        <td>
          <xsl:apply-templates />
        </td>
      </tr>
    </table> 
</xsl:template>

<xsl:template match="text()[ancestor::headline]">
    <h1>
      <xsl:copy-of select="." />
    </h1>
</xsl:template>

<xsl:template match="text()[ancestor::button]">
    <div>
      <xsl:copy-of select="." />
    </div>
</xsl:template>

这会将您的两个示例模板合并为一个,然后再次将其拆分为两个不同的路径。我还添加了您的 Outlook 2007 处理。

以上模板的输出为

<table cell-padding="0">
    <tr>
        <td>
            <h1>Hello</h1>
        </td>
    </tr>
</table>
<table cell-padding="0">
    <tr>
        <td>
            <div>Click me</div>
        </td>
    </tr>
</table>