2013-05-14 76 views
2

我很確定這個答案是否定的,但由於唯一的選擇是我認爲不雅的代碼,我想我會拋出這個,看看我是否失去了一些東西,同時希望這沒有被問到。是否有可能使xsl:template對不使用xsl:param的push-from節點敏感?

定源XML:

<root> 
    <p>Hello world</p> 
    <move elem="content" item="test"/> 
    <p>Another text node.</p> 
    <content item="test">I can't <b>figure</b> this out.</content> 
</root> 

我想這樣的結果:

<root> 
    <block>Hello world</block> 
    <newContent>I can't <hmmm>figure</hmmm> this out.</newContent> 
    <block>Another text node.</block> 
</root> 

一個普通的語言描述:

  1. 更換<移動.../>與結果處理 名稱與move的@elem attr匹配的元素ibute並且其@item 配招的@item屬性(例如,在這種情況下,元素的含量[<內容>]被加工成<b>由<HMM>取代)。
  2. 防止從 步驟1中的元素被寫入到結果樹在其原始文檔順序

的問題是輸入XML文件將是複雜得多和變量。樣式表是我正在擴展的第三方轉換。爲了使用基於模式的解決方案,我必須複製的模板在尺寸上非常重要,對我來說這似乎不夠雅緻。我知道,例如,這會工作:

<xsl:template match="b"> 
    <hmmm> 
     <xsl:apply-templates/> 
    </hmmm> 
</xsl:template> 
<xsl:template match="p"> 
    <block> 
     <xsl:apply-templates/> 
    </block> 
</xsl:template> 
<xsl:template match="move"> 
    <xsl:variable name="elem" select="@elem"/> 
    <xsl:variable name="item" select="@item"/> 
    <xsl:apply-templates select="//*[name()=$elem and @item=$item]" mode="copy-and-process"/> 
</xsl:template> 
<xsl:template match="content"/> 
<xsl:template match="content" mode="copy-and-process"> 
      <newContent><xsl:apply-templates/></newContent> 
</xsl:template> 

我想這樣做是有<的xsl:模板>匹配「內容」是什麼節點推到它敏感。所以,我可以有一個< xsl:template match =「content」/ >,它只在被推送的節點是<根>而不是<移動>時才被執行(並且因此它的匹配節點和子節點被抑制)。這樣做的好處是,如果更新了第三方樣式表的相關模板,我不必擔心更新處理<節點的樣式表的副本。我很確定這是不可能的,但我認爲這值得問。

回答

1

根本就

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:key name="kMover" match="move" use="concat(@elem,'+',@item)"/> 

<xsl:key name="kToMove" match="*" use="concat(name(),'+',@item)"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="move"> 
    <newContent> 
     <xsl:apply-templates mode="move" select= 
     "key('kToMove', concat(@elem,'+',@item))/node()"/> 
    </newContent> 
</xsl:template> 

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

<xsl:template match="b" mode="move"> 
    <hmmm><xsl:apply-templates/></hmmm> 
</xsl:template> 
<xsl:template match="*[key('kMover', concat(name(),'+',@item))]"/> 
</xsl:stylesheet> 

當這種變換所提供的XML文檔應用:

<root> 
    <p>Hello world</p> 
    <move elem="content" item="test"/> 
    <p>Another text node.</p> 
    <content item="test">I can't <b>figure</b> this out.</content> 
</root> 

想要的,正確的結果產生:

<root> 
    <block>Hello world</block> 
    <newContent>I can't <hmmm>figure</hmmm> this out.</newContent> 
    <block>Another text node.</block> 
</root> 
+0

對xsl:key沒有正確的理解會再次讓我陷入困境。謝謝! – user2379780 2013-05-14 02:17:51

+0

@ user2379780,不客氣。 – 2013-05-14 02:19:14

+0

我相信這可以通過以下方式簡化:(a)完全移除「移動」模式,(b)將最後一個模板更改爲僅僅是'(這樣就不需要' kMover'鍵),是嗎? – ABach 2013-05-14 02:47:14

相關問題