开发者

XSLT contains two periods

I have an HTML document that used an unordered list to display the navigation. When it is output as XML it no longer uses the list, but instead assigns each link a <Description>. The way that the description works is that the main links are assigned numbers like 100, 200, 300, 400, and so on. Subnavigation links from those are assigned as follows: 200.100, 200.200, 200.300, and so on.

The XML looks like the following:

<Items>
  <PgIndexElementItem>
      <Description>100</Description&g开发者_如何转开发t;
      <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>

If you look at the last PgIndexElementItem, there are three sets of numbers.

I'm trying to recreate the unordered list using XSLT. This is what I have been doing so far:

<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>

My question would be, is there a way to specify a contains(Description that targets descriptions with two periods, like the last PgIndexElementItem above?

I hope I explained this well enough. I don't know how to make it less confusing. Thanks in advance!

EDIT

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


You can use

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

to test whether an element has a Description child with two or more periods.

However, I would instead change your XSLT to:

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

Updated this template:

<!-- 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>

This will avoid unnecessary code duplication, and unwanted empty <ul> elements.

I've made some assumptions about how the Description children are to be interpreted... e.g. "200.100" should appear in a sublist under "200" but not under "100".


Use:

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

This works the same for any number $n (while the "substring-after" technique is simply unusable in the general case):

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


I looks like you're dealing with nested PgIndexElementItem elements - if they nest in multiple layers you should consider refactoring your XSL to use a recursive template (assuming the HTML output for each level is predictable).

As it is written, your for-each loop selects all the PgIndexElementItem descendants of the current element, then does that again when it hits the inner for-each loop. Possibly not what you intended.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜