XSL通过排序,添加和删除元素进行复杂的转换

时间:2013-02-12 04:12:58

标签: xslt xslt-1.0

我正在尝试使用XSLT转换XML文档,但是我遇到了困难,因为要对XML文档执行多个处理任务。

以下是我要完成的步骤(抱歉,我不确定这是否可行,或者我是否需要尝试其他方法):

1 - 删除/移除所有<group>元素并将相邻的<relation>元素放入/移动到下一个<filter>元素

2 - 按调用<filter><relation>

中的两个元素对所有<filtertype>元素进行排序

3 - 通过添加<filter>元素并将<relation>元素拉出<filtertype>元素,按<group><relation>重新组合所有<filter>元素<group>

中的第一个<mainXML> <version major="1" minor="0" build="0" revision="0"/> <id>30</id> <set>Partial</set> <evaluate>True</evaluate> <group> <relation>And</relation> <filter> <filtertype>Search</filtertype> <attributeid>32900</attributeid> <action> <type>Numeric</type> <operator>GreaterThanOrEqualTo</operator> <value>01001</value> </action> </filter> <filter> <relation>Or</relation> <filtertype>Search</filtertype> <attributeid>32900</attributeid> <action> <type>Numeric</type> <operator>LessThanOrEqualTo</operator> <value>26886</value> </action> </filter> </group> <group> <relation>Or</relation> <filter> <filtertype>Search</filtertype> <attributeid>32900</attributeid> <action> <type>Numeric</type> <operator>GreaterThanOrEqualTo</operator> <value>30001</value> </action> </filter> </group> <group> <relation>And</relation> <filter> <filtertype>Grouping</filtertype> <action> <type>Mailing</type> <operator>DoNotBelongTo</operator> <groupingid>1133519</groupingid> </action> </filter> <filter> <relation>And</relation> <filtertype>Action</filtertype> <campaign> <campaignid>1509779</campaignid> </campaign> <action> <status>DoNot</status> <operator>Bill</operator> </action> <operator>AfterNHour</operator> <value>36</value> </filter> <filter> <relation>Or</relation> <filtertype>Action</filtertype> <campaign> <campaignid>1509779</campaignid> </campaign> <action> <status>DoNot</status> </action> <operator>AfterNHour</operator> <value>36</value> </filter> </group> </mainXML> 元素

换句话说,我试图撤消所有现有的分组,按照类似过滤器和关系对所有过滤器元素进行排序,然后通过常见的过滤类型和关系重新对过滤器进行分组,因为知道第一个组元素必须具有关系元素从它的第一个过滤元素移动到组元素

很抱歉,如果这令人困惑,我的样本就在下面(提前谢谢)

INPUT XML

<mainXML>
   <version major="1" minor="0" build="0" revision="0"/>
   <id>30</id>
   <set>Partial</set>
   <evaluate>True</evaluate>
   <group>
      <relation>And</relation>
      <filter>
         <filtertype>Action</filtertype>
         <campaign>
            <campaignid>1509779</campaignid>
         </campaign>
         <action>
            <status>DoNot</status>
            <operator>Bill</operator>
         </action>
         <operator>AfterNHour</operator>
         <value>36</value>
      </filter>
   </group>
   <group>
      <relation>Or</relation>
      <filter>
         <filtertype>Action</filtertype>
         <campaign>
            <campaignid>1509779</campaignid>
         </campaign>
         <action>
            <status>DoNot</status>
         </action>
         <operator>AfterNHour</operator>
         <value>36</value>
      </filter>
   </group>
   <group>
      <relation>And</relation>
      <filter>
         <filtertype>Grouping</filtertype>
         <action>
            <type>Mailing</type>
            <operator>DoNotBelongTo</operator>
            <groupingid>1133519</groupingid>
         </action>
      </filter>
   </group>
   <group>
      <relation>And</relation>
      <filter>
         <filtertype>Search</filtertype>
         <attributeid>32900</attributeid>
         <action>
            <type>Numeric</type>
            <operator>GreaterThanOrEqualTo</operator>
            <value>01001</value>
         </action>
      </filter>
   </group>
   <group>
      <relation>Or</relation>
      <filter>
         <filtertype>Search</filtertype>
         <attributeid>32900</attributeid>
         <action>
            <type>Numeric</type>
            <operator>LessThanOrEqualTo</operator>
            <value>26886</value>
         </action>
      </filter>
      <filter>
         <relation>Or</relation>
         <filtertype>Search</filtertype>
         <attributeid>32900</attributeid>
         <action>
            <type>Numeric</type>
            <operator>GreaterThanOrEqualTo</operator>
            <value>30001</value>
         </action>
      </filter>
   </group>
</mainXML>

所需的输出XML

{{1}}

1 个答案:

答案 0 :(得分:0)

此转化:

<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="kFilterRel" match="filter"
  use="concat(filtertype,'+'
              , (preceding-sibling::*[1]
                            [self::relation]
               | relation
                )[1]
              )"/>

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

 <xsl:template match="/*">
  <xsl:copy>
   <xsl:apply-templates select="@*|*[not(self::group)]"/>

   <xsl:apply-templates select=
     "*/filter
        [generate-id()
        =
         generate-id(key('kFilterRel',
                         concat(filtertype,'+'
                                , (preceding-sibling::*[1]
                                             [self::relation]
                                  | relation
                                  )[1]
                               )
                         )
                         [1]
                     )]">
    <xsl:sort select="filtertype"/>
    <xsl:sort select="(preceding-sibling::*[1]
                                   [self::relation]
                     | relation)[last()]"/>
   </xsl:apply-templates>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="filter">
  <group>
    <xsl:variable name="vRelation"
        select="(preceding-sibling::*[1][self::relation]
               | relation)[last()]"/>
    <xsl:copy-of select="$vRelation"/>
    <xsl:apply-templates mode="inGroup" select=
     "key('kFilterRel',
          concat(filtertype,'+'
                 , (preceding-sibling::relation[1]
                   | relation
                   )[last()]
                )
         )">
       <xsl:with-param name="pRel" select="$vRelation"/>
     </xsl:apply-templates>
  </group>
 </xsl:template>

 <xsl:template match="filter" mode="inGroup">
  <xsl:param name="pRel"/>

  <filter>
      <xsl:if test="not(relation) and position() > 1">
       <xsl:copy-of select="$pRel"/>
      </xsl:if>
      <xsl:apply-templates>
       <xsl:with-param name="pPos" select="position()"/>
      </xsl:apply-templates>
  </filter>
 </xsl:template>

 <xsl:template match="relation">
  <xsl:param name="pPos"/>

  <xsl:if test="$pPos > 1">
   <xsl:copy-of select="."/>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档时:

<mainXML>
   <version major="1" minor="0" build="0" revision="0"/>
   <id>30</id>
   <set>Partial</set>
   <evaluate>True</evaluate>
   <group>
      <relation>And</relation>
      <filter>
         <filtertype>Search</filtertype>
         <attributeid>32900</attributeid>
         <action>
            <type>Numeric</type>
            <operator>GreaterThanOrEqualTo</operator>
            <value>01001</value>
         </action>
      </filter>
      <filter>
         <relation>Or</relation>
         <filtertype>Search</filtertype>
         <attributeid>32900</attributeid>
         <action>
            <type>Numeric</type>
            <operator>LessThanOrEqualTo</operator>
            <value>26886</value>
         </action>
      </filter>
   </group>
   <group>
      <relation>Or</relation>
      <filter>
         <filtertype>Search</filtertype>
         <attributeid>32900</attributeid>
         <action>
            <type>Numeric</type>
            <operator>GreaterThanOrEqualTo</operator>
            <value>30001</value>
         </action>
      </filter>
   </group>
   <group>
      <relation>And</relation>
      <filter>
         <filtertype>Grouping</filtertype>
         <action>
            <type>Mailing</type>
            <operator>DoNotBelongTo</operator>
            <groupingid>1133519</groupingid>
         </action>
      </filter>
      <filter>
         <relation>And</relation>
         <filtertype>Action</filtertype>
         <campaign>
            <campaignid>1509779</campaignid>
         </campaign>
         <action>
            <status>DoNot</status>
            <operator>Bill</operator>
         </action>
         <operator>AfterNHour</operator>
         <value>36</value>
      </filter>
      <filter>
         <relation>Or</relation>
         <filtertype>Action</filtertype>
         <campaign>
            <campaignid>1509779</campaignid>
         </campaign>
         <action>
            <status>DoNot</status>
         </action>
         <operator>AfterNHour</operator>
         <value>36</value>
      </filter>
   </group>
</mainXML>

会产生想要的正确结果:

<mainXML>
   <version major="1" minor="0" build="0" revision="0"/>
   <id>30</id>
   <set>Partial</set>
   <evaluate>True</evaluate>
   <group>
      <relation>And</relation>
      <filter>
         <filtertype>Action</filtertype>
         <campaign>
            <campaignid>1509779</campaignid>
         </campaign>
         <action>
            <status>DoNot</status>
            <operator>Bill</operator>
         </action>
         <operator>AfterNHour</operator>
         <value>36</value>
      </filter>
   </group>
   <group>
      <relation>Or</relation>
      <filter>
         <filtertype>Action</filtertype>
         <campaign>
            <campaignid>1509779</campaignid>
         </campaign>
         <action>
            <status>DoNot</status>
         </action>
         <operator>AfterNHour</operator>
         <value>36</value>
      </filter>
   </group>
   <group>
      <relation>And</relation>
      <filter>
         <filtertype>Grouping</filtertype>
         <action>
            <type>Mailing</type>
            <operator>DoNotBelongTo</operator>
            <groupingid>1133519</groupingid>
         </action>
      </filter>
   </group>
   <group>
      <relation>And</relation>
      <filter>
         <filtertype>Search</filtertype>
         <attributeid>32900</attributeid>
         <action>
            <type>Numeric</type>
            <operator>GreaterThanOrEqualTo</operator>
            <value>01001</value>
         </action>
      </filter>
   </group>
   <group>
      <relation>Or</relation>
      <filter>
         <filtertype>Search</filtertype>
         <attributeid>32900</attributeid>
         <action>
            <type>Numeric</type>
            <operator>LessThanOrEqualTo</operator>
            <value>26886</value>
         </action>
      </filter>
      <filter>
         <relation>Or</relation>
         <filtertype>Search</filtertype>
         <attributeid>32900</attributeid>
         <action>
            <type>Numeric</type>
            <operator>GreaterThanOrEqualTo</operator>
            <value>30001</value>
         </action>
      </filter>
   </group>
</mainXML>