如何使用XSLT将<p>标签内的元素与文本拆分至独立<p>标签?
需求:拆分
标签内的内容为独立元素
需要实现XSLT转换,将
标签内的子内容按原有顺序拆分:连续的文本及内联标签(如、)放入独立的
标签,块级元素(如)直接移出
,确保整体顺序不变。
输入示例
<kk><p id="p_aj3uga5iqfuzmmw"> Some text is here <table outputclass="ruled" id="ko4xjv6txx"> <tgroup cols="2" id="67dc15u6ud"> <colspec colname="c1" colnum="1" colwidth="40" id="jc204r3bna"/> <colspec colname="c2" colnum="2" colwidth="60" id="o79df53wog"/> <thead id="kih5dc7um1"> <row id="ve4ln370t8"> <entry id="yi4lwe9p51">head text is here</entry> <entry id="dwl1ol06ju">head text is here</entry> </row> </thead> <tbody id="62gug7qywr" class="- topic/tbody "> <row id="7wdson97xv" class="- topic/row "> <entry id="3at6ja8goj">text is here</entry> <entry id="m33p8e0e9f">text is here</entry> </row> </tbody> </tgroup> </table> <b id="nryvddsy5o"><i id="cs8atnkc9h">Component auditor responsibilities</i></b> some text here </p></kk>
期望输出
<kk><p id="p_aj3uga5iqfuzmmw"> Some text is here</p> <table outputclass="ruled" id="ko4xjv6txx"> <tgroup cols="2" id="67dc15u6ud"> <colspec colname="c1" colnum="1" colwidth="40" id="jc204r3bna"/> <colspec colname="c2" colnum="2" colwidth="60" id="o79df53wog"/> <thead id="kih5dc7um1"> <row id="ve4ln370t8"> <entry id="yi4lwe9p51">head text is here</entry> <entry id="dwl1ol06ju">head text is here</entry> </row> </thead> <tbody id="62gug7qywr" class="- topic/tbody "> <row id="7wdson97xv" class="- topic/row "> <entry id="3at6ja8goj">text is here</entry> <entry id="m33p8e0e9f">text is here</entry> </row> </tbody> </tgroup> </table> <p><b id="nryvddsy5o"><i id="cs8atnkc9h">Component auditor responsibilities</i></b> some text here</p></kk>
现有XSLT代码
<?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" xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" exclude-result-prefixes="xs xd" version="2.0"> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <xsl:template match="p"> <xsl:choose> <xsl:when test="starts-with(., text())"> <p><xsl:apply-templates select="text()[1] except table | text() | *"/></p> </xsl:when> <xsl:when test="table[1]"> <xsl:apply-templates select="table[1]"/> </xsl:when> <xsl:when test="*[1]"> <xsl:apply-templates select="*[1]"/> </xsl:when> </xsl:choose> </xsl:template> <xsl:template match="table"> <table> <xsl:apply-templates select="@* | node()"/> </table> </xsl:template> </xsl:stylesheet>
解决方案
核心思路是遍历
的所有子节点,将连续的文本节点和内联元素归为一组,生成新的
;**块级元素(如table)**直接输出,同时将原
的属性传递给第一个生成的新
。
以下是修正后的XSLT代码:
<?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="xs" version="2.0"> <!-- 身份模板:复制所有未匹配的节点和属性 --> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> <!-- 处理p标签 --> <xsl:template match="p"> <!-- 按节点类型分组:块级元素单独一组,文本+内联元素为一组 --> <xsl:for-each-group select="node()" group-adjacent="boolean(self::table)"> <xsl:choose> <!-- 块级元素组:直接输出 --> <xsl:when test="current-grouping-key()"> <xsl:apply-templates select="current-group()"/> </xsl:when> <!-- 文本+内联元素组:生成新的p标签 --> <xsl:otherwise> <p> <!-- 仅给第一个p标签添加原p的属性 --> <xsl:if test="position() = 1"> <xsl:apply-templates select="../@*"/> </xsl:if> <xsl:apply-templates select="current-group()"/> </p> </xsl:otherwise> </xsl:choose> </xsl:for-each-group> </xsl:template> </xsl:stylesheet>
关键说明
- 分组逻辑:使用
xsl:for-each-group按self::table分组,将table单独划分为一组,其余文本和内联元素(如b、i)归为连续组。 - 属性传递:仅给第一个生成的
标签保留原
的所有属性,符合示例输出要求。
- 身份模板复用:保留默认的身份模板,确保其他节点(如kk、table内部结构)原样复制,无需额外编写模板。
内容的提问来源于stack exchange,提问作者KITA ANSARI
相关产品推荐
相关产品推荐

