2013-02-12 100 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>