How to count elements in categorys and compare it with other categorys in XSLT

两盒软妹~` 提交于 2019-12-11 17:00:02

问题


i have a problem :-)

i would like to print out a xml and write a xslt for it. the problem is that i would like to build a table with my xml-elements but i must count if each row has the same amount of columns and if not i have to add a value element.

i know that i cant change a variables value once i have set the value but how can i compare the categorys/table-rows amount of processes then? (and add empty rows)

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>

Desired output:

<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>

回答1:


Preserving yours, this stylesheet:

<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>

With this input:

<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>

Output:

<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>

Note: Well known maximum idiom.




回答2:


thank´s for your answers, i have solved it myself in the last 4-5 hours ~_~

first, get the count:

<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>

second, add the Processes and after this add the empty ones:

<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>



回答3:


So you should do this in 2 Steps:

  1. Identifiing the row with the maximum number of columns
  2. Iterating all rows filling up the missing columns

So the first part is what's the core problem here because it is not possible to find this out just by xpath.

The Answers to this questions confirmed that:

Find the maximum child count with XPath 1.0

I'm trying to answer this question now for about 30 mins. And i am really familiar to XML and XSLT due to my job. But i could't just figure out how to find the element with the maximum count of child elements. But someone else did before:

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

btw: this guy diserves an upvote on his answer!

If you have that we come to step 2:

In your Category template just add a call to the following template (which is just a for loop):

<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>

Now then you call that template simpy fill in the count(Process) as param i and fill in the count to your previously saved "Maximum" - Node which you got from the first template out of the linked question count(maximumnode/Process) as param count.

Sigh seems that you hit some points where XSLT is kind of hard.

Hope that helps!



来源:https://stackoverflow.com/questions/5192267/how-to-count-elements-in-categorys-and-compare-it-with-other-categorys-in-xslt

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!