xslt - 合并一些元素并对它们进行排序

时间:2014-12-06 21:38:51

标签: xml xslt

我有这个xml代码

<realtime_result>
  <team>
    <team_name>real madrid</team_name>
    <events>
      <yellow_card time="28">ronaldo</yellow_card>
      <yellow_card time="31">ronaldo</yellow_card>
      <red_card time="39">benzema</red_card>
          .
          .
    </events>
  </team>
  <team>
    <team_name>Barcelona</team_name>
    <events>
      <goal time="25">messi</goal>
      <red_card time="44">messi</red_card>
      <yellow_card time="63">iniesta</yellow_card>
          .
          .
    </events>
  </team>
</realtime_result>

我需要一个xslt代码将其转换为这样的表:

<table>
  <tr>
    <th>real madrid</th>
    <th>time</th>
    <th>barcelona</th>
  </tr>
  <tr>
    <td></td>
    <td>25</td>
    <td>goal : messi</td>
  </tr>
  <tr>
    <td>yello card : ronaldo</td>
    <td>28</td>
    <td>barcelona</td>
  </tr>
    .
    .
<table>

请注意事件已排序(25,28,31,39,44 ......)。

任何人都可以帮助我吗? 非常感谢。

1 个答案:

答案 0 :(得分:1)

您的示例输入XML无效 - 缺少第一个结束team标记,第二个团队的事件具有错误的结束标记。此外,所需的输出有点不清楚 - 第一个事件不会显示团队名称,而第二个事件则显示。我猜团队名称不应该显示,因为它已经在标题中,遵循XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>
<xsl:strip-space elements="*"/>
    <xsl:template match="realtime_result">
      <table>
         <tr>
            <th>
                <xsl:value-of select="//team[1]/team_name"/>
            </th>
            <th>time</th>
            <th>
                <xsl:value-of select="//team[2]/team_name"/>
            </th>
        </tr>
        <xsl:apply-templates select="//events/*">
            <xsl:sort select="@time"/>
        </xsl:apply-templates>
      </table>
    </xsl:template>
    <xsl:template match="*">
      <tr>
        <td>
          <xsl:if test="
            parent::events/preceding-sibling::team_name
                                              [
                                                normalize-space()='real madrid'
                                              ]">
           <xsl:value-of select="concat(local-name(),' : ', .)"/>
         </xsl:if>
        </td>
        <td><xsl:value-of select="@time"/></td>
        <td>
          <xsl:if test="
            parent::events/preceding-sibling::team_name
                                             [
                                               normalize-space()='Barcelona'
                                             ]">
           <xsl:value-of select="concat(local-name(),' : ', .)"/>
         </xsl:if>
       </td>
     </tr>
  </xsl:template>
</xsl:stylesheet>

当应用于更正的输入时,XML具有输出

<table>
   <tr>
      <th>real madrid</th>
      <th>time</th>
      <th>Barcelona</th>
   </tr>
   <tr>
      <td></td>
      <td>25</td>
      <td>goal : messi</td>
   </tr>
   <tr>
      <td>yellow_card : ronaldo</td>
      <td>28</td>
      <td></td>
   </tr>
   <tr>
      <td>yellow_card : ronaldo</td>
      <td>31</td>
      <td></td>
   </tr>
   <tr>
      <td>red_card : benzema</td>
      <td>39</td>
      <td></td>
   </tr>
   <tr>
      <td></td>
      <td>44</td>
      <td>red_card : messi</td>
   </tr>
   <tr>
      <td></td>
      <td>63</td>
      <td>yellow_card : iniesta</td>
   </tr>
</table>

在将模板应用于事件时,使用<xsl:sort select="@time"/>按时间对事件进行排序。生成行的模板使用

检查团队名称
<xsl:if test="parent::events/preceding-sibling::team_name
                                             [
                                               normalize-space()='Barcelona'
                                             ]">

由于输入XML在team_name上没有任何空格,因此也可以写为

<xsl:if test="parent::events/preceding-sibling::team_name
                                             [
                                              .='Barcelona'
                                             ]"> 

normalize-space()只会删除检查相等时有时需要的任何前导或尾随空格 事件单元格的值仅针对当前事件的团队编写,并使用local-name()检索事件名称。

供参考:xsl:sortlocal-name()normalize-space(),以及XPath轴的http://www.xmlplease.com/axis

可能有用的可视化

作为旁注 - 虽然你的问题被一些成员低估了,因为正如你在评论中注意到的那样,它没有显示任何先前的努力,我只是想给你一个答案,因为你已经是1的SO成员了半年,这是你的第一个问题。对于即将出现的问题,最好包括您已尝试寻找解决方案或将问题减少到特定问题,而不是询问如何为输入X获取输出Y.如一条评论中所述,您可能会考虑使用看看https://stackoverflow.com/help/how-to-ask