2012-01-06 61 views
1

我有以下形式的XML数据创建XML数据的TreeView:如何使用XSLT

<table> 
<col> 
    <name>Addresses</name> 
</col> 
<col> 
    <name>Addresses/Address1</name> 
</col> 
<col> 
    <name>Addresses/Address2</name> 
</col> 
<col> 
    <name>Addresses/Address1/Flat Number</name> 
</col> 
<col> 
    <name>Employee Name</name> 
</col> 
<col> 
    <name>Phone Number</name> 
</col> 
<col> 
    <name>Profession</name> 
</col> 
<col> 
    <name>Employee Name/First Name</name> 
</col> 
<col> 
    <name>Employee Name/Last Name</name> 
</col> 
<col> 
    <name>Employee Name/First_Name</name> 
</col> 
<col> 
    <name>Accounts/Account Name/First/Saving</name> 
</col> 
<col> 
    <name>Accounts/Account_Name/Second</name> 
</col> 
</table> 

现在我想创建像在使用这个XML XSLT HTML结构的树形。树视图的结构将类似于以下结构:

  • 地址
    • 地址1
    • 地址2
  • 员工姓名
  • 帐户
    • 帐户名称

请注意,“/”是树状的第一级节点和第一次出现后的子字符串“/”是第一次出现之前子匹配的第一级节点的第二级节点,这只是一个2级树视图。

此外,显示的值是唯一的值。即使这些值在XML中重复,我们也只需要选择唯一的一个值。需要考虑的另一个条件是,在示例中给出的“”的值与“”中的值不相同,因此我们需要在用“”替换“ - ”后显示值。

<xsl:variable name="currentNode" select="//table/col" /> 
<xsl:key name="uniqueCategoryKey" match="record" use="name"/> 
<xsl:key name="uniqueSubCategoryKey" match="record" use="substring-before(substring-after(concat(name,'/'),'/'),'/')"/> 
<xsl:template match="/"> 
<xsl:call-template name="treeTemplate" /> 
</xsl:template> 

<xsl:template name="treeTemplate"> 


    <div id ="newtreeview"> 
    <ul> 
     <xsl:for-each select="$currentNode[generate-id() = generate-id(key('uniqueCategoryKey', name))]"> 

     <xsl:variable name="category" select="name"/> 

     <xsl:if test="string-length($category) > 0 and not(contains($category,'/'))"> 
      <li> 
      <a href="#"> 
       <xsl:value-of select="$category"/> 
      </a> 
      <xsl:if test="//record[contains(name, concat($category,'/'))]"> 
       <ul> 

       <xsl:for-each select="$currentNode[generate-id() = generate-id(key('uniqueSubCategoryKey', substring-before(substring-after(concat(name,'/'),'/'),'/')))]"> 

        <li> 
        <a href="#"> 
         <xsl:variable name="subcat"> 
         <xsl:call-template name="string-replace-all"> 
          <xsl:with-param name="text" select="string(substring-before(substring-after(concat(name,'/'),'/'),'/'))" /> 
          <xsl:with-param name="replace" select="'_'" /> 
          <xsl:with-param name="by" select="' '" /> 
         </xsl:call-template> 
         </xsl:variable> 
         <xsl:value-of select="$subcat"/> 


        </a> 
        </li> 
       </xsl:for-each> 
       </ul> 
      </xsl:if> 
      </li> 
     </xsl:if> 
     </xsl:for-each> 
    </ul> 
    </div> 

</xsl:template> 
<xsl:template name="string-replace-all"> 
<xsl:param name="text" /> 
<xsl:param name="replace" /> 
<xsl:param name="by" /> 
<xsl:choose> 
    <xsl:when test="contains($text, $replace)"> 
    <xsl:value-of select="substring-before($text,$replace)" /> 
    <xsl:value-of select="$by" /> 
    <xsl:call-template name="string-replace-all"> 
     <xsl:with-param name="text" 
     select="substring-after($text,$replace)" /> 
     <xsl:with-param name="replace" select="$replace" /> 
     <xsl:with-param name="by" select="$by" /> 
    </xsl:call-template> 
    </xsl:when> 
    <xsl:otherwise> 
    <xsl:value-of select="$text" /> 
    </xsl:otherwise> 
</xsl:choose> 
</xsl:template> 

的问题是,这个代码是给我像

  • 地址
      • 输出 -
    • 地址1
    • 地址2
  • 员工姓名
      • -
  • 账户
    • 帐户名称
    • 帐户名称

请帮我解决这个问题。

在此先感谢。

+0

您可以提供可能的工作示例XML! – Treemonkey 2012-01-06 14:49:32

回答

2

此XSLT 1。0变换

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:key name="kCatFromName" match="name" 
     use="substring-before(concat(.,'/'), '/')"/> 

    <xsl:key name="kValFromName" match="name[contains(., '/')]" 
     use="concat(substring-before(.,'/'), 
      '+', 
      translate(
       substring-before 
       (concat(substring-after(.,'/'), '/'), 
        '/' 
       ), 
       '_', 
       ' ' 
         ) 
       ) 
      "/> 

    <xsl:template match="/*"> 
     <ul> 
     <xsl:apply-templates mode="cat" select= 
      "*/name 
      [generate-id() 
      = 
       generate-id(key('kCatFromName', 
           substring-before(concat(.,'/'), '/') 
           )[1] 
         ) 
      ] 
      "/> 
     </ul> 
    </xsl:template> 

    <xsl:template match="name" mode="cat"> 
     <xsl:variable name="vCat" select= 
     "substring-before(concat(.,'/'), '/')"/> 
     <li><xsl:value-of select="$vCat"/></li> 

     <xsl:variable name="vInThisCat" select= 
     "key('kCatFromName', $vCat) 
     [generate-id() 
     = 
      generate-id(key('kValFromName', 
          concat(substring-before(.,'/'), 
           '+', 
           translate(
              substring-before 
              (concat(substring-after(.,'/'), '/'), 
              '/' 
              ), 
              '_', 
              ' ' 
              ) 
           ) 
         )[1] 
        ) 
     ]"/> 

     <xsl:if test="$vInThisCat"> 
     <ul> 
      <xsl:apply-templates mode="val" select="$vInThisCat"/> 
     </ul> 
     </xsl:if> 
    </xsl:template> 

     <xsl:template match="name" mode="val"> 
     <li> 
      <xsl:value-of select= 
      "translate(substring-before 
       (concat(substring-after(.,'/'), '/'), 
       '/' 
       ), 
       '_', 
       ' ' 
       ) 
      "/> 
     </li> 
     </xsl:template> 
</xsl:stylesheet> 

当所提供的XML文档施加:

<table> 
    <col> 
     <name>Addresses</name> 
    </col> 
    <col> 
     <name>Addresses/Address1</name> 
    </col> 
    <col> 
     <name>Addresses/Address2</name> 
    </col> 
    <col> 
     <name>Addresses/Address1/Flat Number</name> 
    </col> 
    <col> 
     <name>Employee Name</name> 
    </col> 
    <col> 
     <name>Phone Number</name> 
    </col> 
    <col> 
     <name>Profession</name> 
    </col> 
    <col> 
     <name>Employee Name/First Name</name> 
    </col> 
    <col> 
     <name>Employee Name/Last Name</name> 
    </col> 
    <col> 
     <name>Employee Name/First_Name</name> 
    </col> 
    <col> 
     <name>Accounts/Account Name/First/Saving</name> 
    </col> 
    <col> 
     <name>Accounts/Account_Name/Second</name> 
    </col> 
</table> 

产生想要的,正确的结果

<ul> 
    <li>Addresses</li> 
    <ul> 
     <li>Address1</li> 
     <li>Address2</li> 
    </ul> 
    <li>Employee Name</li> 
    <ul> 
     <li>First Name</li> 
     <li>Last Name</li> 
    </ul> 
    <li>Phone Number</li> 
    <li>Profession</li> 
    <li>Accounts</li> 
    <ul> 
     <li>Account Name</li> 
    </ul> 
</ul> 

,它是由显示浏览器为

  • 地址
    • 地址1
    • 地址2
  • 员工姓名
  • 电话号码
  • 职业
  • 账户
    • 帐户名称
+0

Navatchev,非常感谢:) ...您的XSLT代码工作很好,但它显示如下结果:

  • 地址
    • 地址1
    • 地址2
。在第一个列表项停止后,什么都不显示。我也有我的计划有序列表作为
  • 地址
    • 地址1
    • 地址2
...能否请你帮我显示它新的这种格式,也是所有列表项不只是第一个。 – manishekhawat 2012-01-06 16:51:50

+0

对不起,我的问题是,为什么你的代码不适合我,我正在更新XML,因为我们没有想过通过一个场景,然后我们可以再次尝试获得所需的结果。希望这次也能帮助我。 :) – manishekhawat 2012-01-06 16:59:58

+0

@manishekhawat:该代码已经过测试,使用多个XSLT 1.0处理器(MSXML3/4,.NET XslCompledTransform,Saxon 6.5.4和AltovaXML(XML-SPY))正常工作并生成相同的* complete *结果。得到的结果不完整,要么是更改了XML文档,要么是XSLT代码,或者两者都使用了,或者使用的是错误的,不兼容的XSLT处理器。 – 2012-01-06 17:07:38