正如其他人所说,这绝对不是 XSLT 的工作 - 但是,只是为了好玩,它可以使用 XSLT1.0 来完成。这是使用 XMLSpy 测试的——因此它可能需要使用 exslt 将结果树片段转换为节点集。但原理是一样的。
对于技术解决方案,请跳过接下来的几段
编辑(基于问题中的评论):我没有足够的代表在正确的地方发表评论,但是,这个问题是技术解决方案不够时的完美示例。
您曾说过您“别无选择”来使用 XSLT,但我认为这突出了我在许多 IT 专业人员中看到的一个问题。您可能无法选择工作环境的当前状态(我假设这是一个工作解决方案,因为没有正确思维的教育者会将此作为如何使用 XSLT 的示例)。您可以选择的是如何将此解决方案交付给任何提出请求的人。
这个问题的真正解决方案是 XSLT 肯定不是解决这个问题的正确方法,这就是你的雇主或客户需要被告知的。虽然我下面的解决方案是解决您的问题的完全有效的方法,但我建议这不是最佳实践,不是 XSLT 的适当使用,也不是解决此问题的最有效方法,在专业环境中,您有责任说同样的话。
人们可能不喜欢被告知他们的环境是错误的,或者他们希望如何解决问题而不是应该如何解决,但如果他们向您寻求建议,那么您的建议应该在适当的情况下包括批评。所以无论如何,请在下面提出解决方案,但一定要提出上面的论点 - 这样即使他们在 XSLT 中实现它,至少你已经尽了你的责任来告知和教育,如果最终结束,如果该批评被记录在案使用糟糕的解决方案,如果它坏了,你将不负责。
实际的 XSLT 解决方案从这里开始:
输入(请注意,您需要在代码周围添加一个标签才能使其成为有效的 XML):
<text>Détail|Numéro appelé|Date et heure|Quantité réelle|Qantité facturée|H.T.|T.T.C.
Appel vers un portable|06110XXXXX|14/06 - 09h32|00h00mn23s|00h00mn23s|gratuit|gratuit
Appel vers un portable|06889XXXXX|14/06 - 10h39|00h01mn16s|00h01mn16s|gratuit|gratuit
Appel vers un portable|06110XXXXX|18/06 - 07h24|00h00mn50s|00h00mn50s|gratuit|gratuit
Appel vers un portable|06889XXXXX|20/06 - 09h32|00h00mn23s|00h00mn23s|gratuit|gratuit
Appel vers un portable|06889XXXXX|20/06 - 10h44|00h01mn27s|00h01mn27s|gratuit|gratuit
Appel vers un portable|06110XXXXX|25/06 - 21h09|00h00mn22s|00h0n0mn22s|gratuit|gratuit
Appel vers un portable|06267XXXXX|29/06 - 11h25|00h00mn27s|00h00mn27s|gratuit|gratuit
Appel vers un portable|06889XXXXX|02/07 - 13h39|00h02mn37s|00h02mn37s|gratuit|gratuit
Appel vers un portable|06889XXXXX|02/07 - 18h17|00h06mn55s|00h06mn55s|gratuit|gratuit
Appel vers un portable|06110XXXXX|05/07 - 19h29|00h00mn15s|00h00mn15s|gratuit|gratuit</text>
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:variable name="lines">
<xsl:call-template name="tokenize">
<xsl:with-param name="string">
<xsl:value-of select="."/>
</xsl:with-param>
<xsl:with-param name="token">
<xsl:value-of select="' '"/>
</xsl:with-param>
</xsl:call-template>
</xsl:variable>
<table>
<xsl:for-each select="$lines/match">
<xsl:variable name="cells">
<xsl:call-template name="tokenize">
<xsl:with-param name="string">
<xsl:value-of select="."/>
</xsl:with-param>
<xsl:with-param name="token">
<xsl:value-of select="'|'"/>
</xsl:with-param>
</xsl:call-template>
</xsl:variable>
<tr>
<xsl:for-each select="$cells/match">
<td><xsl:value-of select="."/></td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:template>
<!--
Tokenize with a string and token allows us to split up string on a given token and return a node-set of all of the separate components in <match> tags.
Taken from: http://stackoverflow.com/a/141022/764357
Then modified to use a generic split token.
-->
<xsl:template name="tokenize">
<xsl:param name="string"/>
<xsl:param name="token" select="','"/>
<xsl:param name="count" select="0"/>
<xsl:variable name="first_elem" select="substring-before(concat($string,$token), $token)"/>
<!-- Make sure at least one token at the end exists -->
<xsl:variable name="remaining" select="substring-after($string, $token)"/>
<match>
<xsl:value-of select="$first_elem"/>
</match>
<!--
We check that the remaining list is not just a single token, if it is then the recursive base case has been identified.
-->
<xsl:if test="$remaining and $remaining != $token">
<xsl:call-template name="tokenize">
<xsl:with-param name="string" select="$remaining"/>
<xsl:with-param name="token" select="$token"/>
<xsl:with-param name="count" select="$count + 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
和输出:
<table>
<tr>
<td>Détail</td>
<td>Numéro appelé</td>
<td>Date et heure</td>
<td>Quantité réelle</td>
<td>Qantité facturée</td>
<td>H.T.</td>
<td>T.T.C.</td>
</tr>
<tr>
<td>Appel vers un portable</td>
<td>06110XXXXX</td>
<td>14/06 - 09h32</td>
<td>00h00mn23s</td>
<td>00h00mn23s</td>
<td>gratuit</td>
<td>gratuit</td>
</tr>
<tr>
<td>Appel vers un portable</td>
<td>06889XXXXX</td>
<td>14/06 - 10h39</td>
<td>00h01mn16s</td>
<td>00h01mn16s</td>
<td>gratuit</td>
<td>gratuit</td>
</tr>
<tr>
<td>Appel vers un portable</td>
<td>06110XXXXX</td>
<td>18/06 - 07h24</td>
<td>00h00mn50s</td>
<td>00h00mn50s</td>
<td>gratuit</td>
<td>gratuit</td>
</tr>
<tr>
<td>Appel vers un portable</td>
<td>06889XXXXX</td>
<td>20/06 - 09h32</td>
<td>00h00mn23s</td>
<td>00h00mn23s</td>
<td>gratuit</td>
<td>gratuit</td>
</tr>
<tr>
<td>Appel vers un portable</td>
<td>06889XXXXX</td>
<td>20/06 - 10h44</td>
<td>00h01mn27s</td>
<td>00h01mn27s</td>
<td>gratuit</td>
<td>gratuit</td>
</tr>
<tr>
<td>Appel vers un portable</td>
<td>06110XXXXX</td>
<td>25/06 - 21h09</td>
<td>00h00mn22s</td>
<td>00h0n0mn22s</td>
<td>gratuit</td>
<td>gratuit</td>
</tr>
<tr>
<td>Appel vers un portable</td>
<td>06267XXXXX</td>
<td>29/06 - 11h25</td>
<td>00h00mn27s</td>
<td>00h00mn27s</td>
<td>gratuit</td>
<td>gratuit</td>
</tr>
<tr>
<td>Appel vers un portable</td>
<td>06889XXXXX</td>
<td>02/07 - 13h39</td>
<td>00h02mn37s</td>
<td>00h02mn37s</td>
<td>gratuit</td>
<td>gratuit</td>
</tr>
<tr>
<td>Appel vers un portable</td>
<td>06889XXXXX</td>
<td>02/07 - 18h17</td>
<td>00h06mn55s</td>
<td>00h06mn55s</td>
<td>gratuit</td>
<td>gratuit</td>
</tr>
<tr>
<td>Appel vers un portable</td>
<td>06110XXXXX</td>
<td>05/07 - 19h29</td>
<td>00h00mn15s</td>
<td>00h00mn15s</td>
<td>gratuit</td>
<td>gratuit</td>
</tr>
</table>