如何在XLS模板中添加/测试不存在的元素?

时间:2011-06-16 17:46:49

标签: html xml sharepoint xslt sharepoint-2007

上下文

这适用于 SharePoint 2007 中的自定义查询Web部件(CQWP)。我从日历中提取事件列表,我想显示所有系统的当前系统状态列表,即使它们没有当前事件。

该列表按系统名称排序。

收到XML

假设你有 XML:

<events>
    <event>
        <system>A</system>
        <state>1</state>
    </event>
    <event>
        <system>B</system>
        <state>2</state>
    </event>
    <event>
        <system>C</system>
        <state>3</state>
    </event>
</events>

<events>
    <event>
        <system>A</system>
        <state>1</state>
    </event>

    <event>
        <system>C</system>
        <state>2</state>
    </event>
</events>

注意:3个静态系统(A,B或C)。他们没有当前事件(我没有提出开始/结束日期,因为这个问题不需要。)

想要数据输出

我希望我的XSL输出如下:

<table>
    <tr>
        <th>System</th>
        <th>State</th>
    </tr>
    <tr>
        <td>A</td>
        <td>1</td>
    </tr>
    <tr>
        <td>B</td>
        <td>1</td>
    </tr>
    <tr>
        <td>C</td>
        <td>3</td>
    </tr>
</table>

也就是说,我希望所有3个系统都有输出,即使它们没有当前事件(因此,不在XML中(默认状态为1))。哦,是的,1系统可能有2 +当前事件。 (<td>A</td><td>1</td></tr><tr><td>A</td><td>2</td>)。 完美答案会连接相同的系统事件并且只显示最高状态,但我可以不用。

当前XSL

这是我当前的模板:

<xsl:template name="system" match="Row[@Style='system']" mode="itemstyle">
    <xsl:if test="count(preceding-sibling::*)=0">
        <table><tr><th>System</th>
        <th>State</th></tr>
    </xsl:if>
    <tr>
            <td><xsl:value-of select="@System"/></td>
             <td><xsl:value-of select="@State"/></td>
    </tr>
    <xsl:if test="count(following-sibling::*)=0">
        </table>
    </xsl:if>
</xsl:template>

我的想法

我虽然可以使用变量(或3?)来包含我的(静态)系统列表

<xsl:variable name="Systems">A,B,C</xsl:variable> 

<xsl:variable name="System1">A</xsl:variable> 
<xsl:variable name="System2">B</xsl:variable> 
<xsl:variable name="System3">C</xsl:variable> 

然后,在XSL中,检查<xsl:value-of select="@System"/>是否等于这个/那些变量值。

问题

可行吗?

你建议我继续,否则怎么办?

如何将我的变量与<xsl:value-of select="@System"/>进行比较?

奖金:如何连接相同的系统事件并仅显示最高状态?

3 个答案:

答案 0 :(得分:1)

这是可行的。如果您只有3个站点,则可以更轻松地复制和粘贴以单独检查A,B和C.如果你想要一个更灵活的解决方案,我会使用node-set()扩展函数,但它可能不在你的解析器中。 (在XSLT 2.0中似乎有一种我不知道的更好的方法。)

<xsl:variable name="root" select="/"/>

<xsl:variable name="system">
    <system>A</system>
    <system>B</system>
    <system>C</system>  
</xsl:variable>

<xsl:template match="/">
<table>
<xsl:for-each select="msxsl:node-set($system)/system">
    <tr>
        <td><xsl:value-of select="text()"/></td>
        <td>
            <xsl:for-each select="$root/events/event[system=current()]">
                <xsl:sort select="date" order="descending"/>
                    <xsl:if test="position()=1">
                        <xsl:value-of select="state"/>
                    </xsl:if>

            </xsl:for-each>
        </td>
    </tr>
</xsl:for-each>
</table>
</xsl:template>

我手头没有解析器以确保扩展功能正常工作但希望它能够运行。

答案 1 :(得分:1)

可能有一个更短的解决方案。无论如何我无法弄明白。这是我的XSLT 2.0建议:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

    <xsl:variable name="default">
        <event>
            <system>A</system>
            <state>1</state>
        </event>
        <event>
            <system>B</system>
            <state>1</state>
        </event>
        <event>
            <system>C</system>
            <state>1</state>
        </event>
    </xsl:variable>

    <xsl:template match="events">
        <table>
            <tr>
                <th>System</th>
                <th>State</th>
            </tr>

            <xsl:choose>
                <xsl:when test="event[system='A']">
                    <xsl:apply-templates select="event[system='A'][1]"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:copy-of select="$default/event[system='A']"/>
                </xsl:otherwise>
            </xsl:choose>

            <xsl:choose>
                <xsl:when test="event[system='B']">
                    <xsl:apply-templates select="event[system='B'][1]"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:copy-of select="$default/event[system='B']"/>
                </xsl:otherwise>
            </xsl:choose>

            <xsl:choose>
                <xsl:when test="event[system='C']">
                    <xsl:apply-templates select="event[system='C'][1]"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:copy-of select="$default/event[system='C']"/>
                </xsl:otherwise>
            </xsl:choose>

        </table>        
    </xsl:template>


    <xsl:template match="event">
        <xsl:variable name="maxval" select="max(
            ../event[system=current()/system]/state)"/>
        <tr>
            <td>
                <xsl:value-of select="system"/>
            </td>
            <td>
                <xsl:value-of select="$maxval"/>
            </td>
        </tr>
    </xsl:template>

</xsl:stylesheet>

答案 2 :(得分:0)

感谢回答者,您的示例帮助我理解了XSL。但是,因为它是针对SharePoint的,所以我意识到我必须在框架内玩...

案例没有当前事件 mainStyle.xsl 中处理,只显示默认的html。

项目在 itemStyle.xsl 中逐个处理。我的大多数代码都放在那里。

首先,我创建了一堆变量:

    <xsl:variable name="testACCP">
            <xsl:choose><xsl:when test="count(../Row[@Systeme='A'])>0">1</xsl:when>
            [...]
    </xsl:variable>

然后我建立了我的解决方案,当我在第一个节点时从头开始

     <xsl:if test="count(preceding-sibling::*)=0">
        <xsl:text disable-output-escaping="yes">
            &lt;table width="100%" border="0" cellspacing="0" cellpadding="3" &gt;
            [...]

如果系统没有事件,我会用我的变量知道它,并相应地显示

<xsl:if test="$testA=0">
            <tr id="linkitem" class="item" style="background:#f0fff3">
                    <td>A</td><td>OK</td>
                    [...]

至于最大值的显示,这被放弃了。有一些值得知道你最近有2个影响系统的当前事件。

这个解决方案很有效,但它很笨,每个项目都会创建大量变量来对组进行测试...要进行优化,需要进行高度修改的 mainstyle.xsl 或完整的WebPart是必需的。