展平嵌套在文本节点中的 child 个元素
Flatten child elements nested within text nodes
这里有很多扁平化问题,但是 none 处理这种复杂程度。
我有一个 xml 文档,看起来像:
<document>
<div class='target-one'>
maybe some text node, maybe not...1
<randomElement>
maybe some text node, maybe not...2
</randomElement>
<div class='target-one'>
<randomElement>
maybe some text node, maybe not...3
</randomElement>
</div>
maybe some text node, maybe not...4
<randomElement>
maybe some text node, maybe not...5
</randomElement>
<div class='target-two'>
maybe some text node, maybe not...6
<randomElement>
maybe some text node, maybe not...7
</randomElement>
</div>
maybe some text node, maybe not...8
<randomElement>
maybe some text node, maybe not...9
</randomElement>
</div>
<div class='target-two'>
maybe some text node, maybe not...10
<randomElement>
maybe some text node, maybe not...11
</randomElement>
<div class='target-one'>
<randomElement>
maybe some text node, maybe not...12
</randomElement>
</div>
maybe some text node, maybe not...13
<randomElement>
maybe some text node, maybe not...14
</randomElement>
<div class='target-two'>
maybe some text node, maybe not...15
<randomElement>
maybe some text node, maybe not...16
</randomElement>
</div>
maybe some text node, maybe not...17
<randomElement>
maybe some text node, maybe not...18
</randomElement>
</div>
</document>
所以有一个可以按任何顺序嵌套的目标元素列表。我想通过添加更多 parent 元素来分别包裹 randomElement 和节点,同时使目标 children 成为目标兄弟姐妹,从而在它们嵌套时将它们展平。我的意思是输出应该是这样的:
<document>
<div class='target-one'>
maybe some text node, maybe not...1
<randomElement>
maybe some text node, maybe not...2
</randomElement>
</div>
<div class='target-one'>
<randomElement>
maybe some text node, maybe not...3
</randomElement>
</div>
<div class='target-one'>
maybe some text node, maybe not...4
<randomElement>
maybe some text node, maybe not...5
</randomElement>
</div>
<div class='target-two'>
maybe some text node, maybe not...6
<randomElement>
maybe some text node, maybe not...7
</randomElement>
</div>
<div class='target-one'>
maybe some text node, maybe not...8
<randomElement>
maybe some text node, maybe not...9
</randomElement>
</div>
<div class='target-two'>
maybe some text node, maybe not...10
<randomElement>
maybe some text node, maybe not...11
</randomElement>
</div>
<div class='target-one'>
<randomElement>
maybe some text node, maybe not...12
</randomElement>
</div>
<div class='target-two'>
maybe some text node, maybe not...13
<randomElement>
maybe some text node, maybe not...14
</randomElement>
</div>
<div class='target-two'>
maybe some text node, maybe not...15
<randomElement>
maybe some text node, maybe not...16
</randomElement>
</div>
<div class='target-two'>
maybe some text node, maybe not...17
<randomElement>
maybe some text node, maybe not...18
</randomElement>
</div>
</document>
所以我得到了更多的 parent div,但是所有的文本和其他节点都在正确的位置。请注意,randomElement 可能是 div 而不是目标 class...
这是为了重新格式化电子书以便在在线图书馆中分页,因此在我们真正遇到问题之前可能会有大量元素 div。因此我们需要一些方法 select 问题 children div 之间的所有元素和文本节点作为一个组,因为如果它们都包含在自己的 div 中s,它没有用——我们最终会将每个 p、em 或 span 作为自己的页面。
同时,大部分parentdiv都没有问题children。只要解决方案通过它们,我就可以用另一个 运行 清理任何空的 div,但我确实需要它至少在基本级别上使用没有 [=37] 的文本=] 元素也是如此。
这是我在 Whosebug 上的第一个问题,因为我只是没有得到为此所必需的递归。
谢谢!
根据 user52889 的回答进行编辑。这从来没有成功过,但为了便于阅读,我把它留在这里:
我可以在撒克逊语中使用的 XSL:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"version="2.0">
<xsl:output method="html"
indent="yes"
encoding="utf-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="div[matches(@class,'target-one|target-two','i')]">
<xsl:for-each select="node()">
<xsl:choose>
<xsl:when test="self::*[matches(@class,'target-one|target-two','i')]">
<xsl:apply-templates select="."/>
</xsl:when>
<xsl:when test="preceding-sibling::node()[0][not(self::*[matches(@class,'target-one|target-two','i')])]">
<!-- do nothing, it will be handled by the next case -->
</xsl:when>
<xsl:otherwise>
<!--
create a copy of the element matched by the template, with its attrs
add to it the current node and all nodes which follow it, up to the next SIGNIFICANT node
or, put another way, all following siblings which either
a) do not have a preceding signficant node, or
b) whose nearest preceding singificant node is the same as the nearest preceding significant node of the current node, i.e. its following sibling node is the current node.
-->
<xsl:element name="{../name()}">
<xsl:apply-templates select="../@*"/>
<xsl:apply-templates select="following-sibling::node()[
not(preceding-sibling::*[matches(@class,'target-one|target-two','i')])
or
count(preceding-sibling::*[matches(@class,'target-one|target-two','i')][0]/following-sibling::node()[0] | current()) = 1
]" />
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
此文件的当前输出 children 和重复项:
<document>
<div class="target-one">
<randomElement>
maybe some text node, maybe not...2
</randomElement>
<div class="target-one"></div>
maybe some text node, maybe not...4
<randomElement>
maybe some text node, maybe not...5
</randomElement>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...7
</randomElement>
</div>
<div class="target-two"></div>
maybe some text node, maybe not...8
<randomElement>
maybe some text node, maybe not...9
</randomElement>
</div>
<div class="target-one">
<div class="target-one"></div>
maybe some text node, maybe not...4
<randomElement>
maybe some text node, maybe not...5
</randomElement>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...7
</randomElement>
</div>
<div class="target-two"></div>
maybe some text node, maybe not...8
<randomElement>
maybe some text node, maybe not...9
</randomElement>
</div>
<div class="target-one"></div>
<div class="target-one">
<randomElement>
maybe some text node, maybe not...5
</randomElement>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...7
</randomElement>
</div>
<div class="target-two"></div>
maybe some text node, maybe not...8
<randomElement>
maybe some text node, maybe not...9
</randomElement>
</div>
<div class="target-one">
<div class="target-two">
<randomElement>
maybe some text node, maybe not...7
</randomElement>
</div>
<div class="target-two"></div>
maybe some text node, maybe not...8
<randomElement>
maybe some text node, maybe not...9
</randomElement>
</div>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...7
</randomElement>
</div>
<div class="target-two"></div>
<div class="target-one">
<randomElement>
maybe some text node, maybe not...9
</randomElement>
</div>
<div class="target-one"></div>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...11
</randomElement>
<div class="target-one"></div>
maybe some text node, maybe not...13
<randomElement>
maybe some text node, maybe not...14
</randomElement>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...16
</randomElement>
</div>
<div class="target-two"></div>
maybe some text node, maybe not...17
<randomElement>
maybe some text node, maybe not...18
</randomElement>
</div>
<div class="target-two">
<div class="target-one"></div>
maybe some text node, maybe not...13
<randomElement>
maybe some text node, maybe not...14
</randomElement>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...16
</randomElement>
</div>
<div class="target-two"></div>
maybe some text node, maybe not...17
<randomElement>
maybe some text node, maybe not...18
</randomElement>
</div>
<div class="target-one"></div>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...14
</randomElement>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...16
</randomElement>
</div>
<div class="target-two"></div>
maybe some text node, maybe not...17
<randomElement>
maybe some text node, maybe not...18
</randomElement>
</div>
<div class="target-two">
<div class="target-two">
<randomElement>
maybe some text node, maybe not...16
</randomElement>
</div>
<div class="target-two"></div>
maybe some text node, maybe not...17
<randomElement>
maybe some text node, maybe not...18
</randomElement>
</div>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...16
</randomElement>
</div>
<div class="target-two"></div>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...18
</randomElement>
</div>
<div class="target-two"></div>
</document>
听起来你想要像下面这样的东西,其中 SIGNIFICANT 是描述所有这些元素的表达式,并且只描述那些你想成为新列表项的元素(例如 div[substring(@class,1,6)='target']
之类的东西)...
<xsl:template match="SIGNIFICANT">
<xsl:for-each select="node()">
<xsl:choose>
<xsl:when test="self::SIGNIFICANT">
<xsl:apply-templates select="."/>
</xsl:when>
<xsl:when test="preceding-sibling::node()[0][not(self::SIGNIFICANT)]">
<!-- do nothing, it will be handled by the next case -->
</xsl:when>
<xsl:otherwise>
<!--
create a copy of the element matched by the template, with its attrs
add to it the current node and all nodes which follow it, up to the next SIGNIFICANT node
or, put another way, all following siblings which either
a) do not have a preceding signficant node, or
b) whose nearest preceding singificant node is the same as the nearest preceding significant node of the current node, i.e. its following sibling node is the current node.
-->
<xsl:element name="../name()">
<xsl:apply-templates select="../@*"/>
<xsl:apply-templates select="following-sibling::node()[
not(preceding-sibling::SIGNIFICANT)
or
count(preceding-sibling::SIGNIFICANT[0]/following-sibling::node()[0] | current()) = 1
]">
</xsl:element>
</xsl:otherwise>
</xsl:for-each>
</xsl:template>
注意:这意味着没有子节点的顶级 div
将被完全删除。如果你不想要这种行为,你可以简单地包装在 choose/when 中。
另请注意:对于极长的列表,可能有更高效的递归方法。
很难理解您的示例中的什么是规则,什么只是示例。以下样式表将产生所需的结果——也许这就是您正在寻找的结果。如果不是,请编辑您的问题并解释所请求转换背后的 逻辑 。
XSLT 2.0(或 1.0)
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/document">
<document>
<xsl:for-each select="//randomElement">
<div class='{../@class}'>
<xsl:copy-of select=". | preceding-sibling::text()[1]"/>
</div>
</xsl:for-each>
</document>
</xsl:template>
</xsl:stylesheet>
试图把它当作我想出的分组问题
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:param name="prefix" select="'target-'"/>
<xsl:output indent="yes"/>
<xsl:template match="document">
<xsl:copy>
<xsl:for-each-group select="descendant::text()[normalize-space()]"
group-adjacent="generate-id(ancestor::div[starts-with(@class, $prefix)][1])">
<xsl:apply-templates select="ancestor::div[starts-with(@class, $prefix)][1]" mode="g">
<xsl:with-param name="group" select="current-group()"/>
</xsl:apply-templates>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="g">
<xsl:param name="group"/>
<xsl:if test=". intersect $group/ancestor::*">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="node()" mode="g">
<xsl:with-param name="group" select="$group"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:if>
</xsl:template>
<xsl:template match="text()" mode="g">
<xsl:param name="group"/>
<xsl:if test=". intersect $group">
<xsl:copy/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
这基本上将所有非白色 space 文本节点的后代按最近的祖先 div
与您要查找的 class
分组,然后重新创建祖先中包含的子树分组文本节点。
这里有很多扁平化问题,但是 none 处理这种复杂程度。
我有一个 xml 文档,看起来像:
<document>
<div class='target-one'>
maybe some text node, maybe not...1
<randomElement>
maybe some text node, maybe not...2
</randomElement>
<div class='target-one'>
<randomElement>
maybe some text node, maybe not...3
</randomElement>
</div>
maybe some text node, maybe not...4
<randomElement>
maybe some text node, maybe not...5
</randomElement>
<div class='target-two'>
maybe some text node, maybe not...6
<randomElement>
maybe some text node, maybe not...7
</randomElement>
</div>
maybe some text node, maybe not...8
<randomElement>
maybe some text node, maybe not...9
</randomElement>
</div>
<div class='target-two'>
maybe some text node, maybe not...10
<randomElement>
maybe some text node, maybe not...11
</randomElement>
<div class='target-one'>
<randomElement>
maybe some text node, maybe not...12
</randomElement>
</div>
maybe some text node, maybe not...13
<randomElement>
maybe some text node, maybe not...14
</randomElement>
<div class='target-two'>
maybe some text node, maybe not...15
<randomElement>
maybe some text node, maybe not...16
</randomElement>
</div>
maybe some text node, maybe not...17
<randomElement>
maybe some text node, maybe not...18
</randomElement>
</div>
</document>
所以有一个可以按任何顺序嵌套的目标元素列表。我想通过添加更多 parent 元素来分别包裹 randomElement 和节点,同时使目标 children 成为目标兄弟姐妹,从而在它们嵌套时将它们展平。我的意思是输出应该是这样的:
<document>
<div class='target-one'>
maybe some text node, maybe not...1
<randomElement>
maybe some text node, maybe not...2
</randomElement>
</div>
<div class='target-one'>
<randomElement>
maybe some text node, maybe not...3
</randomElement>
</div>
<div class='target-one'>
maybe some text node, maybe not...4
<randomElement>
maybe some text node, maybe not...5
</randomElement>
</div>
<div class='target-two'>
maybe some text node, maybe not...6
<randomElement>
maybe some text node, maybe not...7
</randomElement>
</div>
<div class='target-one'>
maybe some text node, maybe not...8
<randomElement>
maybe some text node, maybe not...9
</randomElement>
</div>
<div class='target-two'>
maybe some text node, maybe not...10
<randomElement>
maybe some text node, maybe not...11
</randomElement>
</div>
<div class='target-one'>
<randomElement>
maybe some text node, maybe not...12
</randomElement>
</div>
<div class='target-two'>
maybe some text node, maybe not...13
<randomElement>
maybe some text node, maybe not...14
</randomElement>
</div>
<div class='target-two'>
maybe some text node, maybe not...15
<randomElement>
maybe some text node, maybe not...16
</randomElement>
</div>
<div class='target-two'>
maybe some text node, maybe not...17
<randomElement>
maybe some text node, maybe not...18
</randomElement>
</div>
</document>
所以我得到了更多的 parent div,但是所有的文本和其他节点都在正确的位置。请注意,randomElement 可能是 div 而不是目标 class...
这是为了重新格式化电子书以便在在线图书馆中分页,因此在我们真正遇到问题之前可能会有大量元素 div。因此我们需要一些方法 select 问题 children div 之间的所有元素和文本节点作为一个组,因为如果它们都包含在自己的 div 中s,它没有用——我们最终会将每个 p、em 或 span 作为自己的页面。
同时,大部分parentdiv都没有问题children。只要解决方案通过它们,我就可以用另一个 运行 清理任何空的 div,但我确实需要它至少在基本级别上使用没有 [=37] 的文本=] 元素也是如此。
这是我在 Whosebug 上的第一个问题,因为我只是没有得到为此所必需的递归。
谢谢!
根据 user52889 的回答进行编辑。这从来没有成功过,但为了便于阅读,我把它留在这里:
我可以在撒克逊语中使用的 XSL:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"version="2.0">
<xsl:output method="html"
indent="yes"
encoding="utf-8"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="div[matches(@class,'target-one|target-two','i')]">
<xsl:for-each select="node()">
<xsl:choose>
<xsl:when test="self::*[matches(@class,'target-one|target-two','i')]">
<xsl:apply-templates select="."/>
</xsl:when>
<xsl:when test="preceding-sibling::node()[0][not(self::*[matches(@class,'target-one|target-two','i')])]">
<!-- do nothing, it will be handled by the next case -->
</xsl:when>
<xsl:otherwise>
<!--
create a copy of the element matched by the template, with its attrs
add to it the current node and all nodes which follow it, up to the next SIGNIFICANT node
or, put another way, all following siblings which either
a) do not have a preceding signficant node, or
b) whose nearest preceding singificant node is the same as the nearest preceding significant node of the current node, i.e. its following sibling node is the current node.
-->
<xsl:element name="{../name()}">
<xsl:apply-templates select="../@*"/>
<xsl:apply-templates select="following-sibling::node()[
not(preceding-sibling::*[matches(@class,'target-one|target-two','i')])
or
count(preceding-sibling::*[matches(@class,'target-one|target-two','i')][0]/following-sibling::node()[0] | current()) = 1
]" />
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
此文件的当前输出 children 和重复项:
<document>
<div class="target-one">
<randomElement>
maybe some text node, maybe not...2
</randomElement>
<div class="target-one"></div>
maybe some text node, maybe not...4
<randomElement>
maybe some text node, maybe not...5
</randomElement>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...7
</randomElement>
</div>
<div class="target-two"></div>
maybe some text node, maybe not...8
<randomElement>
maybe some text node, maybe not...9
</randomElement>
</div>
<div class="target-one">
<div class="target-one"></div>
maybe some text node, maybe not...4
<randomElement>
maybe some text node, maybe not...5
</randomElement>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...7
</randomElement>
</div>
<div class="target-two"></div>
maybe some text node, maybe not...8
<randomElement>
maybe some text node, maybe not...9
</randomElement>
</div>
<div class="target-one"></div>
<div class="target-one">
<randomElement>
maybe some text node, maybe not...5
</randomElement>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...7
</randomElement>
</div>
<div class="target-two"></div>
maybe some text node, maybe not...8
<randomElement>
maybe some text node, maybe not...9
</randomElement>
</div>
<div class="target-one">
<div class="target-two">
<randomElement>
maybe some text node, maybe not...7
</randomElement>
</div>
<div class="target-two"></div>
maybe some text node, maybe not...8
<randomElement>
maybe some text node, maybe not...9
</randomElement>
</div>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...7
</randomElement>
</div>
<div class="target-two"></div>
<div class="target-one">
<randomElement>
maybe some text node, maybe not...9
</randomElement>
</div>
<div class="target-one"></div>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...11
</randomElement>
<div class="target-one"></div>
maybe some text node, maybe not...13
<randomElement>
maybe some text node, maybe not...14
</randomElement>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...16
</randomElement>
</div>
<div class="target-two"></div>
maybe some text node, maybe not...17
<randomElement>
maybe some text node, maybe not...18
</randomElement>
</div>
<div class="target-two">
<div class="target-one"></div>
maybe some text node, maybe not...13
<randomElement>
maybe some text node, maybe not...14
</randomElement>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...16
</randomElement>
</div>
<div class="target-two"></div>
maybe some text node, maybe not...17
<randomElement>
maybe some text node, maybe not...18
</randomElement>
</div>
<div class="target-one"></div>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...14
</randomElement>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...16
</randomElement>
</div>
<div class="target-two"></div>
maybe some text node, maybe not...17
<randomElement>
maybe some text node, maybe not...18
</randomElement>
</div>
<div class="target-two">
<div class="target-two">
<randomElement>
maybe some text node, maybe not...16
</randomElement>
</div>
<div class="target-two"></div>
maybe some text node, maybe not...17
<randomElement>
maybe some text node, maybe not...18
</randomElement>
</div>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...16
</randomElement>
</div>
<div class="target-two"></div>
<div class="target-two">
<randomElement>
maybe some text node, maybe not...18
</randomElement>
</div>
<div class="target-two"></div>
</document>
听起来你想要像下面这样的东西,其中 SIGNIFICANT 是描述所有这些元素的表达式,并且只描述那些你想成为新列表项的元素(例如 div[substring(@class,1,6)='target']
之类的东西)...
<xsl:template match="SIGNIFICANT">
<xsl:for-each select="node()">
<xsl:choose>
<xsl:when test="self::SIGNIFICANT">
<xsl:apply-templates select="."/>
</xsl:when>
<xsl:when test="preceding-sibling::node()[0][not(self::SIGNIFICANT)]">
<!-- do nothing, it will be handled by the next case -->
</xsl:when>
<xsl:otherwise>
<!--
create a copy of the element matched by the template, with its attrs
add to it the current node and all nodes which follow it, up to the next SIGNIFICANT node
or, put another way, all following siblings which either
a) do not have a preceding signficant node, or
b) whose nearest preceding singificant node is the same as the nearest preceding significant node of the current node, i.e. its following sibling node is the current node.
-->
<xsl:element name="../name()">
<xsl:apply-templates select="../@*"/>
<xsl:apply-templates select="following-sibling::node()[
not(preceding-sibling::SIGNIFICANT)
or
count(preceding-sibling::SIGNIFICANT[0]/following-sibling::node()[0] | current()) = 1
]">
</xsl:element>
</xsl:otherwise>
</xsl:for-each>
</xsl:template>
注意:这意味着没有子节点的顶级 div
将被完全删除。如果你不想要这种行为,你可以简单地包装在 choose/when 中。
另请注意:对于极长的列表,可能有更高效的递归方法。
很难理解您的示例中的什么是规则,什么只是示例。以下样式表将产生所需的结果——也许这就是您正在寻找的结果。如果不是,请编辑您的问题并解释所请求转换背后的 逻辑 。
XSLT 2.0(或 1.0)
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/document">
<document>
<xsl:for-each select="//randomElement">
<div class='{../@class}'>
<xsl:copy-of select=". | preceding-sibling::text()[1]"/>
</div>
</xsl:for-each>
</document>
</xsl:template>
</xsl:stylesheet>
试图把它当作我想出的分组问题
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:param name="prefix" select="'target-'"/>
<xsl:output indent="yes"/>
<xsl:template match="document">
<xsl:copy>
<xsl:for-each-group select="descendant::text()[normalize-space()]"
group-adjacent="generate-id(ancestor::div[starts-with(@class, $prefix)][1])">
<xsl:apply-templates select="ancestor::div[starts-with(@class, $prefix)][1]" mode="g">
<xsl:with-param name="group" select="current-group()"/>
</xsl:apply-templates>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="g">
<xsl:param name="group"/>
<xsl:if test=". intersect $group/ancestor::*">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="node()" mode="g">
<xsl:with-param name="group" select="$group"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:if>
</xsl:template>
<xsl:template match="text()" mode="g">
<xsl:param name="group"/>
<xsl:if test=". intersect $group">
<xsl:copy/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
这基本上将所有非白色 space 文本节点的后代按最近的祖先 div
与您要查找的 class
分组,然后重新创建祖先中包含的子树分组文本节点。