XSLT族树

时间:2016-05-30 13:08:48

标签: xslt

目前,我正在努力让我的XSLT正常运行。我试图将XML转换为无序列表,其子项位于子无序列表中。问题是如果一个人没有孩子,XSL会创建空的列表元素。

XML:

    <?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="Trees.xsl"?>
<Tree>
    <Person ID="1"  FirstName="test" LastName="" ChildOf="0" />
    <Person ID="2" FirstName="test2" LastName="" ChildOf="1" />
    <Person ID="3" FirstName="test3" LastName="" ChildOf="1" />
    <Person ID="4" FirstName="test4" LastName="" ChildOf="1" />
    <Person ID="6" FirstName="test6" LastName="" ChildOf="3" />
    <Person ID="5" FirstName="test5" LastName="" ChildOf="0" />
</Tree>

XSL:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">


    <xsl:template match="Person">


           <ul><li><xsl:value-of select="@FirstName" /></li>
           <li><xsl:apply-templates select="../Person[@ChildOf=current()/@ID]" />
           </li></ul>

    </xsl:template>

</xsl:stylesheet>

我已经尝试使用if检查FirstName是否为空,但它不起作用。错误在哪里。

2 个答案:

答案 0 :(得分:3)

我建议你这样试试:

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

<xsl:key name="children" match="Person" use="@ChildOf" />

<xsl:template match="/Tree">
    <ul>
        <xsl:apply-templates select="Person[@ChildOf=0]"/>
    </ul>
</xsl:template>

<xsl:template match="Person">
    <li>
        <xsl:value-of select="@FirstName" />
    </li>
    <xsl:variable name="children" select="key('children', @ID)" />
    <xsl:if test="$children">
        <ul>
            <xsl:apply-templates select="$children" />
        </ul>
    </xsl:if>
</xsl:template>   

</xsl:stylesheet>

答案 1 :(得分:1)

更简单,更短,更有效的解决方案(无变量,无条件指令):

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:key name="kPersById" match="Person" use="@ID"/>
 <xsl:key name="kChildrenOf" match="Person" use="@ChildOf"/>

  <xsl:template match="/*">
    <xsl:apply-templates select="Person[not(key('kPersById', @ChildOf))][1]" mode="start"/>
  </xsl:template>
  <xsl:template match="Person" mode="start">
    <ul>
      <li><xsl:value-of select="@FirstName" /></li>
      <xsl:apply-templates select="key('kChildrenOf', @ID)[1]" mode="start"/>
      <xsl:apply-templates select="key('kChildrenOf', @ChildOf)[position() > 1]"/>
    </ul>
  </xsl:template>

  <xsl:template match="Person">
      <li><xsl:value-of select="@FirstName" /></li>  
      <xsl:apply-templates select="key('kChildrenOf', @ID)[1]" mode="start"/>
  </xsl:template>
</xsl:stylesheet>

在提供的XML文档上应用此转换时

<Tree>
    <Person ID="1"  FirstName="test" LastName="" ChildOf="0" />
    <Person ID="2" FirstName="test2" LastName="" ChildOf="1" />
    <Person ID="3" FirstName="test3" LastName="" ChildOf="1" />
    <Person ID="4" FirstName="test4" LastName="" ChildOf="1" />
    <Person ID="6" FirstName="test6" LastName="" ChildOf="3" />
    <Person ID="5" FirstName="test5" LastName="" ChildOf="0" />
</Tree>

产生了想要的正确结果:

<ul>
   <li>test</li>
   <ul>
      <li>test2</li>
      <li>test3</li>
      <ul>
         <li>test6</li>
      </ul>
      <li>test4</li>
   </ul>
   <li>test5</li>
</ul>

请注意

此解决方案不依赖于具有Person的顶级ChildOf="0"元素。实际上,对于顶级元素,可以完全省略此属性,或者不同的顶部元素可以具有具有不同值的ChildOf属性 - 例如,当这些属性已被&#34; cut&#34;来自另一个更大的等级。