使用XSLT 1.0构建HTML表

时间:2016-08-16 22:25:02

标签: html xml xslt-1.0

我正在使用XML和XSLT为广告系列构建HTML电子邮件。我几乎有我想要的东西,但我得到一些重复的内容,我无法弄清楚如何消除重复的元素。

我忘了添加一个额外的要求:我需要为每个内容元素添加自定义模板,以根据元素应用不同的格式。此外,内容中存在需要建模的随机图像

以下是一些示例XML:

<?xml version="1.0" encoding="UTF-8"?>
<job>
<surface>
<preheader><preheader_p>Click for more information</preheader_p></preheader>
<preheader><preheader_p>Questions? Call 877-555-1212</preheader_p></preheader>
<preheader><preheader_p>Click to unsubscribe</preheader_p></preheader>
<brand href="Images/logo.jpeg" />
<headline>Headline goes here</headline>
<subhead>Subhead goes here</subhead>
<body_copy>First paragraph goes here</body_copy>
<body_copy>Second paragraph goes here</body_copy>
<chart href="Images/graph.jpeg" />
<body_copy>Third paragraph goes here</body_copy>
</surface>
</job>

使用XSLT我需要构建一个表,该表在两列嵌套表的左列中插入preheader内容。在右栏中,我需要插入产品徽标。

显示预读者和徽标内容后,其余内容将按顺序插入,每个内容都在自己的表格行中。

这是我的XSLT:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:output method="html" encoding="UTF-8" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>

<xsl:template match="/">

<html xmlns="http://www.w3.org/1999/xhtml">

<body>
<table width="600" border="1">
<tr><td>
<table width="100%" border="1">
  <tr>
    <td width="60%">
        <table width="100%" border="1">
        <xsl:apply-templates select="job/surface/preheader" />          
        </table>
    </td>
    <td width="40%"><xsl:apply-templates select="job/surface/brand"/></td>
    </tr>
</table>
</td></tr>
<xsl:apply-templates select="job/surface" /> 
</table>
</body>
</html>
</xsl:template>

<xsl:template match="preheader"><tr><td style="font-size:11pt;"><xsl:value-of select="."/></td></tr>
</xsl:template>
<xsl:template match="brand"><img style="max-width:100%" src="{@href}" />
</xsl:template>
<xsl:template match="headline"><tr><td style="font-size:20pt;"><xsl:value-of select="."/></td></tr>
</xsl:template>
<xsl:template match="subhead"><tr><td style="font-size:16pt;"><xsl:value-of select="."/></td></tr>
</xsl:template>
<xsl:template match="body_copy"><tr><td style="font-size:12pt;"><xsl:value-of select="."/></td></tr>

    

 </xsl:stylesheet>

问题是preheader和logo元素重复两次。

目标是创建以下HTML:

<html>
<body>
<table width="600" border="1">
<tr><td>
<table width="100%" border="1">
<tr><td width="60%"><table width="100%" border="1">
    <tr><td>Click for more information</td></tr>
    <tr><td>Questions? Call 877-555-1212</td></tr>
    <tr><td>Click to unsubscribe</td></tr>
    </table></td>
    <td width="40%"><img style="max-width:100%" src="Images/logo.jpeg"></td</tr>
</table></td></tr>
<tr><td style="font-size:20pt;">Headline goes here</td></tr>
<tr><td style="font-size:16pt;">Subhead goes here</td></tr>
<tr><td style="font-size:12pt;">First paragraph goes here</td></tr>
<tr><td style="font-size:12pt;">Second paragraph goes here</td></tr>
<tr><td><img style="max-width:100%" src="Images/graph.jpeg" /></td></tr>
<tr><td style="font-size:12pt;">Third paragraph goes here</td></tr>
</table>
</body>
</html>

2 个答案:

答案 0 :(得分:0)

  

问题是preheader和logo元素正在重复   两次。

你有这些重复行的原因是这条指令:

<xsl:apply-templates select="job/surface" /> 

这有效地将模板应用于surface所有后代 - 包括您已处理的preheaderbrand个节点。

避免这种情况的一种方法是仅将模板选择性地应用于此时所需的节点:

<xsl:apply-templates select="job/surface/headline | job/surface/subhead | job/surface/body_copy" /> 
顺便说一句,我想知道你是否能做到这一点:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml">
<xsl:output method="xml" encoding="UTF-8" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" indent="yes"/>

<xsl:template match="/job">
    <html>
        <body>
            <table border="1">
                <tr>
                    <td>
                        <xsl:value-of select="surface/preheader[1]"/>
                    </td>
                    <td rowspan="{count(surface/preheader)}">
                        <img style="max-width:100%" src="{@href}" />
                    </td>
                </tr>
                <xsl:for-each select="surface/preheader[position() > 1]">
                    <tr>
                        <td>
                            <xsl:value-of select="."/>
                        </td>
                    </tr>
                </xsl:for-each>
                <xsl:for-each select="surface/headline | surface/subhead | surface/body_copy">
                    <tr>
                        <td colspan="2">
                            <xsl:value-of select="."/>
                        </td>
                    </tr>
                </xsl:for-each>
            </table>
        </body>
    </html>
</xsl:template>

</xsl:stylesheet>

另请注意,您在其他模板中创建的元素不会继承您的命名空间声明。您可以看到许多表行都在非命名空间中:

<tr xmlns="">

您应该将默认命名空间声明向上移动到stylesheet元素,如上例所示。

答案 1 :(得分:0)

这是完美运作的解决方案。它结合了迈克尔对重复元素的修复,并提供了模板的应用,以格式化各个内容元素。感谢

library(data.table)
setDT(df, key = "Product")[c("a", "b")][, if(uniqueN(Product)==2) .SD , ID]
#   ID Product Quantity
#1:  1       a        1
#2:  1       b        1
#3:  2       a        1
#4:  2       b        1