Dear all,
in order to let you able to reproduce the results I'm having, I'll copy here an example of original XML file and the script I'm trying to correct.
But before that, here's a short description of what is the purpose of the script:
a) replace one "function" tag which is child of one "step/lhs" tag
b) replace, if it exists, the same "function" tag which is descendant of the same "step" but child of "rhs" (namely, "step/rhs")
I added comments also in the script which helps understending the purpose of the script. One result file has to be generated for each occurence of "function" tag that has to be removed. And the rest of the original file must stay as it was at the beginning.
Here's the original file:
Code:
<?xml version="1.0" encoding="ISO-8859-1"?>
<original>
<rules>
<step name="step_001">
<lhs>
<facts>
<function name="function1">
<parameters>
<variable name="Var1"/>
</parameters>
</function>
<not>
<function name="function2">
<parameters>
<variable name="Var1"/>
</parameters>
</function>
</not>
<function name="function3">
<parameters>
<variable name="Var2"/>
<variable name="Var3"/>
<number value="1"/>
</parameters>
</function>
</facts>
</lhs>
<rhs>
<facts>
<function name="function4">
<parameters>
<constant name="c1"/>
<constant name="c2"/>
</parameters>
</function>
<function name="function4">
<parameters>
<constant name="c3"/>
<constant name="c4"/>
</parameters>
</function>
<function name="function5">
<parameters>
<variable name="Var3"/>
<variable name="Var3_1"/>
</parameters>
</function>
<function name="function5">
<parameters>
<variable name="Var3"/>
<variable name="Var3_2"/>
</parameters>
</function>
<function name="function1">
<parameters>
<variable name="Var1"/>
</parameters>
</function>
<function name="function3">
<parameters>
<variable name="Var2"/>
<variable name="Var3"/>
<number value="1"/>
</parameters>
</function>
<function name="function6">
<parameters>
<constant name="c5"/>
<variable name="Var3_1"/>
<number value="1"/>
<variable name="Var1"/>
<constant name="c6"/>
<constant name="c1"/>
<constant name="c2"/>
<constant name="c7"/>
</parameters>
</function>
<function name="function6">
<parameters>
<constant name="c8"/>
<variable name="Var3_2"/>
<number value="1"/>
<constant name="c9"/>
<constant name="c10"/>
<constant name="c3"/>
<constant name="c2"/>
<constant name="c11"/>
</parameters>
</function>
</facts>
</rhs>
</step>
<step name="step_002">
<lhs>
<facts>
<function name="function2">
<parameters>
<variable name="Var4"/>
</parameters>
</function>
<not>
<function name="function2">
<parameters>
<variable name="Var2"/>
</parameters>
</function>
</not>
<function name="function6">
<parameters>
<variable name="Var2"/>
<variable name="Var3"/>
<number value="1"/>
<variable name="Var4"/>
<variable name="Var5"/>
<variable name="Var6"/>
<variable name="Var7"/>
<variable name="Var8"/>
</parameters>
</function>
</facts>
</lhs>
<rhs>
<facts>
<function name="function5">
<parameters>
<variable name="Var3"/>
<variable name="Var3_3"/>
</parameters>
</function>
<function name="function5">
<parameters>
<variable name="Var3"/>
<variable name="Var3_4"/>
</parameters>
</function>
<function name="function7">
<parameters>
<function name="function13">
<parameters>
<variable name="Var5"/>
<function name="function13">
<parameters>
<variable name="Var8_1"/>
<variable name="Var6"/>
</parameters>
</function>
</parameters>
</function>
<constant name="c12"/>
</parameters>
</function>
<function name="function2">
<parameters>
<variable name="Var4"/>
</parameters>
</function>
<function name="function8">
<parameters>
<variable name="Var5"/>
</parameters>
</function>
<function name="function1">
<parameters>
<variable name="Var8_1"/>
</parameters>
</function>
<function name="function9">
<parameters>
<variable name="Var4"/>
<variable name="Var3_3"/>
<number value="1"/>
<variable name="Var5"/>
<variable name="Var8_1"/>
<variable name="Var7"/>
<constant name="c13"/>
<constant name="c14"/>
<constant name="c15"/>
</parameters>
</function>
<function name="function10">
<parameters>
<constant name="c13"/>
<variable name="Var3_4"/>
<number value="1"/>
<variable name="Var4"/>
<constant name="c16"/>
<constant name="c17"/>
<constant name="c_Var6_1"/>
<constant name="c_Var7_1"/>
<constant name="c18"/>
<constant name="c19"/>
<constant name="c20"/>
<constant name="c21"/>
</parameters>
</function>
<function name="function6">
<parameters>
<variable name="Var2"/>
<variable name="Var3"/>
<number value="8"/>
<variable name="Var4"/>
<variable name="Var5"/>
<variable name="Var6"/>
<variable name="Var7"/>
<variable name="Var8_1"/>
</parameters>
</function>
</facts>
</rhs>
</step>
<step name="step_003">
<lhs>
<facts>
<not>
<function name="function2">
<parameters>
<variable name="Var2"/>
</parameters>
</function>
</not>
<not>
<function name="function2">
<parameters>
<variable name="Var4"/>
</parameters>
</function>
</not>
<function name="function6">
<parameters>
<variable name="Var2"/>
<variable name="Var3"/>
<number value="1"/>
<variable name="Var4"/>
<variable name="Var5"/>
<variable name="Var6"/>
<variable name="Var7"/>
<variable name="Var8"/>
</parameters>
</function>
</facts>
</lhs>
<rhs>
<facts>
<function name="function5">
<parameters>
<variable name="Var3"/>
<variable name="Var3_3"/>
</parameters>
</function>
<function name="function5">
<parameters>
<variable name="Var3"/>
<variable name="Var3_4"/>
</parameters>
</function>
<function name="function7">
<parameters>
<function name="function13">
<parameters>
<variable name="Var5"/>
<function name="function13">
<parameters>
<variable name="Var8_2"/>
<variable name="Var6"/>
</parameters>
</function>
</parameters>
</function>
<constant name="c12"/>
</parameters>
</function>
<function name="function9">
<parameters>
<variable name="Var4"/>
<variable name="Var3_3"/>
<number value="1"/>
<variable name="Var5"/>
<variable name="Var8_2"/>
<variable name="Var7"/>
<constant name="c13"/>
<constant name="c14"/>
<constant name="c15"/>
</parameters>
</function>
<function name="function10">
<parameters>
<constant name="c13"/>
<variable name="Var3_4"/>
<number value="1"/>
<variable name="Var4"/>
<constant name="c16"/>
<constant name="c17"/>
<constant name="c_Var6_1"/>
<constant name="c_Var7_1"/>
<constant name="c18"/>
<constant name="c19"/>
<constant name="c20"/>
<constant name="c21"/>
</parameters>
</function>
<function name="function6">
<parameters>
<variable name="Var2"/>
<variable name="Var3"/>
<number value="1"/>
<variable name="Var4"/>
<variable name="Var5"/>
<variable name="Var6"/>
<variable name="Var7"/>
<variable name="Var8"/>
</parameters>
</function>
</facts>
</rhs>
</step>
<step name="step_004">
<lhs>
<facts>
<function name="function5">
<parameters>
<variable name="Var3"/>
<variable name="Var3"/>
</parameters>
</function>
<not>
<function name="function2">
<parameters>
<variable name="Var2"/>
</parameters>
</function>
</not>
<function name="function9">
<parameters>
<variable name="Var2"/>
<variable name="Var3"/>
<number value="1"/>
<variable name="Var5"/>
<variable name="Var8"/>
<variable name="Var7"/>
<variable name="c13"/>
<variable name="Var9"/>
<variable name="Var10"/>
</parameters>
</function>
</facts>
</lhs>
<rhs>
<facts>
<function name="function5">
<parameters>
<variable name="Var3"/>
<variable name="Var3_5"/>
</parameters>
</function>
<function name="function7">
<parameters>
<variable name="Var2"/>
<function name="function14">
<parameters>
<variable name="Var3"/>
</parameters>
</function>
</parameters>
</function>
<function name="function7">
<parameters>
<variable name="c13"/>
<function name="function14">
<parameters>
<variable name="Var3"/>
</parameters>
</function>
</parameters>
</function>
<function name="function1">
<parameters>
<function name="function15">
<parameters>
<function name="function16">
<parameters>
<variable name="c13"/>
</parameters>
</function>
<function name="function13">
<parameters>
<constant name="c22"/>
<function name="function13">
<parameters>
<variable name="Var2"/>
<function name="function13">
<parameters>
<variable name="Var5"/>
<variable name="Var8"/>
</parameters>
</function>
</parameters>
</function>
</parameters>
</function>
</parameters>
</function>
</parameters>
</function>
<function name="function11">
<parameters>
<variable name="Var8"/>
<constant name="c_Var8"/>
<function name="function14">
<parameters>
<variable name="Var3"/>
</parameters>
</function>
</parameters>
</function>
<function name="function9">
<parameters>
<variable name="Var2"/>
<variable name="Var3"/>
<number value="2"/>
<variable name="Var5"/>
<variable name="Var8"/>
<variable name="Var7"/>
<variable name="c13"/>
<variable name="Var9"/>
<variable name="Var10"/>
</parameters>
</function>
</facts>
</rhs>
</step>
<step name="step_005">
<lhs>
<facts>
<function name="function1">
<parameters>
<function name="function15">
<parameters>
<function name="function16">
<parameters>
<variable name="Var2"/>
</parameters>
</function>
<function name="function17">
<parameters>
<function name="function18">
<parameters>
<function name="function19">
<parameters>
<constant name="c13"/>
</parameters>
</function>
</parameters>
</function>
<function name="function13">
<parameters>
<constant name="function20"/>
<function name="function13">
<parameters>
<variable name="Var2"/>
<variable name="Var9_1"/>
</parameters>
</function>
</parameters>
</function>
</parameters>
</function>
</parameters>
</function>
</parameters>
</function>
<function name="function9">
<parameters>
<variable name="Var2"/>
<variable name="Var3"/>
<number value="2"/>
<variable name="Var5"/>
<variable name="Var8"/>
<variable name="Var7"/>
<variable name="c13"/>
<variable name="Var9"/>
<variable name="Var10"/>
</parameters>
</function>
</facts>
</lhs>
<rhs>
<facts>
<function name="function1">
<parameters>
<function name="function15">
<parameters>
<function name="function16">
<parameters>
<constant name="c13"/>
</parameters>
</function>
<function name="function17">
<parameters>
<function name="function18">
<parameters>
<function name="function19">
<parameters>
<variable name="Var2"/>
</parameters>
</function>
</parameters>
</function>
<function name="function13">
<parameters>
<constant name="function20"/>
<function name="function13">
<parameters>
<constant name="c13"/>
<function name="function13">
<parameters>
<variable name="Var9_1"/>
<variable name="Var7"/>
</parameters>
</function>
</parameters>
</function>
</parameters>
</function>
</parameters>
</function>
</parameters>
</function>
</parameters>
</function>
<function name="function9">
<parameters>
<variable name="Var2"/>
<variable name="Var3"/>
<number value="4"/>
<variable name="Var5"/>
<variable name="Var8"/>
<variable name="Var7"/>
<variable name="c13"/>
<variable name="Var9_1"/>
<variable name="Var10"/>
</parameters>
</function>
<function name="function12">
<parameters>
<variable name="Var2"/>
<variable name="c13"/>
<constant name="c_Var7"/>
<variable name="Var7"/>
</parameters>
</function>
</facts>
</rhs>
</step>
</rules>
</original>
And here's the script:
Code:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:xdt="http://www.w3.org/2005/xpath-datatypes"
xmlns:err="http://www.w3.org/2005/xqt-errors"
exclude-result-prefixes="xs xdt err fn">
<xsl:output method="xml" indent="yes"/>
<!-- Variable storing the original tree -->
<xsl:variable name="main-doc" as="document-node()" select="/"/>
<!-- Variable storing the function names which will be the targets of this mutating operator -->
<xsl:variable name="funcnames" as="xs:string*">
<xsl:sequence select="'function1'"/>
<xsl:sequence select="'function2'"/>
<xsl:sequence select="'function3'"/>
<xsl:sequence select="'function6'"/>
</xsl:variable>
<!-- Variable storing the names of the steps containing in their LHS at least one occurrence of one function name in $funcnames -->
<!-- NOTE: this is a multiset, i.e., if step_001 contains two functions it will appear two times in $targetSteps. This is necessary to -->
<!-- apply the following templates once for each occurence of the elements in $funcnames -->
<xsl:variable name="targetSteps" as="xs:string*">
<xsl:for-each select="$main-doc/original/rules/step/lhs/facts/function/@name[(. = $funcnames)] | $main-doc/original/rules/step/lhs/facts/not/function/@name[(. = $funcnames)]">
<xsl:choose>
<xsl:when test="parent::*/parent::node()[name()='not']">
<xsl:sequence select="parent::*/parent::*/parent::*/parent::*/parent::node()/@name" />
<xsl:message terminate="no">
DEBUG "not case" step name = <xsl:value-of select="parent::*/parent::*/parent::*/parent::*/parent::node()/@name" />
</xsl:message>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="parent::*/parent::*/parent::*/parent::node()/@name" />
<xsl:message terminate="no">
DEBUG "function case" step name = <xsl:value-of select="parent::*/parent::*/parent::*/parent::node()/@name" />
</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:variable>
<!-- main template which invokes the sub-templates defined below -->
<xsl:template match="/">
<!-- <xsl:message terminate="no">
targetSteps = <xsl:value-of select="$targetSteps" />
funcnames = <xsl:value-of select="$funcnames" />
</xsl:message> -->
<xsl:for-each select="$targetSteps">
<xsl:variable name="currNode" select="position()"/>
<xsl:variable name="uri" select="concat('result_file_', $currNode, '.xml')"/>
<xsl:variable name="step" select="." as="xs:string"/>
<!-- <xsl:message terminate="no">
STEP NAME = <xsl:value-of select="$step" />
</xsl:message> -->
<xsl:result-document href="{$uri}">
<xsl:apply-templates select="$main-doc" mode="once">
<xsl:with-param name="counter" select="$currNode" />
<xsl:with-param name="currStep" select="$step" />
</xsl:apply-templates>
</xsl:result-document>
</xsl:for-each>
</xsl:template>
<!-- the identity/copy template -->
<xsl:template match="node( ) | @*" mode="once">
<xsl:param name="counter"/>
<xsl:param name="currStep"/>
<xsl:copy>
<xsl:apply-templates select="@* | node( )" mode="once">
<xsl:with-param name="counter" select="$counter" />
<xsl:with-param name="currStep" select="$currStep" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<!-- a template which modifies both sides of the matched step -->
<xsl:template match="original/rules/step" mode="once">
<xsl:param name="counter"/>
<xsl:param name="currStep"/>
<!-- <xsl:message terminate="no">
DEBUG checking the step's name before test = <xsl:value-of select="current()/@name" />
DEBUG $currStep variable is = <xsl:value-of select="$currStep" />
</xsl:message> -->
<xsl:choose>
<xsl:when test="current()/@name = $currStep">
<!-- <xsl:message terminate="no">
DEBUG here with step <xsl:value-of select="current()/@name" />
</xsl:message> -->
<!-- First of all we copy the <fact> tag with all its attributes -->
<xsl:copy>
<xsl:copy-of select="@*"/>
<!-- then we process its children, i.e., lhs, rhs, and possible others -->
<xsl:for-each select="child::node()">
<xsl:choose>
<!-- applying the mutation to the lhs side -->
<xsl:when test="current()[name()='lhs']">
<lhs>
<facts>
<xsl:for-each select="current()/facts/*">
<xsl:choose>
<xsl:when test="( current()[name()='function'] and current()[(@name=$funcnames)] ) or ( current()[name()='not'] and current()/function[(@name = $funcnames)] )">
<!-- when we encounter a function or not/function fact which matches one of the values in $funcnames we have to check if it is the one we have to replace (only one change per generated mutant) -->
<xsl:variable name="pos">
<xsl:choose>
<xsl:when test="parent::node()[name()='not']">
<xsl:value-of select="count(parent::*/parent::*/parent::*/preceding::lhs/facts/function[(@name = $funcnames)] | parent::*/parent::*/parent::*/preceding::lhs/facts/not/function[(@name = $funcnames)] | parent::*/preceding-sibling::*/function[(@name = $funcnames)] | parent::*/preceding-sibling::*[(@name = $funcnames)])" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="count(parent::*/parent::*/parent::*/preceding::lhs/facts/function[(@name = $funcnames)] | parent::*/parent::*/parent::*/preceding::lhs/facts/not/function[(@name = $funcnames)] | preceding-sibling::*[(@name = $funcnames)] | preceding-sibling::*/function[(@name = $funcnames)])" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- Now that we have the position, we can check if it is the one we have to modify or not -->
<xsl:choose>
<xsl:when test="$pos=$counter - 1 and parent::node()[name()='not']"> <!-- the check "parent::node()[name()='not']" does not seem to work -->
<constant name="false"/>
<!-- <xsl:message terminate="no">
REPLACED <xsl:value-of select="parent::node()" />
</xsl:message> -->
</xsl:when>
<xsl:when test="$pos=$counter - 1 and not(parent::node()[name()='not'])">
<constant name="true"/>
<!-- <xsl:message terminate="no">
REPLACED <xsl:value-of select="parent::node()" />
</xsl:message> -->
</xsl:when>
<xsl:otherwise>
<!-- This is not the fact we are looking for :) -->
<!-- <xsl:message terminate="no">
DEBUG lhs int otherwise (copy of <xsl:value-of select="current()/@name" />)
</xsl:message> -->
<xsl:copy-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<!-- The current fact does not match one of the values in $funcnames, so we simply copy it -->
<xsl:otherwise>
<!-- <xsl:message terminate="no">
DEBUG lhs ext otherwise (copy of <xsl:value-of select="current()/@name" />)
</xsl:message> -->
<xsl:copy-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</facts>
</lhs>
</xsl:when>
<!-- Now we check the rhs in order to replace the same function fact (if indeed present) -->
<!-- We are still in the scope of the for-each command going through all <step> children -->
<xsl:when test="current()[name()='rhs']">
<xsl:message terminate="no">
DEBUG just into rhs (curent() = <xsl:value-of select="current()" />)
<!-- this is empty, why? -->
</xsl:message>
<rhs>
<facts>
<!-- first of all we have to check the position of the fact we removed from the lhs, this is necessary
to determine which one is and to check if we have it also here in the rhs. Or maybe there is another way to do that? -->
<xsl:variable name="pos">
<xsl:for-each select="parent::*/lhs/facts/*">
<xsl:choose>
<xsl:when test="( current()[name()='function'] and current()[(@name=$funcnames)] ) or ( current()[name()='not'] and current()/function[(@name = $funcnames)] )">
<xsl:choose>
<xsl:when test="parent::node()[name()='not']">
<xsl:value-of select="count(parent::*/parent::*/parent::*/preceding::lhs/facts/function[(@name = $funcnames)] | parent::*/parent::*/parent::*/preceding::lhs/facts/not/function[(@name = $funcnames)] | parent::*/preceding-sibling::*/function[(@name = $funcnames)] | parent::*/preceding-sibling::*[(@name = $funcnames)])" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="count(parent::*/parent::*/parent::*/preceding::lhs/facts/function[(@name = $funcnames)] | parent::*/parent::*/parent::*/preceding::lhs/facts/not/function[(@name = $funcnames)] | preceding-sibling::*[(@name = $funcnames)] | preceding-sibling::*/function[(@name = $funcnames)])" />
</xsl:otherwise>
</xsl:choose>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:variable>
<!-- <xsl:message terminate="no">
DEBUG rhs after 1st for-each (curent() = <xsl:value-of select="current()" />)
DEBUG pos is = <xsl:value-of select="$pos" />
</xsl:message> -->
<!-- Now we select the fact in the lhs that is at the right position. This will be used below to check if we find it in the rhs -->
<xsl:variable name="fact">
<xsl:for-each select="parent::*/lhs/facts/*">
<xsl:choose>
<xsl:when test="$pos=$counter - 1 and parent::node()[name()='not']">
<xsl:value-of select="."/>
</xsl:when>
<xsl:when test="$pos=$counter - 1 and not(parent::node()[name()='not'])">
<xsl:value-of select="."/>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:variable>
<!-- <xsl:message terminate="no">
DEBUG before rhs replacement, $fact = <xsl:value-of select="$fact" /> !!!!
</xsl:message> -->
<!-- Finally, we check if the fact is present in the rhs and we replace it as the one in the lhs (if present) -->
<xsl:for-each select="current()/facts/*">
<xsl:choose>
<xsl:when test="deep-equal(current(), $fact)">
<xsl:choose>
<xsl:when test="parent::node()[name()='not']">
<constant name="false"/>
</xsl:when>
<xsl:when test="not(parent::node()[name()='not'])">
<constant name="true"/>
</xsl:when>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</facts>
</rhs>
</xsl:when>
<!-- We copy everything that is not rhs nor lhs -->
<xsl:otherwise>
<xsl:copy-of select="." />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
For your convenience, I have uploaded the two files on RapidShare:
http://rapidshare.com/files/3862398989/original.xml
http://rapidshare.com/files/3372804020/script.xsl
Thanks in advance,
EastvanAxon