XSLT包含两个句点

时间:2010-12-16 19:33:01

标签: xslt xpath contains

我有一个HTML文档,它使用无序列表来显示导航。当它以XML格式输出时,它不再使用列表,而是为每个链接分配<Description>。描述的工作方式是为主链接分配数字,如100,200,300,400等。这些的子导航链接分配如下:200.100,200.200,200.300等。

XML如下所示:

<Items>
  <PgIndexElementItem>
      <Description>100</Description>
      <Title>This is the Title</Title>
  </PgIndexElementItem>
  <PgIndexElementItem>
      <Description>200</Description>
      <Title>This is the Title</Title>
  </PgIndexElementItem>
  <PgIndexElementItem>
      <Description>200.100</Description>
      <Title>This is the Title</Title>
  </PgIndexElementItem>
  <PgIndexElementItem>
      <Description>200.100.100</Description>
      <Title>This is the Title</Title>
  </PgIndexElementItem>
</Items>

如果查看最后一个PgIndexElementItem,则有三组数字。

我正在尝试使用XSLT重新创建无序列表。这就是我到目前为止所做的事情:

<ul>
    <xsl:for-each select="//PgIndexElementItem">
        <xsl:if test="not(contains(Description, '.'))">
            <li><a href="{ResolvedURL/ServerRelative}"><xsl:value-of select="Title"/></a>
                <ul>
                    <xsl:for-each select="//PgIndexElementItem">
                        <xsl:if test="contains(Description, '.')">
                            <li><a href="{ResolvedURL/ServerRelative}"><xsl:value-of select="Title"/></a></li>
                        </xsl:if>
                    </xsl:for-each>
                </ul>
            </li>
        </xsl:if>
    </xsl:for-each>
</ul>

我的问题是,有没有办法指定一个contains(Description定位具有两个句点的描述,例如上面的最后一个PgIndexElementItem?

我希望我解释得这么好。我不知道如何减少它的混乱。提前谢谢!

修改

o Graduate Program
   * How to Apply
   * Masters Program
        o M.A. Handbook
        o FAQs
        o Alumni
        o Masters Theses
        o Sample Thesis Proposals
   * M.A. Handbook
   * FAQs
   * Alumni
   * Masters Theses
   * Sample Thesis Proposals

3 个答案:

答案 0 :(得分:2)

您可以使用

<xsl:if test="contains(substring-after(Description, '.'), '.')">
    ...

测试元素是否具有包含两个或更多句点的Description子项。

但是,我会将您的XSLT更改为:

  <!-- this part replaces your <ul> code above -->
  <ul>
     <xsl:apply-templates
         select="//PgIndexElementItem[not(contains(Description, '.'))]" />
  </ul>      

更新了此模板:

<!-- add this new template -->
<xsl:template match="PgIndexElementItem">
   <li>
      <a href="{ResolvedURL/ServerRelative}"><xsl:value-of select="Title"/></a>
      <xsl:variable name="prefix" select="concat(Description, '.')"/>
      <xsl:variable name="childOptions"
         select="../PgIndexElementItem[starts-with(Description, $prefix)
           and not(contains(substring-after(Description, $prefix), '.'))]"/>
      <xsl:if test="$childOptions">
         <ul>
            <xsl:apply-templates select="$childOptions" />
         </ul>
      </xsl:if>
   </li>
</xsl:template>

这样可以避免不必要的代码重复,以及不需要的空<ul>元素。

我已经对如何解释描述儿童做了一些假设......例如“200.100”应出现在“200”下的子列表中,但不应出现在“100”下。

答案 1 :(得分:2)

使用

string-length(Description) - string-length(translate(Description, '.',''))  = 2

对于任何数字$n 都是一样的(虽然“substring-after”技术在一般情况下根本无法使用):

string-length(Description) - string-length(translate(Description, '.',''))  = $n

答案 2 :(得分:0)

我看起来你正在处理嵌套的PgIndexElementItem元素 - 如果它们嵌套在多个层中,你应该考虑重构你的XSL以使用递归模板(假设每个级别的HTML输出是可预测的)。

在编写时,你的for-each循环选择当前元素的所有PgIndexElementItem后代,然后当它到达内部for-each循环时再次执行 。可能不是你想要的。