2010-07-05 113 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