【发布时间】:2019-08-17 04:47:28
【问题描述】:
我需要使用 XSLT 1.0 从平面 XML 结构创建 HTML 无序列表。输入 XML 由一系列要转换为列表项的节点组成。但是,这个系列可能会被不同类型的非列表节点打断:
<input>
<paragraph>abc</paragraph>
<paragraph>def</paragraph>
<listable>123</listable>
<listable>456</listable>
<other-block>
<other-text>Foo</other-text>
</other-block>
<listable>789</listable>
<listable>012</listable>
</input>
我的目标是:
<div class="output">
<p>abc</p>
<p>def</p>
<ul>
<li>123</li>
<li>456</li>
</ul>
<div class="my-block">
<p class="other">Foo</p>
</div>
<ul>
<li>789</li>
<li>012</li>
</ul>
</div>
我找到了old thread with a solution that almost works for me(页面上的最后一个解决方案,由 Dimitre Novatchev 提供)并对其进行了修改。这是基于该解决方案的最小样式表:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes" encoding="utf-8" indent="yes" />
<xsl:strip-space elements="*" />
<!-- IDENTITY TRANSFORM: -->
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<!-- NON-LIST ITEMS: -->
<xsl:template match="input">
<div class="output">
<xsl:apply-templates />
</div>
</xsl:template>
<xsl:template match="paragraph">
<p>
<xsl:apply-templates />
</p>
</xsl:template>
<xsl:template match="other-block">
<div class="my-block">
<xsl:apply-templates select="descendant::other-text" />
</div>
</xsl:template>
<xsl:template match="other-text">
<p class="other">
<xsl:copy-of select="text()" />
</p>
</xsl:template>
<!-- LIST HANDLING: -->
<xsl:key name="kFollowingUL" match="listable"
use="generate-id(preceding-sibling::*[not(self::listable)][1])"/>
<xsl:template match="*[not(self::listable) and following-sibling::*[1][self::listable]]">
<xsl:call-template name="identity" />
<xsl:variable name="vFolUL"
select="key('kFollowingUL',generate-id())"/>
<xsl:if test="$vFolUL">
<ul>
<xsl:apply-templates mode="copy"
select="key('kFollowingUL',generate-id())" />
</ul>
</xsl:if>
</xsl:template>
<xsl:template match="listable" mode="copy">
<li>
<xsl:value-of select="normalize-space()" />
</li>
</xsl:template>
<xsl:template match="listable" />
</xsl:stylesheet>
这种方法的问题是它不会对每个列表之前的最后一个不可列表节点应用转换。输入中的 <paragraph> 和 <other-block> 节点直接复制到输出中,尽管模板应用于 <other-block> 的后代:
<div class="output">
<p>abc</p>
<paragraph>def</paragraph>
<ul>
<li>123</li>
<li>456</li>
</ul>
<other-block>
<p class="other">Foo</p>
</other-block>
<ul>
<li>789</li>
<li>012</li>
</ul>
</div>
谁能建议一种方法来修改早期的 XSLT 1.0 解决方案并在可列出组之前添加最后一个节点的转换?
【问题讨论】:
-
我们希望能够回答您关于如何做某事的特定问题,而不是仅仅为您编写代码。考虑到这一点,如果您能提供 minimal, complete, and verifiable example 以及您提出的关于某事如何运作或如何运作的具体问题,将会很有帮助。例如,我不知道你不知道什么。此外,我尝试将 Dimitre 的代码应用于您的示例输入,并且从您的帖子中得到了不同的输出。因此,请同时发布您正在使用的 XSL。
-
我修改了我的问题以包含输入、XSLT 和输出的工作示例。