2009-11-30 187 views
3

使用XSL我試圖把這個XML:問題的for-each

<book><title>This is a <b>great</b> book</title></book> 

這個XML:

<book>This is a <bold>great</bold> book</book> 

使用這個XSL:

<xsl:for-each select="book/title/*"> 
<xsl:choose> 
    <xsl:when test="name() = 'b'"> 
     <bold> 
      <xsl:value-of select="text()"/> 
     </bold> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:value-of select="text()"/> 
    </xsl:otherwise> 
</xsl:choose> 
</xsl:for-each> 

但我的輸出是這樣的:

<book><bold>great</bold></bold> 

任何人都可以解釋爲什麼<title>的根文本正在迷路?我相信我的for-each select語句可能需要修改,但我無法弄清楚應該是什麼。

請記住,由於樣式表的複雜性,我不能使用<xsl:template match>

謝謝!

+0

上面的XSL代碼是否在xsl:template中?如果是這樣,你可以添加代碼嗎? – 2009-11-30 17:19:37

+0

@帕維爾的回答是正確的。然而,你接近這個問題的方式看起來非常脆弱(即非常規並且很容易破壞你輸入文件改變的一分鐘)。你可能會考慮更詳細地描述問題。 – 2009-11-30 17:22:41

+0

對於一個寫得好的問題+1 + – 2009-11-30 17:23:26

回答

7

該XPath表達式:

book/title/* 

指 「所有子的book/title元件」。在你的情況,book/title有3個孩子節點

  • 文本節點:This is a
  • 元素節點:<b>...</b>
  • 文本節點:book

正如你所看到的,只有一個他們是一個元素,並被選中。如果你想獲得的所有子節點,文本和元素,使用這樣的:如果你想單獨獲得文本節點

book/title/node() 

,使用此:

book/title/text() 
1

雖然帕維爾Minaev提供的答案問題必須注意,這個問題證明了一個非常糟糕的方法(可能是由於缺乏經驗)到XSLT處理

的任務可以在一個優雅的方式,這表明XSLT的功率來完成:

當上述變換所提供的XML文檔應用:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes"/> 
    <xsl:template match="node()|@*"> 
     <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="title"> 
     <xsl:apply-templates/> 
    </xsl:template> 

    <xsl:template match="title/b"> 
     <bold> 
     <xsl:apply-templates/> 
     </bold> 
    </xsl:template> 
</xsl:stylesheet> 

通緝產生結果:

<book><title>This is a <b>great</b> book</title></book> 

這是基本的XSLT設計模式之一的一個很好的例子 - 覆蓋了身份規則重命名/展平

+0

他說:「記住我不能在問題中使用'',因爲我的樣式表很複雜」他試圖用模板做到這一點,並發現它與現有的規則衝突。如果是這樣,'mode'應該解決這個問題。 – 2009-11-30 18:11:41

+0

@ pavel-minaev大概他有poblems,但是這樣不好的代碼不應該被忽略,否則其他人會認爲這是一個很好的例子:) – 2009-11-30 20:53:07