2013-02-12 76 views
0

我想要使用XSLT转换XML文档,但我有困难,因为有多个处理任务要在XML文档上执行。XSL复杂的转换与排序,添加和删除元素

这里是我要找的步骤来完成(对不起,我不知道这甚至有可能,或者我会尝试一些其他方式):

1 - 带/删除所有<group>元件和放/相邻<relation>元件移动到下一个元素<filter>

2 - 排序所有<filter>元件由两个元素中称为<relation><filtertype>

3 - 重组的所有<filter>个元件通过<relation>和通过<filtertype>通过添加回<group>元件和在<group>

换句话说拉动<relation>元件从所述第一<filter>元件的,我试图撤消所有现有的分组,排序所有的过滤器通过类似过滤类型和关系的元素,然后通过常见的filtertype和relation将过滤器重新组合,因为知道第一个组元素必须具有从其第一个过滤元素移动到组元素的关系元素

对不起,如果这很让人困惑,我的样品是低于(预先感谢)

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

所需的输出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> 

回答

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>