Xslt 将XML邻接列表模型规范化为HTML树列表

Xslt 将XML邻接列表模型规范化为HTML树列表,xslt,Xslt,我见过转换“邻接模型”XML的例子,但没有一个能很好地用于ul/li项目符号列表。有人能给我一个提示吗?如果该解决方案能够支持典型的邻接模型需求并处理多层嵌套/递归,那就太好了 如果XML为: <?xml version="1.0" encoding="ISO-8859-1"?> <root> <row Id="2" Name="data" /> <row Id="3" Name="people" /> <row Id="4" N

我见过转换“邻接模型”XML的例子,但没有一个能很好地用于ul/li项目符号列表。有人能给我一个提示吗?如果该解决方案能够支持典型的邻接模型需求并处理多层嵌套/递归,那就太好了

如果XML为:

<?xml version="1.0" encoding="ISO-8859-1"?>
<root>
  <row Id="2" Name="data" />
  <row Id="3" Name="people" />
  <row Id="4" Name="person" ParentId="3" />
  <row Id="6" Name="folder" ParentId="2" />
  <row Id="7" Name="thing" ParentId="3" />
  <row Id="8" Name="web" />
  <row Id="9" Name="link" ParentId="8" />
</root>

我用的是:

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

<xsl:template match="/">
<ul id="someid" class="menu">
  <xsl:apply-templates select="root/row[not(@ParentId)]"/>
</ul>
</xsl:template>

<xsl:template match="row">
<ul>
    <li>
    <xsl:variable name="ID" select="@Id"/>
      <xsl:attribute name="rel">
      <xsl:value-of select="@Id"/>
      </xsl:attribute>
      <xsl:value-of select="@Name"/>
      <xsl:apply-templates select="//row[@ParentId=$ID]"/>
   </li>
</ul>
</xsl:template>

</xsl:stylesheet>   

然后我得到:

<ul id="someid" class="menu">
  <ul>
    <li rel="2">
      data<ul>
        <li rel="6">folder</li>
      </ul>
    </li>
  </ul>
  <ul>
    <li rel="3">
      people
      <ul>
        <li rel="4">person</li>
      </ul><ul>
        <li rel="7">thing</li>
      </ul>
    </li>
  </ul>
  <ul>
    <li rel="8">
      web<ul>
        <li rel="9">link</li>
      </ul>
    </li>
  </ul>
</ul>
    • 数据
        文件夹
          • 事情
        • 网络
            链接
请注意,“人”和“物”之间额外的闭合/打开ul标签-不应存在。我可以理解为什么会发生这种情况,但不知道如何更改代码来修复它


谢谢。

你真的很接近了,你只需要把你的
和你的
移到你的
    声明之外

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    
      <xsl:template match="/">
        <ul id="someid" class="menu">
          <xsl:apply-templates select="root/row[not(@ParentId)]"/>
        </ul>
      </xsl:template>
    
      <xsl:template match="row">
        <xsl:variable name="ID" select="@Id"/>
          <li>
            <xsl:attribute name="rel">
              <xsl:value-of select="@Id"/>
            </xsl:attribute>
            <xsl:value-of select="@Name"/>
          </li>
        <xsl:if test="//row[@ParentId=$ID]">
          <ul>
            <xsl:apply-templates select="//row[@ParentId=$ID]"/>
          </ul>
        </xsl:if>
      </xsl:template>
    
    </xsl:stylesheet>
    
    
    
    这就产生了我认为你正在寻找的结果

    <ul id="someid" class="menu">
      <li rel="2">data</li>
      <ul>
        <li rel="6">folder</li>
      </ul>
      <li rel="3">people</li>
      <ul>
        <li rel="4">person</li>
        <li rel="7">thing</li>
      </ul>
      <li rel="8">web</li>
      <ul>
        <li rel="9">link</li>
      </ul>
    </ul>
    
      数据
        文件夹
      • 人 事情
    • 网络
      • 链接

    这还将删除顶层
  • 之前的额外
      ,以反映OP新请求

      这是一个递归模板,它按照W3C规范中的定义生成一个符合HTML的嵌套列表

      <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      
          <xsl:output indent="yes"/>
      
          <xsl:template match="/root">
              <ul id="someid" class="menu">
                  <xsl:apply-templates select="row[not(@ParentId)]"/>
              </ul>
          </xsl:template>
      
          <xsl:template match="row">
              <li rel="{@Id}">
                  <xsl:value-of select="@Name"/>
                  <xsl:if test="count(../row[@ParentId=current()/@Id])>0">
                      <ul>
                          <xsl:apply-templates select="../row[@ParentId=current()/@Id]"/>
                      </ul>
                  </xsl:if>
              </li>
          </xsl:template>
      
      </xsl:stylesheet>
      
      
      
    • 应用于此输入:

      <root>
        <row Id="1" Name="data" />
        <row Id="2" Name="data" />
        <row Id="3" Name="people" />
        <row Id="4" Name="person" ParentId="3" />
        <row Id="6" Name="folder" ParentId="2" />
        <row Id="7" Name="thing" ParentId="3" />
        <row Id="8" Name="web" />
        <row Id="9" Name="link" ParentId="8" />
          <row Id="10" Name="anotherone" ParentId="9" />
          <row Id="11" Name="anotherone" ParentId="9" />
          <row Id="12" Name="anotherone" ParentId="9" />
          <row Id="13" Name="anotherone" ParentId="3" />
      </root>
      
      
      
      产生:

      <ul id="someid" class="menu">
         <li rel="1">data</li>
         <li rel="2">data<ul>
               <li rel="6">folder</li>
            </ul>
         </li>
         <li rel="3">people<ul>
               <li rel="4">person</li>
               <li rel="7">thing</li>
               <li rel="13">anotherone</li>
            </ul>
         </li>
         <li rel="8">web<ul>
               <li rel="9">link<ul>
                     <li rel="10">anotherone</li>
                     <li rel="11">anotherone</li>
                     <li rel="12">anotherone</li>
                  </ul>
               </li>
            </ul>
         </li>
      </ul>
      
        数据 数据 文件夹
    • 人们
        人 事情
      • 另一个
    • web
        链接
      • 另一个
      • 另一个
      • 另一个

如果您在如何创建列表方面遇到困难,请尝试使用。

这是上面的列表,但在人和物之间没有额外的/ul标签。我不认为这个列表在HTML中是有效的,只要这些标签存在?i、 e.人和物项是兄弟项,它们都是“人”项的子项。这对浏览器没有多大区别,这是正确的。不过,您会在我的答案中找到创建嵌套列表的正确方法。:)谢谢。将尽快验证并标记为答案。欢迎您。我用MSXSL 4.5.0测试了XSLT1.0,效果很好。非常感谢。此输出HTML看起来确实不像正确的HTML,即使浏览器仍将显示列表。@empo-我明白你的意思-我试图尽可能少地偏离OP提供的输出,但内部
    可以是
  • 的子项,这是更好的形式。工作起来很有魅力,可以处理递归(这是我应该提到的!!)+1表示初始递归性(OP没有提到)。关于错误的HTML,你离正确的代码不远了。好吧-大家能不能别再表现得太棒了,我开始觉得自己很愚蠢:)