节点缺失时XSL应用模板

时间:2014-02-18 21:24:40

标签: xml xslt xml-parsing

当我想要格式化的节点丢失时,我无法应用模板。我不相信这种解释是非常具有描述性的,所以我已经包含了一个模拟的例子来说明我的意思。我有以下形式的XML:

<mains>
    <main>
        <detail1>stuff11</detail1>
        <detail2>stuff12</detail2>
    </main>
    <main>
        <detail1>stuff22</detail1>
    </main>
    <main>
        <detail2>stuff32</detail2>
        <detail3>stuff33</detail3>
    </main>
</mains>

目前,我使用的XSL执行以下操作

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/mains">
<table>
    <xsl:apply-templates select="main"/>
</table>
</xsl:template>

<xsl:template match="main">
    <xsl:apply-templates select="detail1"/>
    <xsl:apply-templates select="detail2"/>
    <xsl:apply-templates select="detail3"/>
</xsl:template>

<xsl:template match="detail1">
    <tr>
        <td>
            <xsl:value-of select="."/>
        </td>
    </tr>
</xsl:template>
<xsl:template match="detail2">
    <tr>
        <td>
            <xsl:value-of select="."/>
        </td>
    </tr>
</xsl:template>
<xsl:template match="detail3">
    <tr>
        <td>
            <xsl:value-of select="."/>
        </td>
    </tr>
</xsl:template>

</xsl:stylesheet>

当我申请XSL时,我得到以下内容

<?xml version="1.0" encoding="UTF-8"?>
<table>
    <tr><td>stuff11</td></tr>
    <tr><td>stuff12</td></tr>
    <tr><td>stuff21</td></tr>
    <tr><td>stuff32</td></tr>
    <tr><td>stuff33</td></tr>
</table>

这不是我想要的表格。我反而想要下表

<?xml version="1.0" encoding="UTF-8"?>
<table>
    <tr><td>stuff11</td></tr>
    <tr><td>stuff12</td></tr>
    <tr><td></td></tr>
    <tr><td>stuff21</td></tr>
    <tr><td></td></tr>
    <tr><td></td></tr>
    <tr><td></td></tr>
    <tr><td>stuff32</td></tr>
    <tr><td>stuff33</td></tr>
</table>

为了论证,我说我不能将<tr><td></td></tr>标签移到各种细节模板之外,他们必须留在那里。

我知道我可以在每个模板调用上执行<xsl:if>并检查值 - 以确保它是否存在,但这感觉非常笨重。是否有设置使apply-templates适用,即使节点丢失了?

3 个答案:

答案 0 :(得分:2)

谈论“不存在的节点”是一厢情愿的想法。没有这样的节点,因此您无法选择它,因此您无法处理它。你需要一个xsl:choose。

答案 1 :(得分:1)

很抱歉,但将模板应用于空集会产生空结果。

您可以通过向上重构HTML包装器来获得所需内容 - 在调用模板中生成<tr><td></td></tr>包装,并让“详细信息”模板仅生成数据内容。

或者,也许只有一个<xsl:apply-templates select="detail1|detail2|detail3">,但应用<xsl:sort>来生成所需顺序的结果(1,然后是2,然后是3)。

答案 2 :(得分:1)

找出解决方法。

<xsl:apply-templates select=".">
    <xsl:with-param name="value" select="detail1" />
</xsl:apply-templates>

这将使模板始终被调用,我可以在模板中处理xsl:choose缺少的节点,而不是围绕每个模板调用包裹xsl:choose

话虽如此,我不确定什么是“最佳做法”,所以如果有人有更好的解决方案,我仍然有兴趣听到它。

相关问题