克服xsl中未关闭的标签

时间:2011-04-28 19:30:04

标签: xslt sharepoint tags

我正在处理一个下拉菜单,该菜单从Sharepoint列表中提取数据,并使用xsl进行样式设置。 html结构是一个简单的无序列表

<ul><li>parent page</li><ul><li>sub page 1</li><li>sub page2</li></ul></ul>

xsl测试列表中的项目是父页面还是子页面以及子页面编号是什么。父页面有一个数字,因此可以将所需的子页面附加到正确的父页面。

每个项目的基本xsl是:

<xsl:for-each select="//Data/Row">
    <xsl:if test="./@Page_x0020_type = 0">
        <li >
            <a>
                <xsl:attribute name="href">
                    <xsl:value-of
                     select="./@Page_x002f_link_x0020_url"/>
                </xsl:attribute>
                <xsl:value-of select="./@Title0"/>
            </a>
        </li>
    </xsl:if>

我希望xsl等于这个: 如果它是子页面,则在项目前面加上ul标签,如果它是父项下的最后一个子页面,则添加一个结束的ul标签。

我如何解决xsl不会让我添加未封闭的ul标签的事实,因为它(正确地)不知道标签是否会被关闭?

XML

    <Field Type="Text" 
           DisplayName="Page/link url" 
           Required="FALSE" 
           MaxLength="255" 
           Name="Page_x002f_link_x0020_url"/>
    <Field ReadOnly="TRUE" 
           Type="Computed" 
           Name="LinkTitle" 
           DisplayName="Page number"/>
    <Field Type="Text" 
           DisplayName="Title" 
           Required="FALSE" 
           MaxLength="255" 
           Name="Title0"/>  
    <Field Type="Choice" 
           DisplayName="Page type" 
           Required="FALSE" 
           Format="RadioButtons" 
           FillInChoice="FALSE" 
           Name="Page_x0020_type">    
           <CHOICES>  
               <CHOICE>0</CHOICE>  
               <CHOICE>1</CHOICE>  
           </CHOICES>  
           <DefaultFormula>=0</DefaultFormula>  
           <DefaultFormulaValue/>  
    </Field>
    <Field Type="Text" 
           DisplayName="Sub page number" 
           Required="FALSE" 
           MaxLength="2" 
           Name="Sub_x0020_page_x0020_number"/>
    <Field Type="Text" 
           DisplayName="Parent page number" 
           Required="FALSE" 
           MaxLength="1" 
           Name="Parent_x0020_page_x0020_number">
           <Default>0</Default>
    </Field>
</Schema>
<Data ItemCount="1">
    <Row Page_x002f_link_x0020_url="" 
         LinkTitle="" 
         Title0="" 
         Page_x0020_type="" 
         Sub_x0020_page_x0020_number="" 
         Parent_x0020_page_x0020_number="" 
         ul="" 
         _x003c_li_x003e__x003c_a_x003e_="" 
         _x003c__x002f_a_x003e__x003c__x0="" 
         _x003c_ul_x003e__x003c_li_x003e_="" 
         _x003c__x002f_a_x003e__x003c__x00="" 
         _x003c__x002f_a_x003e__x003c__x01=""/>

更新

页面类型:
  • <li>parent1</li>
  • 子页面1 - 需要以<ul>...<li>sub page 1</li>
  • 开头
  • 中间子页面 - (编号设置排序顺序-html与父页面相同)<li>sub page #</li>
  • 群组中的最后一个子页面 - 需要以</ul>
  • 结尾

2 个答案:

答案 0 :(得分:4)

  

我希望xsl等同于:如果它是一个子页面,则在项目前面加上ul标签,如果它是父项下的最后一个子页面,则添加一个结束ul标签。

你在想错误的方法。 XSLT不写标签,它写一个节点树。您不能将半个节点写入结果树。

在XSLT 2.0中你可以使用xsl:for-each-group和group-starting-with属性做你想做的事情 - 我不能具体,因为你没有明确指出问题,但它是可能是这样的:

<xsl:template match="parent">
  <xsl:for-each-group select="*" group-starting-with="li[....]">
    <ul>
      <xsl:copy-of select="current-group()"/>
    </ul>
  </xsl:for-each-group>
</xsl:template>

如果你坚持使用XSLT 1.0,那将会更加困难:我将使用一种名为“兄弟递归”的技术,在这种技术中,你将模板应用于第一个孩子,然后将模板应用于下一个兄弟,等等。父级的模板规则执行此操作:

<xsl:template match="parent">
  <xsl:apply-templates select="*[1]"/>
</xsl:template>

作为组中第一个兄弟的模板规则执行此操作:

<xsl:template match="parent/*[ (: where this is the first in a group :) ]">
  <group>
    <xsl:copy-of select="."/>
    <xsl:apply-templates select="following-sibling::*[1]"/>
  </group>
  <xsl:apply-templates select="following-sibling::*[(* start of next group *)][1]"/>
</xsl:template>

以及其他兄弟姐妹的模板规则:

<xsl:template match="parent/*">
  <xsl:copy-of select="."/>
  <xsl:apply-templates select="following-sibling::*[1]"/>
</xsl:template>

即使对于有经验的XSLT开发人员来说,细节也很棘手。

答案 1 :(得分:0)

我错过了什么。由于XSL是一个XML文档,可用于将另一个XML(XHTML,SOAP等)文档转换为另一种格式,通常是某种XML。如果将数据文档(字符串等)提供给XSL,它将根据您设置的模式进行转换,该模式必须是有效的XML。

现在,为什么这是您实例中的问题。您是否只构建了结构的一部分,然后将其添加到另一个部分,直到您拥有整个结构?如果是这样,我会将所有位都拉成一段数据(文件,字符串等)并对其进行转换。或者,将占位符保留在最高级别,正确​​结束标记,并以这种方式添加子位。

看着你的问题,我看到你想要一个有效的和一个无效的,这让我相信你正试图零碎一个解决方案。不幸的是,我知道无法告诉XSL“嘿,这是无效的XML,但不要冒汗”。