2010-07-05 104 views
2

我需要轉換傳入的XML,以便我可以將「categorie」等於「2」的所有「item」提取出來,並將它們移入單獨的「records」節點,並將屬性初始化爲type = 「2」。通過XSLT提取和移動節點

下面是傳入XML的示例。

<datafeed> 
<records type="one"> 
    <purchases> 
    <items> 
      <item> 
       <categorie>one</categorie> 
       <intrant>String</intrant> 
      </item> 
      <item> 
       <categorie>two</categorie> 
       <intrant>String</intrant> 
      </item> 
      <item> 
       <categorie>one</categorie> 
       <intrant>String</intrant> 
      </item> 
      <item> 
       <categorie>two</categorie> 
       <intrant>String</intrant> 
      </item>       
     </items> 
    </purchases> 
    </records> 
<exchange/> 
<context/> 
<pilotage/> 
</datafeed> 

這是我想什麼:

<datafeed> 
<records type="one"> 
    <purchases> 
    <items> 
      <item> 
       <categorie>one</categorie> 
       <intrant>String</intrant> 
      </item> 
      <item> 
       <categorie>one</categorie> 
       <intrant>String</intrant> 
      </item>     
     </items> 
    </purchases> 
    </records> 
    <records type="two"> 
    <purchases> 
    <items> 
      <item> 
       <categorie>two</categorie> 
       <intrant>String</intrant> 
      </item> 
      <item> 
       <categorie>two</categorie> 
       <intrant>String</intrant> 
      </item>       
     </items> 
    </purchases> 
    </records> 
<exchange/> 
<context/> 
<pilotage/> 
</datafeed> 

我現在有兩個「紀錄」都初始化與它的預定義類型(總是一個或兩個)。提取的記錄被移動,因此從原始記錄中刪除。

感謝

+0

好問題(+1)。查看我的答案以獲得完整的解決方案並瞭解其中的一些重要觀點。 :) – 2010-07-05 16:40:15

回答

3

這種轉變

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:key name="kitemByCategory" match="item" 
    use="categorie"/> 

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

<xsl:template match="records"> 
    <xsl:call-template name="identity"/> 

    <xsl:variable name="vCat2Items" select= 
    "key('kitemByCategory', 'two')"/> 

    <xsl:if test="$vCat2Items"> 
    <records type="two"> 
     <purchases> 
      <items> 
      <xsl:copy-of select="$vCat2Items"/> 
      </items> 
     </purchases> 
    </records> 
    </xsl:if> 
</xsl:template> 

<xsl:template match="item[categorie = 'two']"/> 
</xsl:stylesheet> 

時所提供的XML文檔應用時產生想要的,正確的結果

<datafeed> 
    <records type="one"> 
     <purchases> 
     <items> 
      <item> 
       <categorie>one</categorie> 
       <intrant>String</intrant> 
      </item> 
      <item> 
       <categorie>one</categorie> 
       <intrant>String</intrant> 
      </item> 
     </items> 
     </purchases> 
    </records> 
    <records type="two"> 
     <purchases> 
     <items> 
      <item> 
       <categorie>two</categorie> 
       <intrant>String</intrant> 
      </item> 
      <item> 
       <categorie>two</categorie> 
       <intrant>String</intrant> 
      </item> 
     </items> 
     </purchases> 
    </records> 
    <exchange/> 
    <context/> 
    <pilotage/> 
</datafeed> 

待辦事項:

  1. 身份規則的使用和覆蓋

  2. 如何將項目類別「2」排除在之外,通過使用匹配它們的空白模板進行處理。

  3. 使用按鍵可以通過分類高效方便地定位項目。

+0

+1對你而言:-D – gef 2010-07-05 16:49:31

+0

非常好,謝謝你,作品很有魅力。 – Brian 2010-07-06 01:45:12

2

有了這個樣式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:key name="itemsBycategorie" match="item" use="categorie"/> 
    <xsl:template match="@*|node()"> 
     <xsl:param name="items"/> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"> 
       <xsl:with-param name="items" select="$items"/> 
      </xsl:apply-templates> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="records"> 
     <xsl:variable name="me" select="."/> 
     <xsl:for-each select="*/*/*[count(.|key('itemsBycategorie',categorie)[1])=1]"> 
      <records type="{categorie}"> 
       <xsl:apply-templates select="$me/node()"> 
        <xsl:with-param name="items" select="key('itemsBycategorie',categorie)"/> 
       </xsl:apply-templates> 
      </records> 
     </xsl:for-each> 
    </xsl:template> 
    <xsl:template match="items"> 
     <xsl:param name="items"/> 
     <xsl:copy> 
      <xsl:apply-templates select="$items"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

結果:

<datafeed> 
    <records type="one"> 
     <purchases> 
      <items> 
       <item> 
        <categorie>one</categorie> 
        <intrant>String</intrant> 
       </item> 
       <item> 
        <categorie>one</categorie> 
        <intrant>String</intrant> 
       </item> 
      </items> 
     </purchases> 
    </records> 
    <records type="two"> 
     <purchases> 
      <items> 
       <item> 
        <categorie>two</categorie> 
        <intrant>String</intrant> 
       </item> 
       <item> 
        <categorie>two</categorie> 
        <intrant>String</intrant> 
       </item> 
      </items> 
     </purchases> 
    </records> 
    <exchange></exchange> 
    <context></context> 
    <pilotage></pilotage> 
</datafeed> 

注意:分組Muenchian方法。和「窮人的隧道」params(Dimitre quot)。

+0

+1抽空做​​某人的功課;-) XSLT 1.0中的「tunnel params」 – gef 2010-07-05 16:46:36

+0

??? – 2010-07-05 16:52:57

+0

@Dimitre:你是對的!我應該把這些寫成小塊。 JA!但是,你還能稱這種模式嗎? – 2010-07-05 17:01:57