我正在使用样式表将alphabetized XML book索引转换为XHTML。作为这个过程的一部分,我必须:
以下是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很新,我强烈怀疑我正在考虑整个问题,但是我不知道从哪里开始。
答案 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>