通过XSLT提取和移动节点

时间:2010-07-05 15:26:22

标签: xslt

我需要转换传入的XML,以便我可以提取“itemsie”等于“two”的所有“item”,并将它们移动到一个单独的“records”节点中,其属性初始化为type =“two”。

以下是传入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>

我现在有两个“记录”都用它的预定义类型初始化(总是一两个)。提取的记录被移动,因此从原始记录中删除。

由于

2 个答案:

答案 0 :(得分: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. 如何通过使用匹配它们的空模板从处理中排除“两个”类别的项目

  3. 使用按键,按类别高效便捷地定位项目。

答案 1 :(得分: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分组方法。和“穷人的隧道”一样(Dimitre)。