我试图使用XSLT转换XML文档,但遇到了困难,因为要对XML文档执行多个处理任务。
以下是我想要完成的步骤(对不起,我不确定这是否可能,或者我是否必须尝试其他方法):
1-剥离/移除所有<group>
元素,并将相邻的<relation>
元素放入/移动到下一个<filter>
元素中
2-根据称为<relation>
和<filtertype>
的两个元素对所有<filter>
元素进行排序
3-通过将<group>
元素相加并从<group>
中的第一个<filter>
元素中取出<relation>
元素,将所有<filter>
元素按<relation>
和<filtertype>
重新分组
换言之,我正试图撤消所有现有的分组,根据类似的filtertype和relation对所有过滤元素进行排序,然后根据公共的filtertyype和relation重新分组过滤器,因为我知道第一个组元素必须有一个从其第一个过滤元素移到组元素中的relation元素
很抱歉,如果这让人困惑,我的样品在下面(提前感谢)
输入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>
此转换:
<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>