我有一个正在使用的测试文件,我正在尝试包装中。如果将模板匹配项更改为root,则可以使其正常工作,但随后我将失去所有其他东西。有什么想法吗?提前致谢。这是我到目前为止的xml和xsl。
xml输入
<?xml version="1.0" encoding="UTF-8"?>
<document>
<chapter>
<title toc_id="new">An new story</title>
<para>New stories are different</para>
<listitem class="ol">Here is one list item</listitem>
<listitem class="ol">Here is two list item</listitem>
<listitem class="ol">Here is three list item</listitem>
<section>
<title toc_id="h2-intro-1">Introduction H1</title>
<para>Upon a time ....</para>
<title toc_id="h2-intro-2">Introduction H2</title>
<para>... there was a young prince. http://www.stuff.com, here's a website</para>
</section>
</chapter>
</document>
对于xslt:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"
doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="listitem">
<xsl:for-each-group select="." group-by="@class">
<ol>
<xsl:for-each select=".">
<li>
<p>
<xsl:value-of select="."/>
</p>
</li>
</xsl:for-each>
</ol>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
我正在寻找的输出是这样:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<document>
<chapter>
<title toc_id="new">An new story</title>
<para>New stories are different</para>
<ol>
<li>
<p>Here is one list item</p>
</li>
<li>
<p>Here is two list item</p>
</li>
<li>
<p>Here is three list item</p>
</li>
</ol>
<section>
<title toc_id="h2-intro-1">Introduction H1</title>
<para>Upon a time ....</para>
<title toc_id="h2-intro-2">Introduction H2</title>
<para>... there was a young prince. http://www.stuff.com, here's a website</para>
</section>
</chapter>
</document>
答案 0 :(得分:0)
因为listitem
的模板匹配每个单个项目,而您的fo-each-group
仅适用于.
(当前元素),因此会包装每个元素。
您需要调整更多选择。
您的模板仅需应用于listitem
,其前身不是listitem
(可能是具有相同类的列表项)。在模板内部,您需要打开ol
标记,然后使用不同的规则来计算项目和所有后继者的内容,只要它们是listitem
。
检查XPath轴:https://www.w3schools.com/xml/xpath_axes.asp
应该可以执行以下操作:
<xsl:template match="listitem[preceding-sibling::self[position()=1 and name() != 'listitem']]">
<ol>
<xsl:apply-templates mode="inlist" select="."/>
</ol>
</xsl:template>
<xsl:template match="listitem" mode="inlist">
<li><xsl:value-of select="."/></li>
<xsl:apply-templates select="following-sibling::self[position() = 1 and name() = 'listitem']" mode="inlist"/>
</xsl:template>
答案 1 :(得分:0)
我将使用match="*[listitem]"
或match="*[listitem[@class]]"
来匹配包含要分组/包装的listitem
元素的父元素,然后在以下元素的子元素上使用for-each-group
父级,如果只希望它们是元素,则可以在XSLT 3中使用select="*" composite="yes" group-adjacent="boolean(self::listitem), @class"
来标识具有相同listitem
属性值的相邻class
:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output method="html" indent="yes" html-version="5"/>
<xsl:template match="*[listitem]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each-group select="*" composite="yes" group-adjacent="boolean(self::listitem), @class">
<xsl:choose>
<xsl:when test="current-grouping-key()[1]">
<xsl:element name="{current-grouping-key()[2]}">
<xsl:apply-templates select="current-group()"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="listitem">
<li>
<p>
<xsl:apply-templates/>
</p>
</li>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/gWmuiJK
借助XSLT 2,您可以使用两个嵌套的for-each-group
,例如
<xsl:for-each-group select="*" group-adjacent="boolean(self::listitem)">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<xsl:for-each-group select="current-group()" group-adjacent="@class">
<xsl:element name="{current-grouping-key()}">
<xsl:apply-templates select="current-group()"/>
</xsl:element>
</xsl:for-each-group>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
请参阅https://xsltfiddle.liberty-development.net/gWmuiJK/1,有关完整的XSLT 2解决方案,您当然需要用身份转换模板(您已经在发布的代码中)替换xsl:mode
声明。