XSLT к HTML с простым группировкой данных XML с использованием шаблонов вместо каждого

StackOverflow https://stackoverflow.com/questions/3006818

Вопрос

Я разговаривал с XSLT и включенным, поскольку я стал администратором SharePoint, он использует XSLT Olot для отображения данных списка. Я недавно начал использовать его для преобразования результатов базы данных, которые я преобразовал в XML с помощью метода расширения. Я пытаюсь произвести чистый HTML.

Моя первая попытка, работала нормально. Однако я использовал для каждого повсюда, с тех пор, как я прочитал, что это плохо. Я читаю кучу вещей об использовании клавиш, но я не мог понять это или получить его на работу. Поэтому я переписал этот стиль листа ниже к тому, который находится под ним. Он использует шаблоны без для каждого.

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

Я не включал ввод пример и вывод, так как все автоматически генерируется. Если это необходимо, я могу взять много времени и попытаться что-то произвести.

Мой вопрос в том, это лучший способ сделать это? Также, если ключевой способ лучше, может кто-то объяснить это или предоставить ссылку на хорошее объяснение?

Это было полезно?

Решение

В основном вопрос об использовании for-each Вс. Шаблоны сводится к созданию многоразовых, более общих преобразований.

Используя шаблоны, все соответствующие узлы - нет только тех, которые явно используются в каждом - могут извлечь выгоду из шаблона, что помогает избежать дубликата кода и в то же время нарушает лист на более мелкие агрегаты, которые легче управлять. Это на самом деле в значительной степени так же, как иметь огромную процедуру или меньшие процедуры, вызывающие друг друга в императивном программировании.

Хотя некоторые люди предполагают, что использование шаблонов может работать лучше в некоторых двигателях, я считаю, что это не будет иметь значение.

Что сказал, вы можете узнать о Мюнченский метод (который использует ключевые ключи) для фактически группировки данных, где вы повторные ключи. Использование 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', .))]" />

Другие советы

Шаблон «для каждого» - это хорошая особенность XSLT.

Советы по использованию «шаблонов» вместо «для каждого» в основном о возможном неправильном использовании модели обработки XSLT.

В вашем примере ясно: один наивный «шаблон» и многие «для каждого», которые направляют процесс.

Использование ключа в самом XSLT о производительности. Его полезность заключается в замене выражений XPath, которые включают повторяющиеся путешествия на многие узлы входного дерева. MUENCHIAN Способ группировки - это специальное использование ключей. Простая группировка может быть оптимально без использования ключей.

С другой стороны, население - это особый случай преобразования. Я думаю, что лучше поддерживать, чтобы отделить семантику XHTML от преобразования XSLT. Проверьте www.aranedabienesraises.com.ar в качестве примера.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top