XSLT - Добавление элементов динамически - PullRequest
2 голосов
/ 22 сентября 2009

Мне нужно отобразить определенное содержимое XML в табличной форме (XSL-FO для отчетов в формате pdf), и не все отображаемые столбцы присутствуют в исходном XML. Итак, мне было интересно если есть способ преобразовать исходный XML путем встраивания дополнительных столбцов на основе определенные значения элементов, а затем обработать полученный XML для отображения содержимого?

Например, для исходных данных:

<projectteam>
  <member>
    <name>John Doe</name>
    <role>dev</role>
 <hrs>100</hrs>
  </member>
  <member>
    <name>Paul Coder</name>
    <role>dev</role>
 <hrs>40</hrs>
  </member>
  <member>
    <name>Henry Tester</name>
    <role>qa</role>
 <hrs>80</hrs>
  </member>
  <member>
    <name>Peter Tester</name>
    <role>qa</role>
 <hrs>40</hrs>
  </member>
</projectteam>

Я бы хотел, чтобы данные отображались как:

Name         Role  Dev   QA
---------------------------
John Doe     dev   100  
Paul Coder   dev    40
Henry Tester qa          80
Peter Tester qa          40
---------------------------
Role Totals:       140  120
---------------------------

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

    <xsl:element name="{role}">
      <xsl:value-of select="member/hrs"/>
    </xsl:element>

Чтобы я мог вставлять элементы 100 и т. Д. Во время выполнения во время сначала пройти, а затем использовать полученный XML для отображения данных для нового columsn 'dev' и 'qa', таким образом, вычисление итогов для каждого типа роли будет намного проще (например, "sum (previous-sibling :: member / dev)" для столбца dev) и данные для каждого ячейка в столбцах 'dev' и 'qa' может быть просто значением этих тегов соответственно.

Он добился желаемых результатов, используя следующую таблицу стилей (форматирование страницы). подробности опущены для краткости), но я не уверен, что это подходящее решение.

    ...
              <fo:table-body>
      <!-- fills table rows -->
                <xsl:apply-templates select="member"/>

      <!-- dislpay totals for each role -->
      <fo:table-row height="12pt" border-bottom="1pt solid black">
      <fo:table-cell number-columns-spanned="2">
        <fo:block>Role Totals:</fo:block>
      </fo:table-cell>

      <fo:table-cell text-align="right">
        <xsl:call-template name="RoleTotals">
          <xsl:with-param name="node" select="//member[1]"/>
         <xsl:with-param name="roleName" select="'dev'"/>
        </xsl:call-template>
      </fo:table-cell>
      <fo:table-cell text-align="right">
        <xsl:call-template name="RoleTotals">
          <xsl:with-param name="node" select="//member[1]"/>
         <xsl:with-param name="roleName" select="'qa'"/>
        </xsl:call-template>
      </fo:table-cell>
      </fo:table-row>
              </fo:table-body>
    ...
    </fo:root>
  </xsl:template>

  <xsl:template match="member">
  <fo:table-row border-bottom="1pt solid black">
      <fo:table-cell> <fo:block> <xsl:value-of select="name"/></fo:block></fo:table-cell>
      <fo:table-cell> <fo:block> <xsl:value-of select="role"/></fo:block></fo:table-cell>
      <fo:table-cell text-align="right">
        <fo:block> 
      <xsl:if test="role = 'dev'"><xsl:value-of select="hrs"/></xsl:if>
  </fo:block>
      </fo:table-cell>
      <fo:table-cell text-align="right">
        <fo:block> 
      <xsl:if test="role = 'qa'"><xsl:value-of select="hrs"/></xsl:if>
  </fo:block>
      </fo:table-cell>
    </fo:table-row>
  </xsl:template>

  <xsl:template name="RoleTotals">
    <xsl:param name="node"/>
    <xsl:param name="roleName"/>
    <xsl:param name="RT" select="0"/>
    <xsl:variable name="newRT">
    <xsl:choose>
      <xsl:when test="$node/role = $roleName">
         <xsl:value-of select="$RT + $node/hrs"/>
      </xsl:when>
      <xsl:otherwise><xsl:value-of select="$RT"/></xsl:otherwise>
    </xsl:choose>
    </xsl:variable>
   <xsl:choose>
     <xsl:when test="$node/following-sibling::member">
      <xsl:call-template name="RoleTotals">
        <xsl:with-param name="node" select="$node/following-sibling::member[1]"/>
        <xsl:with-param name="roleName" select="$roleName"/>
        <xsl:with-param name="RT" select="$newRT"/>
      </xsl:call-template>
     </xsl:when>
     <xsl:otherwise>
      <fo:block><xsl:value-of select="$newRT"/></fo:block>
     </xsl:otherwise>
   </xsl:choose> 
  </xsl:template>

Ответы [ 2 ]

3 голосов
/ 24 сентября 2009

Что произойдет, если будет добавлено больше рабочих мест, кроме Dev и QA? Ваша таблица стилей сможет справиться? Может быть, вы можете использовать Muenchian Grouping, чтобы получить все возможные роли в таблице стилей, а затем динамически генерировать столбцы для каждой возможной роли?

<xsl:key name="roles" match="role" use="."/>

<xsl:template match="/projectteam">
 <table border="1">
  <tr>
   <td>Name</td>
   <td>Role</td>
   <xsl:for-each select="member[generate-id(role) = generate-id(key('roles', role)[1])]">
    <td>
     <xsl:value-of select="role"/>
    </td>
   </xsl:for-each>
  </tr>
  <xsl:apply-templates select="member"/>
 </table>
</xsl:template>

<xsl:template match="member">
 <xsl:variable name="currentrole" select="role"/>
 <xsl:variable name="currenthrs" select="hrs"/>
 <tr>
  <td>
   <xsl:value-of select="name"/>
  </td>
  <td>
   <xsl:value-of select="role"/>
  </td>
  <xsl:for-each select="/projectteam/member[generate-id(role) = generate-id(key('roles', role)[1])]">
   <td>
    <xsl:choose>
     <xsl:when test="$currentrole = role">
      <xsl:value-of select="$currenthrs"/>
     </xsl:when>
    </xsl:choose>
   </td>
  </xsl:for-each>
 </tr>
</xsl:template>

Я выводил в формате HTML, а не XSL-FO, но, возможно, это дает вам общее представление.

2 голосов
/ 22 сентября 2009

Да, вы можете.

Чтобы ответить на ваш вопрос. Я не читал огромную таблицу стилей, чтобы быть правдой.

...