2015-12-02 98 views
0

嗨,我有以下問題:如何檢測元素文本節點

我需要檢測,如果某些元素中有子文本節點,但不包括開頭和結尾的空格,回車,製表符和換行。任何「空白」空間都不計入文字。

我發現這個功能normalize-space()它部分適用於我。但是,如果文本節點放置在嵌套元素之後,則該函數不會找到它。例如:

<list> 
    <list-item/> 
    This is the text node 
</list> 

所以噹噹前上下文匹配<list>元素<xsl:value-of select="noramalize-space(text())"/>返回空字符串。但它應該返回「這是文本節點」是不是?

這裏是我的實驗上的代碼:

的.xml

<catalog> 
    <cd> 
     <empty-element> 
      <nested-empty-element/> 
     </empty-element> 
     <title>Empire Burlesque</title> 
     <list> 
      <list-itme> 
       <bullet>This is bullet</bullet> 
      </list-itme> 
     This is the text node 
     </list> 
     <artist>Bob Dylan</artist> 
    </cd> 
</catalog> 

的.xsl

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml"/> 
    <xsl:template match="/"> 
     <root> 
      <xsl:apply-templates select="/catalog/cd"/> 
     </root> 
    </xsl:template> 
    <xsl:template match="cd"> 
     <xsl:apply-templates select="*"/> 
    </xsl:template> 
    <xsl:template match="*"> 
     <xsl:if test="normalize-space(text())"> 
      <para> 
      <xsl:value-of select="."/> 
      </para> 
     </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 

改造後,我得到這樣的結果:

<root> 
    <para>Empire Burlesque</para> 
    <para>Bob Dylan</para> 
</root> 

,問題是:爲什麼我沒有得到這個結果?:

<root> 
    <para>Empire Burlesque</para> 
    <para>This is the text node</para> 
    <para>Bob Dylan</para> 
</root> 

爲什麼不處理list元素,它具有文本節點呢?

回答

1

這是因爲在list-itme之前的list下有一個空格的文本節點(我已經添加了一個註釋來顯示其中的內容,從技術上講,您將在下面的XML中有兩個空白節點,一個後)

<list>  <!-- Whitespace text node here --> 
     <list-itme> 
      <bullet>This is bullet</bullet> 
     </list-itme> 
    This is the text node 
    </list> 

如果要忽略這些空白節點,那麼你可以使用xsl:strip-space命令忽略它們

<xsl:strip-space elements="*" /> 

試試這個XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml"/> 
    <xsl:strip-space elements="*" /> 
    <xsl:template match="/"> 
     <root> 
      <xsl:apply-templates select="/catalog/cd"/> 
     </root> 
    </xsl:template> 
    <xsl:template match="cd"> 
     <xsl:apply-templates select="*"/> 
    </xsl:template> 
    <xsl:template match="*"> 
     <xsl:if test="normalize-space(text())"> 
      <para> 
      <xsl:value-of select="normalize-space(text())"/> 
      </para> 
     </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 

可替換地,相同的結果可通過測試,其中歸一化空間不爲空任何文本節點(您當前的表達歸一化所述第一文本節點)來實現

<xsl:if test="text()[normalize-space()]"> 

嘗試這個太

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml"/> 
    <xsl:template match="/"> 
     <root> 
      <xsl:apply-templates select="/catalog/cd"/> 
     </root> 
    </xsl:template> 

    <xsl:template match="cd"> 
     <xsl:apply-templates select="*"/> 
    </xsl:template> 

    <xsl:template match="*"> 
     <xsl:if test="text()[normalize-space()]"> 
      <para> 
      <xsl:value-of select="normalize-space(text()[normalize-space()])"/> 
      </para> 
     </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 
+0

謝謝@Tim C的快速回復。你的代碼適合我。有一件事對我來說很模糊。你能否請求解釋第二個例子中的[normalize-space()]是做什麼的?不應該'normalize-space()'去掉這些空間嗎? – Hairi

+1

如果您還沒有使用'xsl:strip-spaces',那麼如果您只是執行'normalize-space(text())',那麼這將標準化第一個文本節點的空間,在您的示例中這是空白文本節點。由於有多個文本節點,添加'[normalize-space()]'的條件將選擇非空的第一個文本節點。條件'[normalize-space()]'本身並不標準化空間。這只是一個選擇。 –