3

自从我成为共享点管理员以来,我一直在断断续续地使用 xslt,它使用 xslt 来显示列表数据。我最近开始使用它来转换我使用扩展方法转换为 xml 的数据库结果。我正在尝试生成干净的 html。

我的第一次尝试,效果很好。但是,我到处都使用 for-each,从那以后我读到这是一件坏事。我读了一堆关于使用密钥的东西,但我无法理解或让它工作。所以我重写了这个样式表,下面是它下面的那个。它使用没有 for-each 的模板。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="/">


<html>
  <head>
    <link rel="Stylesheet" type="text/css" href="../styles/BoxReportStyle.css" />
  </head>
  <body>


    <span class="BoxReport">
      <h2>Checked Out Boxes by Department with Transaction History</h2>

      Count=<xsl:value-of select="count( /CheckedOutBoxes/row ) "/>

    <!-- Get the divisions, since we are groing to group by division-->
    <xsl:variable name="DivisionList" select="/CheckedOutBoxes/row[ not( Division = preceding-sibling::row/Division ) ]/Division" />

    <xsl:for-each select="$DivisionList">

      <xsl:variable name="DivisionName" select="." />

      <h3>
        <xsl:value-of disable-output-escaping="yes" select="$DivisionName "/>
      </h3>

      <!-- Get the list of departments, so we can group by department -->
      <xsl:variable name="DepartmentList" select="/CheckedOutBoxes/row[ Division = $DivisionName and not( Department = preceding-sibling::row/Department) ]/Department" />

      <xsl:for-each select="$DepartmentList">
        <xsl:variable name="DepartmentName" select="." />

        <h4>
          <xsl:value-of disable-output-escaping="yes" select="$DepartmentName"/>
        </h4>

        <xsl:variable name="Rows" select="/CheckedOutBoxes/row[ Division = $DivisionName and Department = $DepartmentName ]" />

        <!-- Start displaying the checked out box information for this division and department -->
        <table>
          <th>Box Number</th>
          <th>Status Name</th>
          <th>Entry Date</th>
          <th>Description</th>

          <xsl:for-each select="$Rows">

            <tr>
              <td>
                <xsl:value-of select="BoxNumber"/>
              </td>
              <td>
                <xsl:value-of select="StatusName"/>
              </td>
              <td>
                <xsl:value-of select="EntryDate"/>
              </td>
              <td width="200px">
                <xsl:value-of disable-output-escaping="yes" select="Description"/>
              </td>

            </tr>

            <!-- Now display the transaction history if there is any-->
            <xsl:if test=" count( Transaction ) > 0 ">
              <tr>
                <td></td> <!-- One blank row to shift things over-->
                <td colspan="3">
                  <!-- Display transaction table-->
                  <table class="SubTable">
                    <th>Transaction Date</th>
                    <th>Requestor</th>
                    <th>Comments</th>

                    <xsl:for-each select="Transaction" >
                      <tr>
                        <td>
                          <xsl:value-of select="TransactionDate"/>
                        </td>
                        <td>
                          <xsl:value-of select="Requestor"/>
                        </td>
                        <td width="200px">
                          <xsl:value-of disable-output-escaping="yes" select="Comments"/>
                        </td>
                      </tr>
                    </xsl:for-each>
                  </table>
                </td>
              </tr>
            </xsl:if>
          </xsl:for-each>
        </table>

      </xsl:for-each>

    </xsl:for-each>
    </span>


  </body>

</html>


  </xsl:template>



</xsl:stylesheet>

我现在将其重写为:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">



 <xsl:template match="/">
<html>
  <head>
    <link rel="Stylesheet" type="text/css" href="../styles/BoxReportStyle.css" />
  </head>
  <body>
    <span class="BoxReport">

      <h2>Checked Out Boxes by Department with Transaction History</h2>

      Count=<xsl:value-of select="count( /CheckedOutBoxes/row ) "/>

      <xsl:apply-templates mode="Division" select="/CheckedOutBoxes/row[ not( Division = preceding-sibling::row/Division ) ]"></xsl:apply-templates>


    </span>
  </body>
</html>
  </xsl:template>

 <xsl:template mode="Division" match="row">
<h3>
  <xsl:value-of select="Division" disable-output-escaping="yes"/>
</h3>

<xsl:variable name="DivisionName" select="Division" />

<xsl:apply-templates mode="Department" select="/CheckedOutBoxes/row[ Division = $DivisionName and not( Department = preceding-sibling::row/Department ) ]"></xsl:apply-templates>

</xsl:template>

 <xsl:template mode="Department" match="row">
<h4>
  <xsl:value-of select="Department" disable-output-escaping="yes"/>
</h4>

<xsl:variable name="DivisionName" select="Division" />
<xsl:variable name="DepartmentName" select="Department" />

<table>
  <th>Box Number</th>
  <th>Status Name</th>
  <th>Entry Date</th>
  <th>Description</th>

  <xsl:apply-templates mode="row" select="/CheckedOutBoxes/row[ Division = $DivisionName and Department = $DepartmentName ]" ></xsl:apply-templates>

  </table>



</xsl:template>

<xsl:template mode="row" match="row">

<tr>
  <td>
    <xsl:value-of select="BoxNumber"/>
  </td>
  <td>
    <xsl:value-of select="StatusName"/>
  </td>
  <td>
    <xsl:value-of select="EntryDate"/>
  </td>
  <td width="200px">
    <xsl:value-of disable-output-escaping="yes" select="Description"/>
  </td>

</tr>

<!-- Display Transaction stuff as another row if we have any -->
<xsl:if test=" count( Transaction ) > 0 ">
  <tr>
    <td></td><!-- Shift the transaction over-->
    <td colspan="3">
      <!-- Start Transaction Table -->
      <table class="SubTable">
        <th>Transaction Date</th>
        <th>Requestor</th>
        <th>Comments</th>

        <xsl:apply-templates select="Transaction">
          <xsl:sort order="descending" select="TransactionDate"/>
        </xsl:apply-templates>
      </table>
    </td>
  </tr>
</xsl:if>

</xsl:template>


<xsl:template match="Transaction">
<tr>
  <td>
    <xsl:value-of select="TransactionDate"/>
  </td>
  <td>
    <xsl:value-of select="Requestor"/>
  </td>
  <td width="200px">
    <xsl:value-of disable-output-escaping="yes" select="Comments"/>
  </td>
</tr>
  </xsl:template>

</xsl:stylesheet>

我没有包括示例输入和输出,因为它们都是自动生成的。如果需要,我可以花很多时间,并尝试制作一些东西。

我的问题是,这是一种更好的方法吗?此外,如果关键方法更好,有人可以解释它,或者提供一个很好的解释的链接吗?

4

2 回答 2

1

“for-each”模板是 XSLT 的一个很好的特性。

使用“模板”而不是“for-each”的建议主要是关于 XSLT 处理模型的可能滥用。

在您的示例中很清楚:一个简单的“模板”和许多指导流程的“for-each”。

XSLT 本身的关键用法与性能有关。它的用处在于替换涉及重复遍历输入树的许多节点的 XPath 表达式。Muenchian 分组方法是键的特殊用途。简单的分组可以在不使用键的情况下达到最佳效果。

另一方面,人口是转型的一个特例。我认为最好将 XHTML 语义与 XSLT 转换分开。以 www.aranedabienesraices.com.ar 为例。

于 2010-06-09T15:37:16.050 回答
1

基本上,使用for-each与模板的问题归结为创建可重用、更通用的转换。

通过使用模板,所有匹配的节点——不仅是那些在 for-each 中明确使用的节点——都可以从模板中受益,这有助于避免重复代码,同时将工作表分解成更易于管理的单元。这实际上与在命令式编程中让一个巨大的过程或较小的过程相互调用几乎相同。

虽然有些人建议在某些引擎中使用模板可能会表现得更好,但我相信这并不会真正产生影响。

也就是说,您可能想了解muenchian 方法(它使用键)来实际对具有重复键的数据进行分组。在某些发动机上,轴的使用preceding-sibling非常缓慢,因此最好在不是绝对需要时避免使用它。

像这样的东西应该对部门有用(未经测试):

<xsl:key name="divisions" match="/CheckedOutBoxes/row/Division" use="." />

...

<xsl:apply-templates mode="Division" select="/CheckedOutBoxes/Division[generate-id(.)=generate-id(key('divisions', .))]" />
于 2010-06-09T14:52:40.770 回答