使用 XSLT 的列表虚拟嵌套
virtual nesting of list using XSLT
我需要按以下方式嵌套列表,我必须创建 n-1 个列表包装器,其中 n 是 @virtual-nesting 的值:
XML 文档:
<l virtual-nesting="3">
<li>
<lilabel/>
<p>
<text>Data used:</text>
</p>
</li>
</l>
需要输出:
<list>
<listitem>
<bodytext>
<list>
<listitem>
<label/>
<bodytext>
<p>
<text>Data used:</text>
</p>
</bodytext>
</listitem>
</list>
</bodytext>
</listitem>
</list>
XSLT 我试过了。因为我是新手:
<xsl:template match="l">
<xsl:choose>
<xsl:when test="@virtual-nesting">
<xsl:variable name="virtual"><xsl:value-of select="@virtual-nesting"/></xsl:variable>
<xsl:if test="$virtual>0">
<xsl:apply-templates select="generate-id(following-sibling::node()),@virtual-nesting-1"/>
</xsl:if>
<xsl:apply-templates select="li"/>
</xsl:when>
<xsl:otherwise>
<xsl:element name="list">
<xsl:apply-templates select="li"/> <!-- Template for list and lilabel is already created -->
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
请指导我完成此操作。
递归是在 XSLT 中创建嵌套结构的关键。
以下使用递归 <xsl:template match="l">
和 $level
参数。此参数默认为 @virtual-nesting - 1
,之后随着每个递归步骤递减。
模板根据其值采用两种不同的路径。
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="l">
<xsl:param name="level" select="@virtual-nesting - 1" />
<list>
<listitem>
<xsl:if test="$level <= 1">
<xsl:apply-templates />
</xsl:if>
<xsl:if test="$level > 1">
<bodytext>
<xsl:apply-templates select=".">
<xsl:with-param name="level" select="$level - 1" />
</xsl:apply-templates>
</bodytext>
</xsl:if>
</listitem>
</list>
</xsl:template>
<xsl:template match="li">
<label>
<xsl:apply-templates select="lilabel/node()" />
</label>
<bodytext>
<xsl:apply-templates select="node()[not(self::lilabel)]" />
</bodytext>
</xsl:template>
</xsl:transform>
结果:
<list>
<listitem>
<bodytext>
<list>
<listitem>
<label/>
<bodytext>
<p>
<text>Data used:</text>
</p>
</bodytext>
</listitem>
</list>
</bodytext>
</listitem>
</list>
我需要按以下方式嵌套列表,我必须创建 n-1 个列表包装器,其中 n 是 @virtual-nesting 的值: XML 文档:
<l virtual-nesting="3">
<li>
<lilabel/>
<p>
<text>Data used:</text>
</p>
</li>
</l>
需要输出:
<list>
<listitem>
<bodytext>
<list>
<listitem>
<label/>
<bodytext>
<p>
<text>Data used:</text>
</p>
</bodytext>
</listitem>
</list>
</bodytext>
</listitem>
</list>
XSLT 我试过了。因为我是新手:
<xsl:template match="l">
<xsl:choose>
<xsl:when test="@virtual-nesting">
<xsl:variable name="virtual"><xsl:value-of select="@virtual-nesting"/></xsl:variable>
<xsl:if test="$virtual>0">
<xsl:apply-templates select="generate-id(following-sibling::node()),@virtual-nesting-1"/>
</xsl:if>
<xsl:apply-templates select="li"/>
</xsl:when>
<xsl:otherwise>
<xsl:element name="list">
<xsl:apply-templates select="li"/> <!-- Template for list and lilabel is already created -->
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
请指导我完成此操作。
递归是在 XSLT 中创建嵌套结构的关键。
以下使用递归 <xsl:template match="l">
和 $level
参数。此参数默认为 @virtual-nesting - 1
,之后随着每个递归步骤递减。
模板根据其值采用两种不同的路径。
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="l">
<xsl:param name="level" select="@virtual-nesting - 1" />
<list>
<listitem>
<xsl:if test="$level <= 1">
<xsl:apply-templates />
</xsl:if>
<xsl:if test="$level > 1">
<bodytext>
<xsl:apply-templates select=".">
<xsl:with-param name="level" select="$level - 1" />
</xsl:apply-templates>
</bodytext>
</xsl:if>
</listitem>
</list>
</xsl:template>
<xsl:template match="li">
<label>
<xsl:apply-templates select="lilabel/node()" />
</label>
<bodytext>
<xsl:apply-templates select="node()[not(self::lilabel)]" />
</bodytext>
</xsl:template>
</xsl:transform>
结果:
<list>
<listitem>
<bodytext>
<list>
<listitem>
<label/>
<bodytext>
<p>
<text>Data used:</text>
</p>
</bodytext>
</listitem>
</list>
</bodytext>
</listitem>
</list>