XSLT - Ajout d'éléments dynamiquement
Question
J'ai besoin d'afficher certains contenus XML sous forme de tableau (XSL-FO pour les rapports PDF), et pas toutes les colonnes à afficher sont présents en XML source. Alors, je me demandais s'il y a un moyen de transformer XML source en intégrant des colonnes supplémentaires en fonction de certaines valeurs d'éléments, et traiter ensuite le XML résultant pour afficher le contenu?
À titre d'exemple, pour les données source:
<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>
Je voudrais les données à afficher comme:
Name Role Dev QA --------------------------- John Doe dev 100 Paul Coder dev 40 Henry Tester qa 80 Peter Tester qa 40 --------------------------- Role Totals: 140 120 ---------------------------
Je voudrais savoir si je peux utiliser quelque chose comme:
<xsl:element name="{role}"> <xsl:value-of select="member/hrs"/> </xsl:element>
Alors que je peux intégrer des éléments
Il a obtenu les résultats souhaités à la dure à l'aide suivantes stylesheet (page mise en forme détails omis de le garder bref), mais ne suis pas convaincu que c'est la solution apt.
... <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>
La solution
Oui, vous pouvez.
Pour répondre à votre question. Je n'ai pas lu l'énorme feuille de style, pour être vrai.
Autres conseils
Que se passerait-il si plus de rôles d'emploi, autres que Dev et QA se sont ajoutés? Est-ce que votre stylesheet être en mesure de faire face? Peut-être que vous pouvez utiliser Muenchian groupe afin d'obtenir tous les rôles possibles dans la feuille de style, puis générer des colonnes pour chaque rôle possible dynamiquement?
<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>
Je suis en HTML émis, non XSL-FO, mais peut-être que cela vous donne l'idée générale.