用XSL制作一本书的索引

时间:2013-12-18 00:14:04

标签: xml xslt

我有一个具有以下结构的XML,我想在其中编写一些特定单词的索引:

<book>
<chapter title="This is first chapter">
        <section title="This is the first section">
        <paragraph title="This is the first paragraph">This is the paragraph content, where this <index>word</index> should be in the index</paragraph>
        </section>
</chapter>
<chapter title="This is second chapter">
        <section title="This is the first section">
        <paragraph title="This is the first paragraph">This is the paragraph content</paragraph>
        </section>
</chapter>
</book>

所以,我想列出所有<index>个元素,这就是我尝试的内容:

<xsl:template match="/">
        <xsl:apply-templates select="book/chapter" />
</xsl:template>


    <xsl:template match="chapter">
            <html>
            <head>
                <title>Index</title>
            </head>
            <body>
      <h1>
            Index
        </h1>
        <xsl:apply-templates  />
            </body>
        </html>
    </xsl:template>


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

因此,所有单词都正确打印,但问题是XML中的所有文本都被打印出来(所有文本节点都是相互打印的)。我只想要索引元素,没有别的。

4 个答案:

答案 0 :(得分:3)

您获取所有文本节点的原因是XSLTs built-in rules

尝试添加模板:

<xsl:template match="text()"/>

答案 1 :(得分:2)

实际上,我认为您需要 less 模板,而不是更多:

<xsl:template match="/book">
<html>
<head>
    <title>Index</title>
</head>
<body>
    <h1>Index</h1>
    <xsl:apply-templates select="descendant::index"/>
</body>
</html>
</xsl:template>

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

或者,如果您愿意:

<xsl:template match="/book">
<html>
<head>
    <title>Index</title>
</head>
<body>
    <h1>Index</h1>
    <xsl:apply-templates select="descendant::index" >
        <xsl:sort select="." data-type="text" order="ascending"/>
    </xsl:apply-templates >
</body>
</html>
</xsl:template>

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

答案 2 :(得分:1)

以下是生成真实索引的粗略尝试 - 即分组,排序并包括找到每个条目的位置列表(以#.paragraph#章节的形式)。

这里有一些假设:

  • 您的处理器支持EXSLT set:distinct()函数(从而避免了对Muenchian分组的需要);
  • 所有索引条目都出现在段落元素中(尽管不一定是直接子元素);每个索引条目在同一段落中只出现一次;
  • 所有段落都是一个部分的孩子;所有部分都是一章的孩子。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:set="http://exslt.org/sets"
extension-element-prefixes = "set">
<xsl:output method="html" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:key name="index" match="index" use="." />

<xsl:template match="/">
<html>
<head>
    <title>Index</title>
</head>
<body>
    <h1>Index</h1>

    <xsl:for-each select="set:distinct(book/chapter/section/paragraph//index)">
    <xsl:sort select="." data-type="text" order="ascending"/>
    <p>
        <xsl:value-of select="."/>
        <xsl:text> - </xsl:text>
        <xsl:for-each select="key('index', .)">
            <xsl:value-of select="count(ancestor::chapter/preceding-sibling::chapter) + 1"/>
            <xsl:text>.</xsl:text>
            <xsl:value-of select="count(ancestor::paragraph/preceding-sibling::paragraph) + count(ancestor::section/preceding-sibling::section/paragraph) + 1"/>
            <xsl:if test="position() != last()">
                <xsl:text>, </xsl:text>
            </xsl:if>   
        </xsl:for-each>
    </p>
    </xsl:for-each>  
</body>
</html>
</xsl:template>
</xsl:stylesheet>

答案 3 :(得分:0)

使用适当的apply-template选择,我将章节标题添加到索引标题中。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <xsl:apply-templates select="book/chapter" />
  </xsl:template>
  <xsl:template match="chapter">
    <html>
      <head>
        <title>Index</title>
      </head>
      <body>
        <h1><xsl:value-of select="@title"/> Index</h1>
        <xsl:apply-templates select=".//index"  />
      </body>
    </html>
  </xsl:template>
  <xsl:template match="text()">
    <p> 
      <xsl:value-of select="."/>
    </p>
  </xsl:template>
</xsl:stylesheet>