1

是否可以在 XSLT 中解析这种文本:

详细信息|Numéro appelé|Date et heure|Quantité réelle|Qantité facturée|HT|TTC
Appel 与 unportable|0611XXXXXX|14/06 - 09h32|00h00mn23s|00h00mn23s|gratuit|gratuit
Appel 与 unportable|0688XXXXXX|14/06 - 10h39|00h01mn16s|00h01mn16s|gratuit|gratuit
Appel 与 unportable|0611XXXXXX|18/06 - 07h24|00h00mn50s|00h00mn50s|gratuit|gratuit
Appel 与 unportable|0688XXXXXX|20/06 - 09h32|00h00mn23s|00h00mn23s|gratuit|gratuit
Appel 与 unportable|0688XXXXXX|20/06 - 10h44|00h01mn27s|00h01mn27s|gratuit|gratuit
Appel 与 unportable|0611XXXXXX|25/06 - 21h09|00h00mn22s|00h00mn22s|gratuit|gratuit
Appel 与 unportable|0626XXXXXX|29/06 - 11h25|00h00mn27s|00h00mn27s|gratuit|gratuit
Appel 与 unportable|0688XXXXXX|02/07 - 13h39|00h02mn37s|00h02mn37s|gratuit|gratuit

此表是变量中的内容,我想替换“|” 字符</td><td><th>如果可能的话,可能在第一行)并添加<tr>.

并且... 使用 XSLT 1.0 执行此操作。

非常感谢。

4

4 回答 4

0

不使用扩展会很痛苦,您必须将其作为外部参数传递或放入一些标签中。Xslt 是关于转换 Xml 文件而不是文本文件,因此请使用正确的工具来完成这项工作。

于 2012-10-09T23:05:14.870 回答
0

使用 XSLT 2.0 的正则表达式功能解析这样的输入要容易得多。

但是,如果您真的只需要tr每行一个,并且td每个垂直条有一个边界,您可以使用两个命名模板(或使用一个更复杂的模板)方便地做到这一点:一个解析变量并中断一行一次,将该行传递给第二个命名模板,该模板将字符序列解析为tr元素序列。在伪代码中,是这样的:

template name="emit-rows"
  param name="input"
  choose when $input = ''
     // do nothing
  otherwise 
     <tr>
      call-template name="emit-columns"
        with-param name="s"
                   value="substring-before($input,'&#xA;')
     </tr>
     call-template name="emit-rows"
       with-param name="input"
                  value="substring-after($input,'&#xA;')

template name="emit-columns"
  param name="s"
  choose when $s = ''
     <!--* do nothing *-->
  otherwise
     <td>
       value-of substring-before($s,'|')
     </td>
     call-template name="emit-columns"
        with-param name="s" value="substring-after($s,'|')
于 2012-10-10T00:14:36.597 回答
0

这是一个简单的 Perl 脚本来做你想做的事

my $tag = "th";
while(<>)
{
    s/[\r\n]*$//;
    print "<$tag>\n";
    for $f (split /\|/)
    {
        print "<td>$f</td>\n";
    }
    print "</$tag>\n";
    $tag = "tr";
}

您可能不得不根据您运行它的位置(Windows 与 Linux)来调整字符编码,以确保您的重音字符不会被破坏。我把它留给你作为练习。

这是您输入的前 3 行的输出:

<th>
<td>D▒tail</td>
<td>Num▒ro appel▒&lt;/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>
</th>
<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>
于 2012-10-10T03:07:21.463 回答
0

正如其他人所说,这绝对不是 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="'&#10;'"/>
                </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>
于 2012-10-10T03:36:40.907 回答