XSLT用于基于父节点对XML进行分组和重组

时间:2017-04-10 10:40:07

标签: xml xslt xslt-1.0

我的XML文件具有这样的结构 -

<products>
 <product>
  <id>1</id>
  <type>fruits</type>
  <varieties>
   <variety>
    <id>a</id>
    <cost>100</cost>
    <availability>Y</availability>
   </variety>
   <variety>
    <id>b</id>
    <cost>75</cost>
    <availability>N</availability>
   </variety>
  </varieties>
 </product>
 <product>
  <id>2</id>
  <type>vegetables</type>
  <varieties>
   <variety>
    <id>c</id>
    <cost>50</cost>
    <availability>Y</availability>
   </variety>
   <variety>
    <id>d</id>
    <cost>55</cost>
    <availability>Y</availability>
   </variety>
  </varieties>
 </product>
</products>

我想根据products / product / id重构给定的XML。预期的产出如下 -

<html>
 <body>
  <table border="1">
  <tr> 
   <td>1</td>
   <td>fruits</td>
   <td>a</td>
   <td>100</td>
   <td>Y</td>
  </tr> 
  <tr> 
   <td>1</td>
   <td>fruits</td>
   <td>b</td>
   <td>75</td>
   <td>N</td>
  </tr>  
  <tr> 
   <td>2</td>
   <td>vegetables</td>
   <td>c</td>
   <td>50</td>
   <td>Y</td>
  </tr> 
  <tr> 
   <td>2</td>
   <td>vegetables</td>
   <td>d</td>
   <td>55</td>
   <td>Y</td>
  </tr>
  </table>
 </body>
</html>

我已经尝试过这个XSLT,但它没有返回预期的xml。

<xsl:stylesheet version="1.0"    
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
 <products>
  <product>
   <varieties>
    <xsl:apply-templates select="products/product/varieties/variety" /> 
   </varieties>
  </product>
 </products>
</xsl:template>
<xsl:template match="products" >
<html>
 <body>
  <table border="1">
   <xsl:for-each select="products/product">
    <tr>
     <td><xsl:value-of select="id" /></td>
     <td><xsl:value-of select="type" /></td>
     <xsl:for-each select="varieties/variety" >
      <td><xsl:value-of select="id" /></td>
      <td><xsl:value-of select="cost" /></td>
      <td><xsl:value-of select="availability" /></td>
     </xsl:for-each>
    </tr> 
   </xsl:for-each>
  </table>
 </body>
</html>
</xsl:template>      
</xsl:stylesheet>

1 个答案:

答案 0 :(得分:0)

你需要匹配/产品,所以下面应该给你你想要的东西

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

<xsl:template match="/products" >
<html>
 <body>
  <table border="1">
   <xsl:for-each select="product">
    <tr>
     <td><xsl:value-of select="id" /></td>
     <td><xsl:value-of select="type" /></td>
     <xsl:for-each select="varieties/variety" >
      <td><xsl:value-of select="id" /></td>
      <td><xsl:value-of select="cost" /></td>
      <td><xsl:value-of select="availability" /></td>
     </xsl:for-each>
    </tr> 
   </xsl:for-each>
  </table>
 </body>
</html>
</xsl:template>      
</xsl:stylesheet>

恕我直言,如果你对每种产品有不同数量的品种,你的HTML输出可能会非常混乱。我不知道你的申请,但你可能想考虑根据品种的数量在前两列使用rowspan,每个品种有一行。

根据OP反馈更新

我已经包含了跨越重复数据的代码,如果您不喜欢,那么随意删除if开始和结束标记并删除rowspan属性

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

<xsl:template match="/products" >
<html>
 <body>
     <table border="1">
        <xsl:for-each select="product">
        <xsl:variable name="ProductID" select="id"/>
        <xsl:variable name="ProductType" select="type"/>
        <xsl:variable name="VarietyCount" select="count(varieties/variety)"/>
         <xsl:for-each select="varieties/variety" >
            <tr>
                <xsl:if test="position() = 1">
                     <td rowspan="{$VarietyCount}"><xsl:value-of select="$ProductID" /></td>
                     <td rowspan="{$VarietyCount}"><xsl:value-of select="$ProductType" /></td>
                </xsl:if>
                  <td><xsl:value-of select="id" /></td>
                  <td><xsl:value-of select="cost" /></td>
                  <td><xsl:value-of select="availability" /></td>
            </tr> 
            </xsl:for-each>
        </xsl:for-each>
     </table>
 </body>
</html>
</xsl:template>      
</xsl:stylesheet>