开发者

extract and move nodes via XSLT

开发者 https://www.devze.com 2023-01-05 14:34 出处:网络
I need to transform the incoming XML so that I can extract all \"item\" with \"categorie\" is equal \"two\" and move these into a separate \"records\" node with an attribute initialized as type=\"two\

I need to transform the incoming XML so that I can extract all "item" with "categorie" is equal "two" and move these into a separate "records" node with an attribute initialized as type="two".

Here's a sample of the incoming 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>

Here's what I would like:

<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>

I now have two "records" both initialize with it's predefined type (always one or two). The records that were extracted, were moved, hence deleted from the original record.

Thanks


This transformation:

<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>

when applied on the provided XML document, produces the wanted, correct result:

<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>

Do note:

  1. The use and overriding of the identity rule.

  2. How items of categorie "two" are excluded from processing by using an empty template matching them.

  3. The use of keys for efficient and convenient locationg of items by categorie.


With this stylesheet:

<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>

Result:

<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>

Note: Muenchian Method of grouping. And "poor man's tunnel" params (Dimitre quot).

0

精彩评论

暂无评论...
验证码 换一张
取 消