【问题标题】:XSLT: Output text of current node only and normalize whitespaceXSLT:仅输出当前节点的文本并规范化空格
【发布时间】:2012-12-06 23:21:53
【问题描述】:

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

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 的模板中使用 value-of 语句 (&lt;xsl:value-of select="./text()"/&gt;),但这根本没有返回任何文本。声明有问题吗?

我应该提到我已经使用以下内容覆盖了默认文本处理模板:&lt;xsl:template match="text()" /&gt;

谢谢

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    &lt;xsl:value-of select="./text()"/&gt; 返回“nothing”的原因是./text() 将返回一个由当前节点的所有直接子文本节点组成的节点setvalue-of 节点集是其 first 项的字符串值,在这种情况下,它是开始 &lt;B&gt; 和开始 &lt;C&gt; 标记之间的纯空格文本节点。这同样适用于下一个最明显的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>
    

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

    <d>text goes here more text here</d>
    

    【讨论】:

      【解决方案2】:

      我得到的最接近的是the child axis//B/child::text()

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

      【讨论】:

      • 嘿弗兰克!你能发布完整的工作代码吗?我尝试使用B/child::text()value-of select="normalize-space(.)" 以及其他一些组合,但似乎它对我不起作用..
      • 我也无法让它工作。完整的模板会很有帮助。谢谢
      【解决方案3】:

      试试这个代码!

      我没有使用&lt;copy-of&gt;,而是使用了模板覆盖!

      1. 我将 B 替换为 D..

      2. 我从输出中删除了&lt;C&gt;。这解决了一半的问题,所以&lt;C&gt;节点的文本不会出现在输出中。

      3. 我将 normalize-space 函数应用于所有文本节点 .. 所以多余的空白将被擦除:)

      代码如下:

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

      【讨论】:

        猜你喜欢
        • 2010-11-04
        • 1970-01-01
        • 2011-03-14
        • 1970-01-01
        • 1970-01-01
        • 2017-11-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多