如何递归连接所有先前兄弟的所有文本?

问题描述 投票:0回答:2

这是我的 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="1.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]

但是,它并没有按预期工作。简而言之,我有兴趣(递归地)连接当前节点的所有兄弟节点的所有文本。

xslt xslt-2.0
2个回答
0
投票

您选择的兄弟节点本身不是文本节点,因此您不能在

text()
轴之后立即使用
preceding-sibiling::
节点测试。相反,您必须选择这些兄弟姐妹的文本后裔

您可能还想省略纯空白文本,例如

<b>
<c>
元素之间的文本:

[<xsl:for-each select="preceding-sibling::*//text()
  [normalize-space(.)!='']"> <!-- filter out whitespace-only -->
  <xsl:if test="position()>1">
    <xsl:text> </xsl:text>
  </xsl:if>
  <xsl:value-of select="normalize-space(.)"/>
</xsl:for-each>]

如果您希望文本以一个空格分隔,则必须显式插入该文本并使用

normalize-space
函数删除尾随和前导空格。

(XSLT 1.0)


0
投票

你可以使用这样的东西:

<?xml version="1.0"?>
<xsl:stylesheet 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  
  <xsl:output method="text"/>
  
  <xsl:template match="/foo">
    <xsl:apply-templates select="bar" />
  </xsl:template>
  
  <xsl:template match="bar">
    <xsl:text>[</xsl:text>
    <xsl:for-each select="preceding-sibling::*">
      <xsl:value-of select="normalize-space(text())"/>
      <xsl:value-of select="' '"/>
      <xsl:apply-templates select="*" mode ="r"/>
    </xsl:for-each>
    <xsl:text>]</xsl:text>
  </xsl:template>
  
  <xsl:template match="*" mode="r">
    <xsl:value-of select="normalize-space(text())"/>
    <xsl:value-of select="' '"/>
    <xsl:apply-templates select="*" mode="r"/>
  </xsl:template>
  
</xsl:stylesheet>

看到它在这里工作:https://xsltfiddle.liberty-development.net/94rjSWw

© www.soinside.com 2019 - 2024. All rights reserved.