请建议如何对文本节点以及“i
”元素中的“b
”或“list
”或“p
”等元素进行分组。确保div
不应该是p
的孩子。
XML:(用于显示目的的换行符或空格,在第二个XML下运行使用)
<article>
<body>
<para>
<display><fig>Fig1</fig></display>
the text node1
</para>
<para>
<display><fig>Fig1</fig></display>
</para>
<para>
<display><fig>Fig1</fig></display>
the text node1 <i>h</i> ther <b>b</b> the text4
<display><tab>Table1</tab></display>
the text node2
<list><li>list1</li></list>
</para>
<para>The text node3</para>
</body>
</article>
XML:(没有换行符)
<article><body><para><display><fig>Fig1</fig></display>the text node1</para><para><display><fig>Fig1</fig></display></para><para><display><fig>Fig1</fig></display>the text node1 <i>h</i> ther <b>b</b> the text4<display><tab>Table1</tab></display>the text node2<list><li>list1</li></list></para><para>The text node3</para></body></article>
XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template>
<xsl:template match="para">
<xsl:choose>
<xsl:when test="not(text())"><xsl:apply-templates/></xsl:when>
<xsl:when test="display and text() or *">
<xsl:for-each select="node()">
<xsl:choose>
<xsl:when test="name()='display'"><div><xsl:apply-templates/></div></xsl:when>
<xsl:when test="name()='i' or name()='b'">
<xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:when>
<xsl:when test="not(*)"><p><xsl:value-of select="."/></p></xsl:when><!--Here grouping required with adjacent elements 'i' or 'b' etc -->
<xsl:otherwise><p><xsl:apply-templates/></p></xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<p><xsl:apply-templates/></p>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
必填结果:
<article>
<body>
<div><fig>Fig1</fig></div><!--ensure div should not child to 'p'-->
<p>the text node1</p> <!--Text area including 'i' and 'b' to be within 'p' -->
<div><fig>Fig1</fig></div>
<div><fig>Fig1</fig></div>
<p>the text node1 <i>h</i> ther <b>b</b> the text4</p><!--Text area including 'i' and 'b' to be within 'p' -->
<div><tab>Table1</tab></div>
<p>the text node2<list><li>list1</li></list></p><!--text area includes 'list' element -->
<p>The text node3</p>
</body>
</article>
答案 0 :(得分:3)
在使用XSLT 2.0时,您可以在此处使用xsl:for-each-group
,根据它们是否为display
元素对相邻的子节点进行分组。
<xsl:for-each-group select="node()" group-adjacent="boolean(self::display)">
因此,display
以外的节点将具有false
的分组键,因此可以将它们组合在一起,允许您将它们包装在p
标记中
试试这个XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
</xsl:template>
<xsl:template match="para">
<xsl:for-each-group select="node()" group-adjacent="boolean(self::display)">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<xsl:apply-templates select="current-group()" />
</xsl:when>
<xsl:otherwise>
<p>
<xsl:apply-templates select="current-group()" />
</p>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="display">
<div>
<xsl:apply-templates />
</div>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
我认为你可以使用for-each-group group-adjacent="boolean(self::text() | self::i |.."
:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="para">
<xsl:for-each-group select="node()" group-adjacent="boolean(self::text() | self::i | self::b | self::list)">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<p>
<xsl:apply-templates select="current-group()"/>
</p>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="display">
<div>
<xsl:apply-templates/>
</div>
</xsl:template>
</xsl:stylesheet>