我想不出一种简单而优雅的方法,可以使用XPath或简单的XSLT模板在XML文档中查找“previous”和“next”元素。这是一个示例XML文档(在真实文档中,@id
不会如此简单地订购)
<manual>
<section id="1">
<section id="2">
<section id="3"/>
<section id="4"/>
<section id="5"/>
</section>
<section id="6">
<section id="7"/>
<section id="8"/>
<section id="9"/>
</section>
</section>
<section id="10"/>
<section id="11">
<section id="12"/>
</section>
</manual>
以下是文档顺序中前/后的含义
+------------------+------------------+--------------+
| Selected section | Previous section | Next section |
+------------------+------------------+--------------+
| 1 | none | 2 |
| 2 | 1 | 3 |
| 3 | 2 | 4 |
| 4 | 3 | 5 |
| 5 | 4 | 6 |
| ... | ... | ... |
| 10 | 9 | 11 |
| 11 | 10 | 12 |
| 12 | 11 | none |
+------------------+------------------+--------------+
preceding::
轴的问题是排除了祖先,即section[id=2]
不是section[id=3]
的前一个节点。
同样,following::
轴排除了后代,即section[id=3]
不是section[id=2]
的后续节点。
那我怎么能产生“前一个”和“下一个”元素,例如来自这些模板:
<xsl:template match="section" mode="prev">
<xsl:value-of select="... what to put here ..."/>
</xsl:template>
<xsl:template match="section" mode="next">
<xsl:value-of select="... what to put here ..."/>
</xsl:template>
请注意,这是一个类似但不相同的问题:XPath 1.0 closest preceding and/or ancestor node with an attribute in a XML Tree。这些XPath结构真的在我脑海中,有时候......
答案 0 :(得分:1)
这是一个样式表,它将Nicholas建议与union结合,然后将last()
用于前一项,第一项用于下一项:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="html" indent="yes"/>
<xsl:template match="manual">
<table>
<thead>
<tr>
<th>Selected section</th>
<th>Previous section</th>
<th>Next section</th>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="descendant::section"/>
</tbody>
</table>
</xsl:template>
<xsl:template match="section">
<tr>
<td>
<xsl:value-of select="@id"/>
</td>
<xsl:apply-templates select="." mode="prev"/>
<xsl:apply-templates select="." mode="next"/>
</tr>
</xsl:template>
<xsl:template match="section" mode="prev">
<td>
<xsl:value-of select="(preceding::section | ancestor::section)[last()]/@id"/>
</td>
</xsl:template>
<xsl:template match="section" mode="next">
<td>
<xsl:value-of select="(following::section | descendant::section)[1]/@id"/>
</td>
</xsl:template>
</xsl:stylesheet>
使用您的样本输入Saxon 6.5.5输出
<table>
<thead>
<tr>
<th>Selected section</th>
<th>Previous section</th>
<th>Next section</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td></td>
<td>2</td>
</tr>
<tr>
<td>2</td>
<td>1</td>
<td>3</td>
</tr>
<tr>
<td>3</td>
<td>1</td>
<td>4</td>
</tr>
<tr>
<td>4</td>
<td>1</td>
<td>5</td>
</tr>
<tr>
<td>5</td>
<td>1</td>
<td>6</td>
</tr>
<tr>
<td>6</td>
<td>1</td>
<td>7</td>
</tr>
<tr>
<td>7</td>
<td>1</td>
<td>8</td>
</tr>
<tr>
<td>8</td>
<td>1</td>
<td>9</td>
</tr>
<tr>
<td>9</td>
<td>1</td>
<td>10</td>
</tr>
<tr>
<td>10</td>
<td>1</td>
<td>11</td>
</tr>
<tr>
<td>11</td>
<td>1</td>
<td>12</td>
</tr>
<tr>
<td>12</td>
<td>1</td>
<td></td>
</tr>
</tbody>
</table>
答案 1 :(得分:0)
“不那么优雅”的实现就是这个(选择@id
而不是整个节点)
<xsl:template match="section" mode="prev-id">
<xsl:variable name="id" select="@id"/>
<xsl:variable name="position">
<xsl:for-each select="//section">
<xsl:if test="@id = $id">
<xsl:value-of select="position()"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:for-each select="//section">
<xsl:if test="position() = $position - 1">
<xsl:value-of select="@id"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="section" mode="next-id">
<xsl:variable name="id" select="@id"/>
<xsl:variable name="position">
<xsl:for-each select="//section">
<xsl:if test="@id = $id">
<xsl:value-of select="position()"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:for-each select="//section">
<xsl:if test="position() = $position + 1">
<xsl:value-of select="@id"/>
</xsl:if>
</xsl:for-each>
</xsl:template>