2011-01-13 63 views
4

我想只選擇包含文本節點的節點。但是,當我測試text()父節點包含子節點與文本也返回。我試圖通過 字符串長度(),但父節點返回一個字符串的長度大於0XSLT僅選擇帶有循環中文本的節點

在這種情況下,檢查我想只選擇

SendDate 
FirstName 
LastName 
Company 
Street 
City 
State 
Zip 

感謝

XML

<BusinessLetter> 
    <Head> 
     <SendDate>November 29, 2005</SendDate> 
     <Recipient> 
      <Name Title="Mr."> 
       <FirstName>Joshua</FirstName> 
       <LastName>Lockwood</LastName> 
      </Name> 
      <Company>Lockwood &amp; Lockwood</Company> 
      <Address> 
       <Street>291 Broadway Ave.</Street> 
       <City>New York</City> 
       <State>NY</State> 
       <Zip>10007</Zip> 
       <Country>United States</Country> 
      </Address> 
     </Recipient> 
    </Head> 
</BusinessLetter> 

XSL

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="html" indent="yes"/> 
    <xsl:template match="/"> 
     <xsl:for-each select="//*[text()]"> 
      <xsl:if test="text()"> 
        <Match> 
         <xsl:value-of select="name()"/>: 
         <xsl:value-of select="string-length(text())"/> 
        </Match> 
        <br /> 
      </xsl:if> 
     </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

輸出

BusinessLetter: 2 
Head: 3 
SendDate: 17 
Recipient: 4 
Name: 5 
FirstName:6 
LastName:8 
Company:19 
Address:5 
Street:17 
City:8 
State:2 
Zip:5 
Country:13 
+0

好問題,+1。請參閱我的回答以獲得解釋,以及對代碼的簡單,最不引人注意的修復。 – 2011-01-13 16:46:12

回答

2

好問題。我花了幾天尋找答案。

<xsl:value-of select="string-length(normalize-space(text()[1]))" /> 
2

此問題是由僅考慮白色空間的文本節點引起的。

解決方案

包含這一全球(最好的地方是之前任何<xsl:template>)指令

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

這指示XSLT處理器剝離工作的空白,只有文字XML文檔中任何(*)元素的節點子節點。

所以,你的固定變換現在是

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="html" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="/"> 
     <xsl:for-each select="//*[text()]"> 
      <xsl:if test="text()"> 
       <Match> 
        <xsl:value-of select="name()"/>:       
        <xsl:value-of select="string-length(text())"/> 
       </Match> 
       <br /> 
      </xsl:if> 
     </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

當所提供的XML文檔應用:

<BusinessLetter> 
    <Head> 
     <SendDate>November 29, 2005</SendDate> 
     <Recipient> 
      <Name Title="Mr."> 
       <FirstName>Joshua</FirstName> 
       <LastName>Lockwood</LastName> 
      </Name> 
      <Company>Lockwood &amp; Lockwood</Company> 
      <Address> 
       <Street>291 Broadway Ave.</Street> 
       <City>New York</City> 
       <State>NY</State> 
       <Zip>10007</Zip> 
       <Country>United States</Country> 
      </Address> 
     </Recipient> 
    </Head> 
</BusinessLetter> 

想要的,正確的結果產生

<Match>SendDate:       
        17 
</Match><br><Match>FirstName:       
        6 
</Match><br><Match>LastName:       
        8 
</Match><br><Match>Company:       
        19 
</Match><br><Match>Street:       
        17 
</Match><br><Match>City:       
        8 
</Match><br><Match>State:       
        2 
</Match><br><Match>Zip:       
        5 
</Match><br><Match>Country:       
        13 
</Match><br> 
+0

+1好答案。一般情況下都是正確的選擇,除非只有空白的文本節點有意義:通常處理混合內容,特別是處理XHTML。 – 2011-01-13 20:24:34

+0

@Alejandro:是的,但在這種情況下,文檔不是XHTML。 – 2011-01-14 03:13:55

3

您是經驗與白的空間只有文本節點一個問題...

解決方案保留空白僅文本節點(更好的處理時(X)HTML):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="*[text()[normalize-space()]]"> 
     <Match> 
      <xsl:value-of select="concat(name(), 
             ' : ', 
             string-length(normalize-space()))"/> 
     </Match> 
     <br /> 
    </xsl:template> 
</xsl:stylesheet> 

輸出:

<Match>SendDate : 17</Match> 
<br /> 
<Match>FirstName : 6</Match> 
<br /> 
<Match>LastName : 8</Match> 
<br /> 
<Match>Company : 19</Match> 
<br /> 
<Match>Street : 17</Match> 
<br /> 
<Match>City : 8</Match> 
<br /> 
<Match>State : 2</Match> 
<br /> 
<Match>Zip : 5</Match> 
<br /> 
<Match>Country : 13</Match> 
<br />