XSLT:仅输出当前节点的文本并规范空格

Jim*_*imS 2 xml xslt

我有一个具有以下结构的xml文档。我正在编写一个转换,其中我想从节点B输出文本,但忽略元素C和文本节点“ title”。本质上,我想提取文本“这里的文本”,并将其输出到一个标准化了所有空白的新元素中。有人可以帮忙吗?以下是到目前为止我尝试过的。

Input Doc
<A>
  <B>
    <C>title</C>
     text goes here
  </B>
</A>

Required output doc
<d>text goes here</d>


Solution A:
<xsl:template match="B">
  <d>       
    <xsl:copy-of select="./text()"/>                
  </d>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)

问题:元素之间的空白被保留了,所以我得到了这样的东西:

<d>

  Text goes here

</d>
Run Code Online (Sandbox Code Playgroud)

我也尝试使用value-of语句(<xsl:value-of select="./text()"/>在解决方案A的模板中),但这根本不返回任何文本。声明有问题吗?

我应该提到,我已经使用以下方法覆盖了默认的文本处理模板: <xsl:template match="text()" />

谢谢

Ian*_*rts 5

<xsl:value-of select="./text()"/>返回“ nothing” 的原因是./text()将返回一个由当前节点的所有直接子文本节点组成的节点。的value-of一节点集合是其的字符串值第一项,在这种情况下是所述开口之间的唯一的空白文本节点<B>和开口<C>标签。倒数第二个同样适用,normalize-space(text())因为这再次将节点集转换为字符串(第一个节点值),然后对该字符串中的空间进行归一化。相反,您需要分别标准化每个子文本节点:

<d>
  <xsl:for-each select="text()">
    <xsl:value-of select="normalize-space(.)"/>
  </xsl:for-each>
</d>
Run Code Online (Sandbox Code Playgroud)

关于这一点要注意的一件事是,如果您输入类似

<A>
  <B>
    <C>title</C>
     text goes here
    <C>subtitle</C>
     more text here
  </B>
</A>
Run Code Online (Sandbox Code Playgroud)

那么您将获得输出

<d>text goes heremore text here</d>
Run Code Online (Sandbox Code Playgroud)

字幕两侧的位之间没有空格。如果这是一个问题,您可以使用类似的技巧

<d>
  <xsl:for-each select="text()[normalize-space(.)]">
    <xsl:if test="position() &gt; 1"><xsl:text> </xsl:text></xsl:if>
    <xsl:value-of select="normalize-space(.)"/>
  </xsl:for-each>
</d>
Run Code Online (Sandbox Code Playgroud)

仅对包含非空格字符的那些文本节点子项进行迭代,并在除第一个以外的所有其他字符之前添加一个空格。

<d>text goes here more text here</d>
Run Code Online (Sandbox Code Playgroud)