XSLT - 与给定节点的以下兄弟姐妹一起工作
XSLT - working with following siblings of given node
我有一个 xml 如下,
<doc>
<h1>header 1</h1>
<p>para 1</p>
<p>para 2</p>
<h1>header 2</h1>
<p>para 3</p>
<p>para 4</p>
<h1>header 3</h1>
<p>para 5</p>
<p>para 6</p>
</doc>
我的要求是从 <h1>
和 link 这些列表项创建无序列表,并且它在 <p>
个节点之后。
所以期望的输出应该是,
<doc>
<div name="list">
<ul>
<li><a href="h1-1">header 1</a></li>
<li><a href="h1-2">header 2</a></li>
<li><a href="h1-3">header 3</a></li>
</ul>
</div>
<div class="content">
<div id="h1-1">
<p>para 1</p>
<p>para 2</p>
</div>
<div id="h1-2">
<p>para 3</p>
<p>para 4</p>
</div>
<div id="h1-3">
<p>para 5</p>
<p>para 6</p>
</div>
</div>
</doc>
我已经编写了以下 xsl 来完成此任务,
<doc>
<div name="list">
<ul>
<xsl:for-each-group select="*" group-starting-with="h1">
<li><a href="h1-{count(preceding::h1)+1}"><xsl:apply-templates/></a></li>
</xsl:for-each-group>
</ul>
</div>
<div class="content">
<xsl:for-each select="h1">
<div id="h1-{count(preceding::h1)+1}">
<!-- should copy follwing <p> nodes in <h1> -->
</div>
</xsl:for-each>
</div>
</doc>
我无法解决的是如何将 <p>
节点作为以下兄弟节点放置到 <h1>
但在出现另一个 <h1>
之前。 (例子会给出清晰的思路。)
任何人都可以建议我解决这个问题吗?
您可能只想查看您的来源 xml。如果段落只是该特定章节的一部分,它们可能应该是 header 的 child 节点。现在没有真正的方法来识别正确的段落。
完成后,解决方案应该更简单。
您的方法需要反转:第一个 div
不需要分组,第二个需要。
而且不需要考虑后面(或前面)的兄弟姐妹;只需将组缩小到 p
个元素即可。
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8" indent="yes"/>
<xsl:template match="doc">
<doc>
<div name="list">
<ul>
<xsl:for-each select="h1">
<li>
<a href="h1-{position()}">
<xsl:value-of select="."/>
</a>
</li>
</xsl:for-each>
</ul>
</div>
<div class="content">
<xsl:for-each-group select="*" group-starting-with="h1">
<div id="h1-{position()}">
<xsl:copy-of select="current-group()[self::p]"/>
</div>
</xsl:for-each-group>
</div>
</doc>
</xsl:template>
</xsl:stylesheet>
我有一个 xml 如下,
<doc>
<h1>header 1</h1>
<p>para 1</p>
<p>para 2</p>
<h1>header 2</h1>
<p>para 3</p>
<p>para 4</p>
<h1>header 3</h1>
<p>para 5</p>
<p>para 6</p>
</doc>
我的要求是从 <h1>
和 link 这些列表项创建无序列表,并且它在 <p>
个节点之后。
所以期望的输出应该是,
<doc>
<div name="list">
<ul>
<li><a href="h1-1">header 1</a></li>
<li><a href="h1-2">header 2</a></li>
<li><a href="h1-3">header 3</a></li>
</ul>
</div>
<div class="content">
<div id="h1-1">
<p>para 1</p>
<p>para 2</p>
</div>
<div id="h1-2">
<p>para 3</p>
<p>para 4</p>
</div>
<div id="h1-3">
<p>para 5</p>
<p>para 6</p>
</div>
</div>
</doc>
我已经编写了以下 xsl 来完成此任务,
<doc>
<div name="list">
<ul>
<xsl:for-each-group select="*" group-starting-with="h1">
<li><a href="h1-{count(preceding::h1)+1}"><xsl:apply-templates/></a></li>
</xsl:for-each-group>
</ul>
</div>
<div class="content">
<xsl:for-each select="h1">
<div id="h1-{count(preceding::h1)+1}">
<!-- should copy follwing <p> nodes in <h1> -->
</div>
</xsl:for-each>
</div>
</doc>
我无法解决的是如何将 <p>
节点作为以下兄弟节点放置到 <h1>
但在出现另一个 <h1>
之前。 (例子会给出清晰的思路。)
任何人都可以建议我解决这个问题吗?
您可能只想查看您的来源 xml。如果段落只是该特定章节的一部分,它们可能应该是 header 的 child 节点。现在没有真正的方法来识别正确的段落。
完成后,解决方案应该更简单。
您的方法需要反转:第一个 div
不需要分组,第二个需要。
而且不需要考虑后面(或前面)的兄弟姐妹;只需将组缩小到 p
个元素即可。
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8" indent="yes"/>
<xsl:template match="doc">
<doc>
<div name="list">
<ul>
<xsl:for-each select="h1">
<li>
<a href="h1-{position()}">
<xsl:value-of select="."/>
</a>
</li>
</xsl:for-each>
</ul>
</div>
<div class="content">
<xsl:for-each-group select="*" group-starting-with="h1">
<div id="h1-{position()}">
<xsl:copy-of select="current-group()[self::p]"/>
</div>
</xsl:for-each-group>
</div>
</doc>
</xsl:template>
</xsl:stylesheet>