如何递归拼接当前节点所有前置兄弟节点的全部文本?
问题解决:拼接前置兄弟节点的全部文本内容
你的XML内容:
<?xml version="1.0"?> <foo> <a> first <b>x</b> <c>y</c> </a> <b>second</b> <bar>hey</bar> </foo>
你的XSL代码:
<?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:template match="/foo"> <xsl:apply-templates select="bar" /> </xsl:template> <xsl:template match="bar"> [<xsl:value-of select="preceding-sibling::text()"/>] </xsl:template> </xsl:stylesheet>
预期输出:
[first x y second]
问题分析
你当前代码里的preceding-sibling::text()只会选中bar节点前的直接文本节点,但你的前置兄弟是<a>和<b>这两个元素节点,它们的文本内容包含在自身及子节点中,所以这个选择器无法获取到目标内容。
解决方案
方案1:利用XSLT 2.0函数简洁实现
直接选择所有前置兄弟元素,提取它们包含的所有文本,清理多余空白后拼接:
<?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:template match="/foo"> <xsl:apply-templates select="bar" /> </xsl:template> <xsl:template match="bar"> [<xsl:value-of select="string-join(preceding-sibling::*//text()/normalize-space(), ' ')"/>] </xsl:template> </xsl:stylesheet>
方案2:递归拼接实现
如果需要严格用递归逻辑遍历前置兄弟节点并收集文本,可以用以下代码:
<?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:template match="/foo"> <xsl:apply-templates select="bar" /> </xsl:template> <xsl:template match="bar"> [<xsl:call-template name="collect-prev-text"> <xsl:with-param name="nodes" select="preceding-sibling::*"/> </xsl:call-template>] </xsl:template> <xsl:template name="collect-prev-text"> <xsl:param name="nodes"/> <xsl:param name="result" select="''"/> <xsl:choose> <xsl:when test="$nodes"> <xsl:variable name="current-text" select="normalize-space(string-join($nodes[1]//text(), ' '))"/> <xsl:call-template name="collect-prev-text"> <xsl:with-param name="nodes" select="$nodes[position() > 1]"/> <xsl:with-param name="result" select="concat($result, if ($result) then ' ' else '', $current-text)"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$result"/> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>
两种方案都能输出你预期的结果,前者借助XSLT 2.0的内置函数更简洁,后者完全通过递归逻辑实现文本拼接。
内容的提问来源于stack exchange,提问作者yegor256
相关产品推荐
相关产品推荐

