如何计算类别中的元素并将其与XSLT中的其他类别进行比较

时间:2011-03-04 10:03:34

标签: xml xslt variables count param

我有一个问题: - )

我想打印出一个xml并为它写一个xslt。问题是我想用我的xml元素构建一个表,但我必须计算每行是否有相同数量的列,如果不是我必须添加一个值元素。

我知道一旦我设置了值,我就无法更改变量值但是如何比较进程的分类/表行数呢? (并添加空行)

XML:

<Settings>
   ...
   ..
  <DashBoard>
    <Category NAME="ph" PICNAME="prh">
      <Process NAME="pd" URL="" PICNAME="prh_prd" />
      <Process NAME="md" URL="" PICNAME="prh_prd" />
      <Process NAME="t" URL="" PICNAME="prh_prd" />
    </Category>
    <Category NAME="cm" PICNAME="cam">
      <Process NAME="ps" URL="" PICNAME="cam_pls" />
      <Process NAME="ea" URL="" PICNAME="cam_eas" />
    </Category>
    <Category NAME="sm" PICNAME="sum">
      <Process NAME="frm" URL="" PICNAME="sum_frm" />
    </Category>
  </DashBoard>
</Settings>

XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl=".....">
  <xsl:output method="xml" indent="yes"/>
  <xsl:variable name="relurl" select="/Settings/Picture/@RELATIVEURL"/>

  <xsl:template match="Settings">
    <table id="dashframe" >
      <xsl:apply-templates/>
    </table>
  </xsl:template>

  <xsl:template match="Category">
    <xsl:variable name="altname" select="@NAME" />
    <xsl:variable name="picname" select="@PICNAME" />
    <tr>
      <th>
        <img alt="{$altname}" src="{$relurl}dash_{$picname}_p_01.png" />
      </th>
      <xsl:apply-templates/>
    </tr>
  </xsl:template>

  <xsl:template match="Process">
    <xsl:variable name="altname" select="@NAME" />
    <xsl:variable name="picname" select="@PICNAME" />
    <td>
      <img alt="{$altname}" src="{$relurl}dash_{$picname}_p_01.png" />
    </td>
  </xsl:template>
</xsl:stylesheet>

期望的输出:

<table id="dashframe" >
    <tr>
        <th>titel 1</th>
        <td>....</td>
        <td>....</td>
        <td>....</td>
    </tr>
    <tr>
        <th>titel 2</th>
        <td>....</td>
        <td>....</td>
        <td></td>
    </tr>
    <tr>
        <th>titel 3</th>
        <td>....</td>
        <td></td>
        <td></td>
    </tr>
</table>

3 个答案:

答案 0 :(得分:1)

保留你的,这个样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html"/>
    <xsl:variable name="relurl" select="/Settings/Picture/@RELATIVEURL"/>
    <xsl:variable name="vColumns">
        <xsl:for-each select="/Settings/DashBoard/Category">
            <xsl:sort select="count(Process)" order="descending"/>
            <xsl:if test="position()=1">
                <xsl:value-of select="count(Process)"/>
            </xsl:if>
        </xsl:for-each>
    </xsl:variable>
    <xsl:template match="DashBoard">
        <table id="dashframe" border="1">
            <xsl:apply-templates/>
        </table>
    </xsl:template>
    <xsl:template match="Category">
        <tr>
            <th>
                <img alt="{@NAME}" src="{$relurl}dash_{@PICNAME}_p_01.png"/>
            </th>
            <xsl:call-template name="process"/>
        </tr>
    </xsl:template>
    <xsl:template name="process">
        <xsl:param name="pColumn" select="number($vColumns)"/>
        <xsl:if test="$pColumn">
            <xsl:call-template name="process">
                <xsl:with-param name="pColumn" select="$pColumn - 1"/>
            </xsl:call-template>
            <td>
                <xsl:variable name="vColumn" select="Process[$pColumn]"/>
                <xsl:if test="$vColumn">
                    <img alt="{$vColumn/@NAME}"
                         src="{$relurl}dash_{$vColumn/@PICNAME}_p_01.png"/>
                </xsl:if>
            </td>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

使用此输入:

<Settings>
    <DashBoard>
        <Category NAME="ph" PICNAME="prh">
            <Process NAME="pd" URL="" PICNAME="prh_prd" />
            <Process NAME="md" URL="" PICNAME="prh_prd" />
            <Process NAME="t" URL="" PICNAME="prh_prd" />
        </Category>
        <Category NAME="cm" PICNAME="cam">
            <Process NAME="ps" URL="" PICNAME="cam_pls" />
            <Process NAME="ea" URL="" PICNAME="cam_eas" />
        </Category>
        <Category NAME="sm" PICNAME="sum">
            <Process NAME="frm" URL="" PICNAME="sum_frm" />
        </Category>
    </DashBoard>
</Settings>

输出:

<table id="dashframe" border="1">
    <tr>
        <th><img alt="ph" src="dash_prh_p_01.png"></th>
        <td><img alt="pd" src="dash_prh_prd_p_01.png"></td>
        <td><img alt="md" src="dash_prh_prd_p_01.png"></td>
        <td><img alt="t" src="dash_prh_prd_p_01.png"></td>
    </tr>
    <tr>
        <th><img alt="cm" src="dash_cam_p_01.png"></th>
        <td><img alt="ps" src="dash_cam_pls_p_01.png"></td>
        <td><img alt="ea" src="dash_cam_eas_p_01.png"></td>
        <td></td>
    </tr>
    <tr>
        <th><img alt="sm" src="dash_sum_p_01.png"></th>
        <td><img alt="frm" src="dash_sum_frm_p_01.png"></td>
        <td></td>
        <td></td>
    </tr>
</table>

注意:众所周知的最大成语。

答案 1 :(得分:1)

感谢您的回答,我在过去4-5小时内自己解决了~~~

首先,得到计数:

<xsl:variable name="maxProcess">
  <xsl:call-template name="db"/>
</xsl:variable>

<xsl:template name="db">
  <xsl:for-each select="/Settings/DashBoard/Category">
    <xsl:sort select="count(Process)" order="descending"/>
    <xsl:if test="position() =1">
      <xsl:value-of select="count(Process)"/>
    </xsl:if>
  </xsl:for-each>
</xsl:template>

第二步,添加进程,然后添加空的进程:

<xsl:template match="Category">
  <tr>
    <td>
      <img .... />
    </td>
    <xsl:apply-templates/>
    <xsl:call-template name="addTDs">
      <xsl:with-param name="rest" select="$maxProcess - count(Process)"/>
    </xsl:call-template>
  </tr>
</xsl:template>

<xsl:template match="Process">
  <td>
     <img ... />
  </td>
</xsl:template>

<xsl:template name="addTDs">
  <xsl:param name="rest"/>
  <xsl:choose>
    <xsl:when test="$rest &gt; 0">
      <td>
        <img ..../>
      </td>
      <xsl:call-template name="addTDs">
        <xsl:with-param name="rest" select="$rest - 1"/>
      </xsl:call-template>
    </xsl:when>
  </xsl:choose>
</xsl:template>

答案 2 :(得分:0)

所以你应该分两步完成:

  1. 标识具有最大列数的行
  2. 迭代填满缺失列的所有行
  3. 所以第一部分是这里的核心问题,因为不可能仅通过xpath找到它。

    这个问题的答案证实:

    Find the maximum child count with XPath 1.0

    我现在试着回答这个问题约30分钟。由于我的工作,我对XML和XSLT非常熟悉。但我不能弄清楚如何找到具有最大子元素数的元素。但其他人之前做过:

    Find maximum value of all child elements and get its parent element in XSLT

    顺便说一句:这家伙在他的回答中失去了一个支持!

    如果你有,我们来到第2步:

    在您的类别模板中,只需添加对以下模板的调用(这只是for循环):

    <xsl:template name="for.loop">
    
       <xsl:param name="i"      />
       <xsl:param name="count"  />
    
       <xsl:if test="$i &lt;= $count">
          //Generate your "fill up" - colum here
       </xsl:if>
    
       <!--begin_: RepeatTheLoopUntilFinished-->
       <xsl:if test="$i &lt;= $count">
          <xsl:call-template name="for.loop">
              <xsl:with-param name="i">
                  <xsl:value-of select="$i + 1"/>
              </xsl:with-param>
              <xsl:with-param name="count">
                  <xsl:value-of select="$count"/>
              </xsl:with-param>
          </xsl:call-template>
       </xsl:if>
    

    现在你调用该模板简单填写count(Process)作为参数,并将计数填入先前保存的“最大” - 您从链接问题{{1}中的第一个模板获得的节点作为参数计数。

    叹息似乎是你遇到了一些XSLT很难的点。

    希望有所帮助!