最近碰到一个比较bt的xslt的转换需求,简化后,原xml是:


  <x>x1</x>
  
<y>y1</y>
  
<x>x2</x>
  
<y>y2</y>
  
<z>z2</z>
  
<x>x3</x>
  
<y>y3</y>
  
<x>x4</x>
  
<z>z4</z>
  
<x>x5</x>
  
<y>y5</y>
</root>

 

   而期望获得的html是一张表格:

 


  <tr>
    
<td>x</td>
    
<td>y</td>
    
<td>z</td>
  
</tr>
  
<tr>
    
<td>x1</td>
    
<td>y1</td>
    
<td></td>
  
</tr>
  
<tr>
    
<td>x2</td>
    
<td>y2</td>
    
<td>z2</td>
  
</tr>
  
<tr>
    
<td>x3</td>
    
<td>y3</td>
    
<td></td>
  
</tr>
  
<tr>
    
<td>x4</td>
    
<td></td>
    
<td>z4</td>
  
</tr>
  
<tr>
    
<td>x5</td>
    
<td>y5</td>
    
<td></td>
  
</tr>
</table>

 

   这里出现2个难题,一个是列名的distinct问题,另一个是如何正确的得到表格,而且还只能用xslt 1.0。经过整整一天的尝试,终于用写出来了一个xslt能够基本完成功能:


    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  
<xsl:output method="html" indent="yes"/>

  
<xsl:template match="/root">
    
<html>
      
<title>test</title>
      
<body>
        
<xsl:variable name="dictinctNames">
          
<xsl:element name="items">
            
<xsl:call-template name="distinct"/>
          
</xsl:element>
        
</xsl:variable>
        
<table>
          
<tr>
            
<xsl:for-each select="msxsl:node-set($dictinctNames)/items/item">
              
<td>
                
<xsl:value-of select="@name"/>
              
</td>
            
</xsl:for-each>
          
</tr>
          
<xsl:call-template name="PrintValue">
            
<xsl:with-param name="items" select="*"/>
            
<xsl:with-param name="distinctItems" select="msxsl:node-set($dictinctNames)/items/item"/>
          
</xsl:call-template>
        
</table>
      
</body>
    
</html>
  
</xsl:template>

  
<!-- Distinct value and create elements -->
  
<xsl:template name="distinct">
    
<xsl:for-each select="*[generate-id(.) =generate-id(key('nameKey', name())[1])]">
        
<xsl:element name="item">
          
<xsl:attribute name="name">
            
<xsl:value-of select="name()"/>
          
</xsl:attribute>
        
</xsl:element>
      
</xsl:for-each>
  
</xsl:template>

  
<!-- Set distinct key -->
  
<xsl:key name="nameKey" match="*" use="name()" />

  
<!-- Print table content-->
  
<xsl:template name="PrintValue">
    
<xsl:param name="items"/>
    
<xsl:param name="distinctItems"/>
      
<xsl:call-template name="PrintValueCore">
        
<xsl:with-param name="nextItems" select="$items"/>
        
<xsl:with-param name="distinctItems" select="$distinctItems"/>
        
<xsl:with-param name="nextDistinctItems" select="$distinctItems"/>
      
</xsl:call-template>
  
</xsl:template>
  
  
<!-- Core method -->
  
<xsl:template name="PrintValueCore">
    
<xsl:param name="nextItems"/>
    
<xsl:param name="distinctItems"/>
    
<xsl:param name="nextDistinctItems"/>

    
<!-- if (nextItems.Count>0) -->
    
<xsl:if test="count($nextItems)>0">

      
<xsl:if test="count($nextDistinctItems)=count($distinctItems)">
        
<xsl:text disable-output-escaping="yes"><![CDATA[<tr>]]></xsl:text>
      
</xsl:if>

      
<!-- if (nextDistinctItems.Count==0) -->
      
<xsl:if test="count($nextDistinctItems)=0">
        
<xsl:text disable-output-escaping="yes"><![CDATA[</tr>]]></xsl:text>
        
<!-- if (nextItems.Count>1) -->
        
<xsl:if test="count($nextItems)>1">
          
<!-- PrintValueCore(nextItems,distinctItems,nextDistinctItems); -->
          
<xsl:call-template name="PrintValueCore">
            
<xsl:with-param name="nextItems" select="$nextItems"/>
            
<xsl:with-param name="distinctItems" select="$distinctItems"/>
            
<xsl:with-param name="nextDistinctItems" select="$distinctItems"/>
          
</xsl:call-template>
        
</xsl:if>
      
</xsl:if>
      
      
<!-- if (nextDistinctItems.Count>0) -->
      
<xsl:if test="count($nextDistinctItems)>0">
        
<!-- string first = nextDistinctItems[0].name -->
        
<xsl:variable name="first" select="$nextDistinctItems[1]/@name"/>
        
<!-- if (first==nextItem[0].name) -->
        
<xsl:if test="$first=name($nextItems)">
          
<td>
            
<!-- nextItem[0].value -->
            
<xsl:value-of select="$nextItems[1]"/>
          
</td>
          
<!-- PrintValueCore(nextItems.Skip(1),distinctItems,nextDistinctItems.Skip(1)); -->
          
<xsl:call-template name="PrintValueCore">
            
<xsl:with-param name="nextItems" select="$nextItems/following::*"/>
            
<xsl:with-param name="distinctItems" select="$distinctItems"/>
            
<xsl:with-param name="nextDistinctItems" select="$nextDistinctItems/following::*"/>
          
</xsl:call-template>
        
</xsl:if>
        
<!-- if (first!=nextItem[0].name) -->
        
<xsl:if test="not($first=name($nextItems))">
          
<td/>
          
<!-- PrintValueCore(nextItems,distinctItems,nextDistinctItems.Skip(1)); -->
          
<xsl:call-template name="PrintValueCore">
            
<xsl:with-param name="nextItems" select="$nextItems"/>
            
<xsl:with-param name="distinctItems" select="$distinctItems"/>
            
<xsl:with-param name="nextDistinctItems" select="$nextDistinctItems/following::*"/>
          
</xsl:call-template>
        
</xsl:if>
      
</xsl:if>
      
    
</xsl:if>
    
    
<!-- if (nextItems.Count==0) -->
    
<xsl:if test="count($nextItems)=0">
      
<!-- if (nextDistinctItems.Count>0) -->
      
<xsl:if test="count($nextDistinctItems)>0">
        
<td/>
        
<!-- PrintValueCore(nextItems,distinctItems,nextDistinctItems.Skip(1)); -->
        
<xsl:call-template name="PrintValueCore">
          
<xsl:with-param name="nextItems" select="$nextItems"/>
          
<xsl:with-param name="distinctItems" select="$distinctItems"/>
          
<xsl:with-param name="nextDistinctItems" select="$nextDistinctItems/following::*"/>
        
</xsl:call-template>
      
</xsl:if>
      
<!-- if (nextDistinctItems.Count==0) -->
      
<xsl:if test="count($nextDistinctItems)=0">
        
<xsl:text disable-output-escaping="yes"><![CDATA[</tr>]]></xsl:text>
      
</xsl:if>
    
</xsl:if>

  
</xsl:template>
  
</xsl:stylesheet>

 

  但是目前还很难把目标格式从转换方法中分离出来,这个就有待以后再改良吧。

相关文章:

  • 2022-12-23
  • 2021-08-17
  • 2021-05-23
  • 2021-06-22
  • 2021-12-05
  • 2021-12-04
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-10-04
  • 2021-12-06
  • 2021-11-19
  • 2022-12-23
  • 2021-04-08
  • 2021-08-01
  • 2022-12-23
相关资源
相似解决方案