html - 在 XSLT 中生成指向按字母顺序排列的文档部分的快捷链接

标签 html xml xslt

我正在制作一个样式表,以将按字母顺序排列的 XML 书籍索引转换为 XHTML。作为此过程的一部分,我必须:

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

这是 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 的新手,我强烈怀疑我是在倒着思考这整个问题,但我不知道从哪里开始。

最佳答案

怎么样....

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

关于html - 在 XSLT 中生成指向按字母顺序排列的文档部分的快捷链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31999477/

相关文章:

html - BlueGriffon 帮助 - 根据窗口大小重新排列的连续图像

xml - 从 URL 读取 XML 并绑定(bind)到 WP7 中的列表框

javascript - 如何使用 Greasemonkey 脚本通过 XSLT 转换 XML 文件?

html - 使用 XSLT 重现 XML 转换中的所有属性

xml - 修改部分XML元素名称并替换为增量编号

html - 无法使用 Internet Explorer 拉伸(stretch)图像和覆盖纵横比

css - 如何添加两个单独的固定侧边栏,如果它们的内容超出屏幕高度则滚动?

html - 如何将背景样式覆盖回原始样式?

java - 使用 rss 版本 ="2"解析提要

xml - 使用 xslt 将节点从 XML 插入到另一个 XML 文件