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

时间:2012-12-06 13:56:42

标签: xml xslt

我有一个带有以下结构的xml文档。我正在编写一个转换,我想从节点B输出文本,但忽略元素C和文本节点“title”。基本上我想提取文本“text goes here”并将其输出到一个新元素中,并将所有空格规范化。有人可以帮忙吗?以下是我到目前为止所尝试的内容。

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>

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

<d>

  Text goes here

</d>

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

我应该提一下,我使用以下内容覆盖了默认文本处理模板:<xsl:template match="text()" />

由于

3 个答案:

答案 0 :(得分:5)

<xsl:value-of select="./text()"/>返回“无”的原因是./text()将返回由当前节点的所有直接子文本节点组成的节点 set value-of节点集是其第一个项的字符串值,在本例中是开头<B>和开头{{1}之间的仅空白文本节点标签。这同样适用于次最明显的<C>,因为它再次将节点集转换为字符串(第一个节点值),然后规范化该字符串中的空间。相反,您需要单独规范化每个子文本节点:

normalize-space(text())

有一点需要注意的是,如果你有像

这样的输入
<d>
  <xsl:for-each select="text()">
    <xsl:value-of select="normalize-space(.)"/>
  </xsl:for-each>
</d>

然后你会得到

的输出
<A>
  <B>
    <C>title</C>
     text goes here
    <C>subtitle</C>
     more text here
  </B>
</A>

字幕两边的位之间没有空格。如果这是一个问题,你可以使用像

这样的技巧
<d>text goes heremore text here</d>

仅迭代那些包含非空白字符的文本节点子节点,并在除第一节之外的所有节点之前添加空格。

<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>

答案 1 :(得分:0)

我最接近的是选择the child axis//B/child::text()

child轴只返回当前上下文节点的直接子节点的文本节点,因此它与title节点不匹配。

答案 2 :(得分:0)

试试这段代码!

我没有使用<copy-of>,而是使用了模板覆盖!

  1. 我用D代替B ..

  2. 我从输出中删除<C>。这解决了问题的一半,因此<C>节点的文本没有出现在输出中。

  3. 我将规范化空间函数应用于所有文本节点..因此将删除额外的空格:)

  4. 这是代码:

      <?xml version="1.0" encoding="utf-8"?>
        <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
            <xsl:output method="xml" indent="yes"/>
          <xsl:template match="B">
            <d>
              <xsl:apply-templates select="node()"/>
            </d>
          </xsl:template>
    
          <xsl:template match="C"/>
    
          <xsl:template match="text()">
            <xsl:value-of select="normalize-space(.)"/>
          </xsl:template>
        </xsl:stylesheet>