xsl在“N”子元素之后展开和折叠

时间:2014-12-05 22:29:56

标签: javascript jquery xml xslt

我的XML可以包含可变数量的子元素 当子元素数超过“N”时,我们需要一种方法来添加展开/折叠功能 示例XML

<?xml version="1.0"?>
<TestXML>
    <N>Test</N>
    <NTList>
        <NT>
            <NT1>NT1 Test 1</NT1>
            <NT2>NT2 Test 1</NT2>
        </NT>
        <NT>
            <NT1>NT1 Test 2</NT1>
            <NT2>NT2 Test 2</NT2>
        </NT>
        <NT>
            <NT1>NT1 Test 3</NT1>
            <NT2>NT2 Test 3</NT2>
        </NT>
    </NTList>
</TestXML>

所以在这个例子中,如果“NTList”中有超过2个“NT”,我们想添加展开/折叠。

我认为this已接近但我无法确定何时在达到“N”记录后添加展开/折叠。

对于HTML输出,这是非常基本的东西:

N : Test
NTLIST
    NT (1)
        NT1 : NT1 Test 1
        NT2 : NT2 Test 1
    NT (2)
        NT1 : NT1 Test 2
        NT2 : NT2 Test 2
    NT (+More) <- where this is the link to click to expand the 3rd NT.

1 个答案:

答案 0 :(得分:0)

因为你有jQuery作为标签我认为以下解决方案可能适合你。您可以在position()循环中使用xsl:for-each确定第N条记录。例如N = 3:

XSLT:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     version="1.0">
<xsl:output method="html" doctype-public="XSLT-compat" 
     omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
  <xsl:template match="TestXML">
    <ul>
      <li>N : Test<br/>NTLIST
        <xsl:for-each select="NTList/NT">       
          <ul>
            <li>
              <xsl:if test="position() >=3">
                <xsl:attribute name="class" select="'toggle'"/>
              </xsl:if>
              <xsl:value-of select="
               if(position() &lt; 3)
               then concat(local-name(),  ' (', position(),')')
               else concat(local-name(),  ' (+More)')"/>
                <ul>
                  <xsl:if test="position() >=3">
                    <xsl:attribute name="class" select="'hidden'"/>
                  </xsl:if>
                  <xsl:for-each select="*">
                    <li>
                      <xsl:value-of select="."/>
                    </li>
                  </xsl:for-each>
                </ul>
             </li>
          </ul>
        </xsl:for-each>
      </li>
    </ul>
  </xsl:template>
</xsl:transform>

当应用于您的输入时,XML产生输出(相关部分):

<ul>
   <li>N : Test<br/>NTLIST
      <ul>
         <li>NT (1)
            <ul>
               <li>NT1 Test 1</li>
               <li>NT2 Test 1</li>
            </ul>
         </li>
      </ul>
      <ul>
         <li>NT (2)
            <ul>
               <li>NT1 Test 2</li>
               <li>NT2 Test 2</li>
            </ul>
         </li>
      </ul>
      <ul>
         <li class="toggle">NT (+More)
            <ul class="hidden">
               <li>NT1 Test 3</li>
               <li>NT2 Test 3</li>
            </ul>
         </li>
      </ul>
   </li>
</ul>

以下CSS隐藏了具有类hidden的列表,并从列表元素中删除了项目符号:

ul
{
  list-style-type:none;
}
.hidden
{
  display:none;)
}

关注jQuery:

$(".toggle").on("click", function () {
  $(this).find("ul").slideToggle();
});

将切换隐藏列表。只为结果添加了Fiddle

供参考:position()http://api.jquery.com/slidetoggle/

更新如评论中所述,由于在if属性中使用select并使用{{select,因此建议的方法不适用于OP设置(Visual Studio) 1}}在xsl:attribute中。以下XSLT使用xsl:when语句生成相同的输出。我无法测试它是否可以在Visual Studio中运行,但如果没有,您只需添加带有新错误的注释即可。

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="html" doctype-public="XSLT-compat"
omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
  <xsl:template match="TestXML">
    <ul>
        <li>
            N : Test<br/>
            NTLIST
            <xsl:for-each select="NTList/NT">
                <ul>
                    <li>
                      <xsl:if test="position() >=3">
                        <xsl:attribute name="class">toggle</xsl:attribute>
                      </xsl:if>
                      <xsl:choose>
                        <xsl:when test="position() &lt; 3">
                          <xsl:value-of 
                               select="concat(local-name(), ' (', position(),')')"/>
                        </xsl:when>
                        <xsl:otherwise>
                          <xsl:value-of 
                                 select="concat(local-name(), ' (+More)')"/>
                        </xsl:otherwise>
                      </xsl:choose>
                      <ul>
                        <xsl:if test="position() >=3">
                          <xsl:attribute name="class">hidden</xsl:attribute>     
                        </xsl:if>
                        <xsl:for-each select="*">
                          <li>
                            <xsl:value-of select="."/>
                          </li>
                        </xsl:for-each>
                      </ul>
                    </li>
                </ul>
            </xsl:for-each>
        </li>
    </ul>
  </xsl:template>
</xsl:transform>

更新:正如评论中所述,我忽略了更改select中的两个xsl:attribute语句。通过调整到例如它来修复它<xsl:attribute name="class">hidden</xsl:attribute>。为避免在空格或换行符时出现潜在问题,可以通过添加<xsl:text>作为包装来更改此问题:

<xsl:attribute name="class">
  <xsl:text>hidden</xsl:text>
</xsl:attribute>