生成XSLT中按字母顺序排列的文档部分的快捷方式链接

时间:2015-08-13 22:29:54

标签: html xml xslt

我正在使用样式表将alphabetized XML book索引转换为XHTML。作为这个过程的一部分,我必须:

  1. 将锚标记添加到每个字母的第一个条目中。
  2. 在顶部用字母表中的每个字母创建一行,每行都有一个指向正确锚点的链接。
  3. 如果没有相应的锚点,顶部的链接会有所不同。 (例如,链接可能有一个额外的title属性。)
  4. 以下是XML

    的简化示例
    <?xml version="1.0" encoding="UTF-8"?>
    <index>
        <heading>I'm an index</heading>
        <primaryEntry>Andy</primaryEntry>
        <primaryEntry>Bob</primaryEntry>
        <primaryEntry>Jimmy</primaryEntry>
        <primaryEntry>Johnny</primaryEntry>
        <primaryEntry>Josephine</primaryEntry>
        <primaryEntry>Zed</primaryEntry>
    </index>
    

    这是预期的输出

    <?xml version="1.0" encoding="UTF-8"?><html><head>Index</head><body>
        <h1>I'm an index</h1>
        <p><a href="#A">A</a>  <a href="#B">B</a>  <a href="#C" title="I go nowhere">C</a>  <a href="#D" title="I go nowhere">D</a>  ... <a href="#J">J</a> ... <a href="#Y" title="I go nowhere">Y</a>  <a href="#Z">Z</a>  </p>
        <a name="A"></a><p>Andy</p>
        <a name="B"></a><p>Bob</p>
        <a name="J"></a><p>Jimmy</p>
        <p>Johnny</p>
        <p>Josephine</p>
        <a name="Z"></a><p>Zed</p>
    </body></html>
    

    这是我的尝试,不会运行。 (见评论。)

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:atict="http://www.arbortext.com/namespace/atict" 
        exclude-result-prefixes="atict" version="2.0">
        <xsl:output method="xhtml" indent="no"/>
    
        <xsl:template match="index">
            <xsl:element name="html">
                <xsl:element name="head">Index</xsl:element>
                <xsl:element name="body">
                    <xsl:apply-templates/>
                </xsl:element>
            </xsl:element>
        </xsl:template>
    
        <xsl:template match="heading">
            <xsl:element name="h1">
                <xsl:apply-templates/>
            </xsl:element>
            <xsl:element name="p">
                <xsl:variable name="alphabet" select="tokenize('A B C D E F G H I J K L M N O P Q R S T U V W X Y Z', ' ')"/>
                <xsl:for-each select="$alphabet">
                    <xsl:sort select="."/>
                    <xsl:element name="a">
                        <xsl:variable name="letter" select="."/>
                        <xsl:if test="//primaryEntry[starts-with(., $letter)]"> <!--Error: We can no longer see the document from this context -->
                            <xsl:attribute name="title" select="'I go nowhere'"></xsl:attribute>
                        </xsl:if>
                        <xsl:value-of select="."/>
                    </xsl:element>
                    <xsl:text>  </xsl:text>
                </xsl:for-each>
            </xsl:element>
        </xsl:template>
    
        <xsl:template match="primaryEntry">
            <xsl:variable name="first_letter" select="upper-case(substring(normalize-space(.), 1, 1))" />
            <xsl:if test="not(preceding-sibling::primaryEntry[starts-with(upper-case(normalize-space(.)), $first_letter)])">
                <xsl:element name="a">
                    <xsl:attribute name="name" select="$first_letter" />
                </xsl:element>
            </xsl:if>
            <xsl:element name="p">
                <xsl:apply-templates/>
            </xsl:element>
        </xsl:template>
    
    </xsl:stylesheet>
    

    这种方法适用于要求1和2,但我不确定使用这种方法是否可以实现3。一旦我在for-each中评估一个节点集,就没有“弹出”来检查XML文档中是否有相应的元素。我对XSLT很新,我强烈怀疑我正在考虑整个问题,但是我不知道从哪里开始。

1 个答案:

答案 0 :(得分:0)

怎么样......

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

<xsl:output method="html" version="5.0"  doctype-system="about:legacy-compat"
            encoding="utf-8" indent="yes" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />

<xsl:key name="letter" match="primaryEntry" use="substring(.,1,1)" />

<xsl:template match="/">
 <xsl:variable name="main-doc" select="." />
 <html>
  <head>
   <meta charset="utf-8" />
   <title>Sample Corporation #1</title>
  </head>
  <body>
    <h1>I'm an index</h1>
    <p>
     <xsl:for-each select="'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'">
     <a href="#{.}">
        <xsl:if test="not( key('letter',.,$main-doc))">
         <xsl:attribute name="title">I go nowhere</xsl:attribute>
        </xsl:if>
       <xsl:value-of select="." />
     </a>
     </xsl:for-each>
    </p> 
    <xsl:for-each-group select="index/primaryEntry" group-by="substring(.,1,1)">
      <a name="{current-grouping-key()}"></a>
      <xsl:apply-templates select="current-group()" />
    </xsl:for-each-group>
  </body>
 </html>
</xsl:template>

<xsl:template match="primaryEntry">
  <p><xsl:value-of select="." /></p>
</xsl:template>

</xsl:stylesheet>

......产生......(使用Saxonica的Saxon-HE 9.5.1.1N)

<!DOCTYPE html SYSTEM "about:legacy-compat">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <meta charset="utf-8">
        <title>Sample Corporation #1</title>
    </head>
    <body>
        <h1>I'm an index</h1>
        <p>
            <a href="#A">A</a>
            <a href="#B">B</a>
            <a href="#C" title="I go nowhere">C</a>
            <a href="#D" title="I go nowhere">D</a>
            <a href="#E" title="I go nowhere">E</a>
            <a href="#F" title="I go nowhere">F</a>
            <a href="#G" title="I go nowhere">G</a>
            <a href="#H" title="I go nowhere">H</a>
            <a href="#I" title="I go nowhere">I</a>
            <a href="#J">J</a>
            <a href="#K" title="I go nowhere">K</a>
            <a href="#L" title="I go nowhere">L</a>
            <a href="#M" title="I go nowhere">M</a>
            <a href="#N" title="I go nowhere">N</a>
            <a href="#O" title="I go nowhere">O</a>
            <a href="#P" title="I go nowhere">P</a>
            <a href="#Q" title="I go nowhere">Q</a>
            <a href="#R" title="I go nowhere">R</a>
            <a href="#S" title="I go nowhere">S</a>
            <a href="#T" title="I go nowhere">T</a>
            <a href="#U" title="I go nowhere">U</a>
            <a href="#V" title="I go nowhere">V</a>
            <a href="#W" title="I go nowhere">W</a>
            <a href="#X" title="I go nowhere">X</a>
            <a href="#Y" title="I go nowhere">Y</a>
            <a href="#Z">Z</a>
        </p>
        </a name="A">
        <p>Andy</p>
        </a name="B">
        <p>Bob</p>
        </a name="J">
        <p>Jimmy</p>
        <p>Johnny</p>
        <p>Josephine</p>
        </a name="Z">
        <p>Zed</p>
    </body>
</html>