0

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

以下是我希望完成的步骤(抱歉,我不确定这是否可能,或者我是否必须尝试其他方法):

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

2 - 通过调用和<filter>中的两个元素对所有元素进行排序<relation><filtertype>

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

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

抱歉,如果这令人困惑,我的示例如下(提前致谢)

输入 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>
4

1 回答 1

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>
于 2013-02-12T05:46:36.210 回答