用于可变长度子节点的XSLT

用于可变长度子节点的XSLT,xslt,Xslt,我正在尝试为以下XML结构编写XSLT模板: <dealership> <division> <division_name>BMW</division_name> <models> <model_no>328i</model_no> <model_no>M3</model_no>

我正在尝试为以下XML结构编写XSLT模板:

<dealership>
    <division>
        <division_name>BMW</division_name>
        <models>
            <model_no>328i</model_no>       
            <model_no>M3</model_no>
            <model_no>X5</model_no>
            <model_no>528i</model_no>
        </models>
        <salesman>
            <salesman_name>Bob</salesman_name>
            <salesman_name>Jerry</salesman_name>
        </salesman>
        <mechanics>
            <mechanic_name>Greg</mechanic_name>
            <mechanic_name>Mike</mechanic_name>
            <mechanic_name>Sean</mechanic_name>
        </mechanics>
    </division>
</dealership>

宝马
328i
M3
X5
528i
上下快速移动
杰瑞
格雷格
迈克
肖恩
我需要以以下格式将其输出到HTML表:

<table>
  <tr>
   <th>Division</th>
   <th>Models</th>
   <th>Salesman</th>
   <th>Mechanics</th>   
 </tr>
 <tr>
  <td>BMW</td>
  <td>328i</td>
  <td>Bob</td>
  <td>Greg</td>
 </tr>
 <tr>
   <td></td>
   <td>M3</td>
   <td>Jerry</td>
   <td>Mike</td>
 </tr>
 <tr>
   <td></td>
   <td>X5</td>
   <td></td>
   <td>Sean</td>
 </tr>
 <tr>
   <td></td>
   <td>528i</td>
   <td></td>
   <td></td>
 </tr>
</table>

分开
模型
售货员
机械师
宝马
328i
上下快速移动
格雷格
M3
杰瑞
迈克
X5
肖恩
528i

问题是可以有任意数量的模型、推销员和机械师。所以我需要让子节点最多的节点知道表中要创建多少行,然后我需要一种方法来跟踪行中哪些单元格是空的。任何帮助都将不胜感激。

我能想到的最好的方法是使用行号作为参数调用命名模板。然后,模板将检查是否有任何数据要输出,如果有,则构建表的该行,并使用下一行号作为新参数值调用自己

这段代码演示。输出与您显示的HTML不同,因为您的输出与您提供的XML数据不对应。据我所知,这是正确的

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output indent="yes" method="html" />

  <xsl:template match="/dealership/division">
    <table>
      <tr>
        <th>Division</th>
        <th>Models</th>
        <th>Salesman</th>
        <th>Mechanics</th>   
      </tr>
      <xsl:call-template name="row" >
        <xsl:with-param name="i" select="1" />
      </xsl:call-template>
    </table>
  </xsl:template>

  <xsl:template name="row">
    <xsl:param name="i"/>

    <xsl:if test="models/model_no[$i] |
                  salesman/salesman_name[$i] |
                  mechanics/mechanic_name[$i]">
      <tr>
        <td>
          <xsl:value-of select="division_name[$i]"/>
        </td>
        <td>
          <xsl:value-of select="models/model_no[$i]"/>
        </td>
        <td>
          <xsl:value-of select="salesman/salesman_name[$i]"/>
        </td>
        <td>
          <xsl:value-of select="mechanics/mechanic_name[$i]"/>
        </td>
      </tr>

      <xsl:call-template name="row" >
        <xsl:with-param name="i" select="$i + 1" />
      </xsl:call-template>

    </xsl:if>

  </xsl:template>


</xsl:stylesheet>

分开
模型
售货员
机械师
输出

<table>
   <tr>
      <th>Division</th>
      <th>Models</th>
      <th>Salesman</th>
      <th>Mechanics</th>
   </tr>
   <tr>
      <td>BMW</td>
      <td>328i</td>
      <td>Bob</td>
      <td>Greg</td>
   </tr>
   <tr>
      <td></td>
      <td>M3</td>
      <td>Jerry</td>
      <td>Mike</td>
   </tr>
   <tr>
      <td></td>
      <td>X5</td>
      <td></td>
      <td>Sean</td>
   </tr>
</table>

分开
模型
售货员
机械师
宝马
328i
上下快速移动
格雷格
M3
杰瑞
迈克
X5
肖恩

听听另一种可能的解决方案


分开
模型
售货员
机械师

第一步是找出除法的哪个子级自身拥有最多的子级。这是通过按子项计数排序的for-each-over-all子项来完成的。因此,第一个问题是孩子最多的问题

    <xsl:for-each select="*" >
        <xsl:sort select="count(*)" order="descending"/>
        <xsl:if test ="position()=1">
            <xsl:value-of select="name(.)"/>
        </xsl:if>
    </xsl:for-each>


这是基于Dimitre Novatchev的一个非常好的解释,您的输出HTML与您的输入不完全一致。例如,“335i”和“528i”从哪里来,可怜的老“M3”怎么了?你的权利,我做了编辑,使它们现在匹配哦,谢谢。我已经开始担心我是唯一一个喜欢它的人,至少有一点顺便说一句,北达科他州的情况真的这么糟吗?不好——我在一部电影中看过这句话,觉得很有趣。:)
    <xsl:for-each select="*" >
        <xsl:sort select="count(*)" order="descending"/>
        <xsl:if test ="position()=1">
            <xsl:value-of select="name(.)"/>
        </xsl:if>
    </xsl:for-each>