2011-11-20 36 views
0

的輸出流量如何使一個XSLT轉換這樣的:打破在XSLT

<root> 
<element>This 
    <element>is</element> 
</element> 
<element>normal!</element> 
<element>This</element> 
<element>will 
    <special>break here</special> 
    <element>and 
    <element>also 
    <special>here!</special> 
    </element> 
    </element> 
</element> 
</root> 

進入這個:

<root> 
<content>This is normal! This will</content> 
<special>break here</special> 
<content>and also</content> 
<special>here!</special> 
</root> 

考慮<special>可以出現任何數量的時間和任何地方。我想我需要處理文件兩次才能做到這一點,但我需要立即執行。

編輯:只是一個澄清,它不是一個簡單的副本,內容也從一端轉換到另一端(爲什麼我認爲我需要兩個不同的轉換)。

EDIT2:這裏是我想要的算法:

1)去等待處理的所有元素,直到你找到一些特別的元素,把它全部到目前爲止裏面<content>

2)如果下一個元素是特殊的將其放在<specialContent>

3)如果有些事轉到步驟1

編輯3我改變了我的示例xml,使其更清晰。

+0

這取決於你在看什麼樣的轉換,這可能是可能的 – prusswan

回答

0

Dimitri的答案非常好,但由於生成的內容和非常深的模板層次結構,它會破壞我的XSLT中的一些東西。

這裏是解決方案,我最終使用:

首先我所有的正常處理,那麼我所說的後處理:

<xsl:variable name="content"> 
    <xsl:apply-templates /> 
</xsl:variable> 
<xsl:apply-templates select="msxsl:node-set($content)" mode="postProcess" /> 

在後處理它搜索任何東西,不是div的類屬性中帶有WideContent標記,並將相鄰的同胞分組在另一個div內,那些具有WideContent標記的同輩只是簡單地複製(但也可以以相同的方式組合)。

<xsl:template match="/*[not(self::xhtml:div[contains(@class,'WideContent')])][preceding-sibling::*[1][self::xhtml:div[contains(@class,'WideContent')]] or position()=1]" mode="postProcess"> 
    <div class="NormalContent"> 
    <xsl:call-template name="postProcessNormalContent" /> 
    </div> 
</xsl:template> 

<xsl:template name="postProcessNormalContent" match="/*[not(self::xhtml:div[contains(@class,'WideContent')])]" mode="postProcessNormalContent"> 
    <xsl:copy-of select="."/> 
    <xsl:apply-templates select="following-sibling::*[1]" mode="postProcessNormalContent" /> 
</xsl:template> 

<xsl:template match="xhtml:div[contains(@class,'WideContent')]" mode="postProcess"> 
    <xsl:copy-of select="."/> 
</xsl:template> 

<xsl:template match="node()" mode="postProcess" /> 
<xsl:template match="node()" mode="postProcessNormalContent" /> 

任何有關如何改進的建議將很樂意採取。

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

<xsl:template match="content//*[not(self::SpecialContent)]"> 
    <xsl:apply-templates/> 
</xsl:template> 

應該就足夠了。

+0

我的不好,實際上內容發生了各種轉換,所以它不是簡單的副本。 –

0
<?xml version="1.0" encoding="iso-8859-1"?> 
<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="root"> 
     <content> 
      <xsl:copy-of select=".//content/text()[following-sibling::node()[1][self::subcontent]]" /> 
      <xsl:copy-of select=".//subcontent/text()[following-sibling::node()[1][self::subsubcontent]]" />   
      <xsl:copy-of select=".//subsubcontent/text()[following-sibling::node()[1][self::SpecialContent]]" />    
     </content> 
     <xsl:for-each select=".//SpecialContent"> 
      <xsl:copy-of select="." /> 
     </xsl:for-each> 
     <content> 
      <xsl:copy-of select=".//subsubcontent/text()[preceding-sibling::node()[1][self::SpecialContent]]" /> 
      <xsl:copy-of select=".//subcontent/text()[preceding-sibling::node()[1][self::subsubcontent]]" /> 
      <xsl:copy-of select=".//content/text()[preceding-sibling::node()[1][self::subcontent]]" /> 
     </content> 
    </xsl:template> 
    <xsl:template match="text()" /> 
</xsl:stylesheet> 

不是很漂亮,但應與其他轉換工作,如果任何

+0

不完全如我所說,Special可以在任何地方和任何次數。 –

+0

好吧我看到您的修改後的問題,因此我的答案不再適用 – prusswan

0

我認爲你可以做到這一點的一個方法是把所有的元素*元素由第一**特殊元素是或者後代或以下元件,

<xsl:key name="content" 
    match="element" 
    use="generate-id((descendant::special|following::special)[1])" /> 

然後可以通過

0123的文檔中的所有 調校妥當元件匹配開始
<xsl:apply-templates select="//special" /> 

併爲每個特殊元素,你匹配,然後你可以組在一起的所有相關元素有這個當前元素作爲其第一個decendant或以下元素的元素。

<content> 
    <xsl:apply-templates select="key('content', generate-id())" /> 
</content> 

因此,考慮到下面的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:key name="content" 
     match="element" 
     use="generate-id((descendant::special|following::special)[1])" /> 

    <xsl:template match="/root"> 
     <xsl:copy> 
     <xsl:apply-templates select="//special" /> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="special"> 
     <content> 
     <xsl:apply-templates select="key('content', generate-id())" /> 
     </content> 
     <xsl:copy-of select="." /> 
    </xsl:template> 

    <xsl:template match="element"> 
     <xsl:value-of select="normalize-space(text())" /><xsl:text> </xsl:text> 
    </xsl:template> 
</xsl:stylesheet> 

當適用於您的示例XML,下面是輸出

<root> 
    <content>This is normal! This will </content> 
    <special>break here</special> 
    <content>and also </content> 
    <special>here!</special> 
</root> 

(請注意,在每個內容的後面加上一個空格標籤,但如果需要,我可以輕鬆調整XSLT以將其刪除)。

2

看來,在這個時候所有現有的答案無意中發現這個XML文檔上:

<root> 
    <element>This 
     <element>is</element></element> 
    <element>normal!</element> 
    <element>This</element> 
    <element>will 
     <special>break here</special> 
     <element>and  
      <element>also  
       <special>here!</special> 
      </element> 
     </element> 
     <element>But not here</element> 
    </element> 
</root> 

下面是正確處理它轉換:

<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="content" match="element" 
    use="generate-id((ancestor::special|preceding::special)[last()])"/> 

<xsl:template match="/*"> 
    <xsl:copy> 
    <content> 
     <xsl:apply-templates select="key('content', '')"/> 
    </content> 
    <xsl:apply-templates select="//special" /> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="special"> 
    <xsl:copy-of select="." /> 
    <content> 
    <xsl:apply-templates select= 
     "key('content', generate-id())" /> 
    </content> 
</xsl:template> 

<xsl:template match="element"> 
    <xsl:value-of select="normalize-space(text())" /> 
    <xsl:text> </xsl:text> 
</xsl:template> 
</xsl:stylesheet> 

當應用在上面的XML文檔中,生成了想要的正確結果

<root> 
    <content>This is normal! This will </content> 
    <special>break here</special> 
    <content>and also </content> 
    <special>here!</special> 
    <content>But not here </content> 
</root> 
+0

這真的會起作用,但我認爲我的問題只是出了問題,有太多的內容正在轉變以跟蹤所有內容,我也得到了一些自動生成的如果我使用這種處理,會丟失內容。我想解決方案是另一個XSLT(流水線)或創建一個變量的內容,並使用node-set()將它傳遞給另一個模板... –

+0

@LuizBorges:是的,這個處理總是可以在一個單獨的過程中完成。如果您在如何執行此操作時遇到問題,請搜索xslt標籤 - 有幾個問題可以解答如何進行多通道處理。 –

+0

@LuizBorges:查看兩遍轉換的示例:http://stackoverflow.com/questions/3678353/apply-xslt-transform-to-an-already-transformed-xml/3678779#3678779 –