2012-10-09 32 views
1

我有這樣的XML文件中刪除一些節點在一個XML文件:如何篩選和使用sxlt

<A> 
<B> 
    <elt>Add</elt> 
    ...there are some element here 
    <bId>2</bId> 
</B> 
<B> 
    <elt>Add</elt> 
    ...there are some element here 
    <bId>2</bId> 
</B> 
<B> 
    <elt>Add</elt> 
    ...there are some element here 
    <bId>2</bId> 
</B> 
<B> 
    <elt>can</elt> 
    ...there are some element here 
    <bId>3</bId> 
</B> 
<B> 
    <elt>can</elt> 
    ...there are some element here 
    <bId>3</bId> 
</B> 

我要檢查每個投標元素的值。如果這個值與之前或之後的元素相同,那麼我會將其他元素的區塊放入另一個區塊,例外元素bId這將在轉換後被拒絕。要通過你讓我的問題的理解,這裏是預期的輸出:

<CA> 
    <cplx> 
    <spRule> 
      <elt>Add</elt> 
      ... 
    </spRule> 
    <spRule> 
      <elt>Add</elt> 
      ... 
    </spRule> 
    <spRule> 
      <elt>Add</elt> 
      ... 
    </spRule> 
    </cplx> 
    <cplx> 
    <spRule> 
      <elt>can</elt> 
      ... 
    </spRule> 
    <spRule> 
      <elt>can</elt> 
      ... 
    </spRule> 
    </cplx> 
</CA> 

即使當在XML文件中的元素不被的的值排序投標,我想也得到了相同的預期輸出。 我嘗試使用這個XSL代碼:

<xsl:for-each select="bId" 
    <CA> 
    <cplx> 
    <xsl:choose> 
     <xsl:when test="node()[preceding::bId]"> 
     <xsl:copy> 
      <xsl:copy-of select="@*"/> 
      <xsl:apply-templates/> 
     </xsl:copy> 
     </xsl:when> 
    </cplx> 
    </CA> 
</xsl:for-each> 

,但它不走。請有人幫助我嗎? 感謝

+0

請詳細說明「時,在XML文件中的元素不受出價的價值排序,我想也得到了相同的預期輸出」,這聽起來就好像你對mply想要將具有某個「bId」值的所有元素進行分組,而前面的描述「如果此值與前面或後面的值相同」聽起來像是不同的要求,即只對相鄰元素進行分組。 –

+0

你好馬丁。我真的想將所有具有** bId **值的元素分組,即使這些元素沒有排序。例如,我們在xml中有** bId **的這些值:2,2,3,2,2 ...然後,我將首先將所有具有值** bId ** = 2的元素分組在一起,休息在另一個集團。 –

+0

請參閱我的答案中的第二個示例,您只需要對其進行分組,然後在XSLT 1.0中使用http://www.jenitennison.com/xslt/grouping/muenchian.xml完成​​分組。 –

回答

2

假設你的第一次描述具有相同bId值組相鄰的元素是你想要什麼的XSLT 1.0方法如下:

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

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

    <xsl:key name="k1" 
    match="B[bId = preceding-sibling::B[1]/bId]" 
    use="generate-id(preceding-sibling::B[not(bId = preceding-sibling::B[1]/bId)][1])"/> 

    <xsl:template match="A"> 
    <CA> 
     <xsl:apply-templates select="B[not(preceding-sibling::B[1]) or not(bId = preceding-sibling::B[1]/bId)]"/> 
    </CA> 
    </xsl:template> 

    <xsl:template match="B"> 
    <cplx> 
     <xsl:apply-templates select=". | key('k1', generate-id())" mode="sp"/> 
    </cplx> 
    </xsl:template> 

    <xsl:template match="B" mode="sp"> 
    <spRule> 
     <xsl:copy-of select="node()[not(self::bId)]"/> 
    </spRule> 
    </xsl:template> 

</xsl:stylesheet> 

如果你只是想將所有B元素具有相同bId值,則使用

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

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

    <xsl:key name="k1" 
    match="B" 
    use="bId"/> 

    <xsl:template match="A"> 
    <CA> 
     <xsl:apply-templates select="B[generate-id() = generate-id(key('k1', bId)[1])]"/> 
    </CA> 
    </xsl:template> 

    <xsl:template match="B"> 
    <cplx> 
     <xsl:apply-templates select="key('k1', bId)" mode="sp"/> 
    </cplx> 
    </xsl:template> 

    <xsl:template match="B" mode="sp"> 
    <spRule> 
     <xsl:copy-of select="node()[not(self::bId)]"/> 
    </spRule> 
    </xsl:template> 

</xsl:stylesheet> 
+0

@ Martin。非常感謝你的幫助。第一個樣本功能非常好,它可以做我想要的。 我試圖使用第二個樣本,但它不走。我得到這個結果爲:' ' 我不知道什麼是錯的這個樣品。請注意,結果是通過在上面給出的xml文件上應用xslt文件獲得的。感謝 –

+1

對不起,我糾正了第二個示例中的錯誤,它現在應該可以工作,並且比第一個示例更高效,更易於理解和維護(在XSLT 1.0中需要複雜的表達式來進行鄰接分組)。 –

+0

馬丁現在一切都好。再次感謝。 –