2017-01-08 23 views
1

我想要處理一些節點並再次處理這些節點的子集,特別是那些'n'-ancestors具有直接子節點'x'的節點。模式輸出中的XSLT模板包含應該在其他模式下匹配的元素

的XML,簡化儘可能:

<root> 
     <s> 
     </s> 
     <s> 
      <n> 
       <w a="Hello"/> 
       <n> 
        <x/> 
        <w a="he said"/> 
       </n> 
      </n> 
      <n> 
       <w a="how are you"/> 
      </n> 
     <n> 
     </n> 
     <n> 
      <w a="she answered"/> 
      <n> 
       <n> 
        <x/> 
        <w a="friendly"/> 
       </n> 
      </n> 
     </n> 
    </s> 
</root> 

正如我必須處理一些W¯¯節點兩次,我決定使用模式。我有兩種模式(可讀性命名爲'fromone','fromtwo')與'a-attribute'相匹配,並且還嘗試了僅使用一種模式的各種組合,添加一個沒有模式的空模板,但結果保持不變。

的XSLT的相關部分,也簡化了,原來的模板大多匹配條件(除了模式的那些):

<xsl:template match="root/s"> 
    <output> 
     <one> 
      <xsl:apply-templates select="descendant::w"/> 
     </one> 
     <x> 
      <xsl:apply-templates select="n"/> 
     </x> 
    </output> 
</xsl:template> 

<xsl:template match="n[x]"> 
    <xsl:apply-templates select="descendant::w/@a" mode="fromtwo"/> 
</xsl:template> 

<xsl:template match="w"> 
    <xsl:apply-templates select="@a" mode="fromone"/> 
</xsl:template> 

<xsl:template match="@a" mode="fromtwo"> 
    <fromtwo> 
     <xsl:value-of select="."/> 
    </fromtwo> 
</xsl:template> 

<xsl:template match="@a" mode="fromone"> 
    <fromone> 
     <xsl:value-of select="."/> 
    </fromone> 
</xsl:template> 

我希望輸出是這樣的:

<root> 
    <output> 
     <one> 
     <fromone>Hello</fromone> 
     <fromone>he said</fromone> 
     <fromone>how are you</fromone> 
     <fromone>she answered</fromone> 
     <fromone>friendly</fromone> 
     </one> 
     <x> 
     <fromtwo>he said</fromtwo> 
     <fromtwo>friendly</fromtwo> 
     </x> 
    </output> 
</root> 

但在實際的結果是,節點x包含我預計將只匹配來自其他模板呼叫到來元素,「fromone」:

<x> 
    <fromone>Hello</fromone> 
    <fromtwo>he said</fromtwo> 
    <fromone>how are you</fromone> 
    <fromone>she answered</fromone> 
    <fromtwo>friendly</fromtwo> 
    </x> 

由於這是我嘗試使用的所有XSLT處理器的結果,因此我假設我的模板結構中存在錯誤。即使在閱讀其他文章的模式問題之後,我也沒有更接近解決方案或在XSLT中發現我的錯誤。

我犯了什麼錯誤?

爲什麼結果有兩個模板的混合輸出,而不是隻顯示'fromtwo'的輸出?

回答

0

我做了什麼錯誤?

當你這樣做:

<x> 
     <xsl:apply-templates select="n"/> 
    </x> 

你申請模板所有n元素。不是由你的模板匹配n[x]匹配那些n元素將由確實默認built in template進行處理:

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

也就是說,它會遞歸應用模板的後代,直到它到達w元素 - 爲你做有一個自定義模板:

<xsl:template match="w"> 
    <xsl:apply-templates select="@a" mode="fromone"/> 
</xsl:template> 

你爲什麼不能做簡單:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

<xsl:template match="root"> 
    <output> 
     <one> 
      <xsl:apply-templates select=".//w"/> 
     </one> 
     <x> 
      <xsl:apply-templates select=".//n[x]//w" mode="fromtwo"/> 
     </x> 
    </output> 
</xsl:template> 

<xsl:template match="w"> 
    <fromone> 
     <xsl:value-of select="@a"/> 
    </fromone> 
</xsl:template> 

<xsl:template match="w" mode="fromtwo"> 
    <fromtwo> 
     <xsl:value-of select="@a"/> 
    </fromtwo> 
</xsl:template> 

</xsl:stylesheet> 
+0

所以我也可以通過創建一個空的w-匹配模板來解決這個問題? –

+0

是的,如果你從一開始就匹配模式。但選擇性應用既簡單又高效。 –

0

這是一個默認模板,可捕獲每個n -lelement,而不包含x-明度。如果在s -node的上下文中應用<xsl:apply-templates select="n"/>,則s的直接後繼將不會有x-子節點,因此您的模板n[x]將永遠不匹配。由於沒有其他模板匹配,所以默認模板到位並應用沒有模式的每個子節點。

所以我想補充的方案,採取一切n -nodes照顧無x -subelement:

<xsl:template match="n[not(x)]"> 
    <xsl:apply-templates select="n"/> 
</xsl:template> 

應用到你上面的示例,它產生以下輸出:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 

<output xmlns="http://www.w3.org/1999/xhtml"> 
    <one/> 
    <x/> 
</output> 
<output xmlns="http://www.w3.org/1999/xhtml"> 
    <one> 
     <fromone>Hello</fromone> 
     <fromone>he said</fromone> 
     <fromone>how are you</fromone> 
     <fromone>she answered</fromone> 
     <fromone>friendly</fromone> 
    </one> 
    <x> 
     <fromtwo>he said</fromtwo> 
     <fromtwo>friendly</fromtwo> 
    </x> 
</output> 
+0

這適用於我在這裏的簡化示例,但不適用於我的實際文件,輸出結合了所有的n [x]/w/@ a-contents,它給了我像他說友好

+0

編輯了答案我認爲它也應該適用於以前的版本。你可以發佈你的實際文件嗎? –