Page 1 of 1
Need suggestions for transforming a logic string
Posted: Thu Oct 30, 2008 4:27 pm
by tsh138
I have a logic string which is somewhat different than I am accustomed to and I am trying to transform it into an XML representation. I am thinking I will need to perform multiple passes in order to get the correct results, but I want to make sure I am not overlooking a simpler method. Any suggestions? Thanks in advance.
| = OR
& = AND
! = NOT
Example 1: 661.1049.|.1099.&.
This equates to "(661 OR 1049) AND 1099"
The XML output to represent this would look like:
Code: Select all
<criteria operator="AND">
<def ref="1099"/>
<criteria operator="OR">
<def ref="661"/>
<def ref="1049"/>
</criteria>
</criteria>
Example 2: 204.1126.1127.53.|.|.&.
This equates to (204 OR 1126 OR 1127) AND 53
The XML output to represent this would look like:
Code: Select all
<criteria operator="AND">
<def ref="53"/>
<criteria operator="OR">
<def ref="204"/>
<def ref="1126"/>
<def ref="1127"/>
</criteria>
</criteria>
Example 3: 624.1296.661.1049.|.|.|.!.
This equates to NOT(624 OR 1296 OR 661 OR 1049)
The XML output to represent this would look like:
Code: Select all
<criteria operator="OR" negate="true">
<def ref="624"/>
<def ref="1296"/>
<def ref="661"/>
<def ref="1049"/>
</criteria>
Re: Need suggestions for transforming a logic string
Posted: Mon Nov 03, 2008 6:02 pm
by sorin_ristache
Hello,
Maybe it can be solved with an XSLT 2.0 stylesheet that parses an input text string and generates an output XML document as in your examples. A possible strategy is simulating a stack to which the numbers can be pushed when they are encountered in the input string and popped and included in the output XML document when an operator is encountered.
Regards,
Sorin
Re: Need suggestions for transforming a logic string
Posted: Wed Nov 05, 2008 1:15 am
by tsh138
I think I solved it. Here it is...let me know if you see any room for improvement?
Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:foo="myFunctions">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:element name="CONDITIONS">
<xsl:for-each select="node()/CONDITION">
<xsl:apply-templates select="current()"/>
</xsl:for-each>
</xsl:element>
</xsl:template>
<xsl:template match="CONDITION">
<xsl:copy-of select="current()"/>
<xsl:variable name="elementIDs">
<xsl:choose>
<xsl:when test="count(tokenize(current(), '\.')) = 2">
<xsl:value-of select="current()"></xsl:value-of>
</xsl:when>
<xsl:when test="count(tokenize(current(), '\.')) > 2">
<xsl:for-each select="reverse(tokenize(current(), '\.'))">
<xsl:if test="not(current()='|' or current()='&' or current()='!' or current()='')">
<xsl:value-of select="concat(current(), '.')"/>
</xsl:if>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:text>can't to do anything this is an obvious error in the content</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="operators">
<xsl:for-each select="reverse(tokenize(current(), '\.'))">
<xsl:if test="current()='|' or current()='&' or current()='!'">
<xsl:choose>
<xsl:when test="current()='|'">
<xsl:text>OR.</xsl:text>
</xsl:when>
<xsl:when test="current()='&'">
<xsl:text>AND.</xsl:text>
</xsl:when>
<xsl:when test="current()='!'">
<xsl:text>NOT.</xsl:text>
</xsl:when>
</xsl:choose>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:choose>
<xsl:when test="(count(tokenize($elementIDs,'\.'))=0) or (count(tokenize($operators,'\.'))=0)"/><!--no need to do anything-->
<xsl:otherwise>
<xsl:copy-of select="foo:BUILDLOGIC('NONE', $elementIDs, $operators)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="*" mode="#all">
<xsl:if test="exists(current())">
<xsl:copy-of select="current()"/>
</xsl:if>
</xsl:template>
<xsl:function name="foo:BUILDLOGIC">
<xsl:param name="prevOp"/>
<xsl:param name="ids"/>
<xsl:param name="ops"/>
<xsl:choose>
<xsl:when test="count(tokenize($ids,'\.'))=0"/><!--no need to do anything-->
<xsl:when test="count(tokenize($ops,'\.'))=0"><!-- one id left so just create the element -->
<xsl:element name="def">
<xsl:attribute name="ref"><xsl:value-of select="tokenize($ids, '\.')[1]"/></xsl:attribute>
</xsl:element>
</xsl:when>
<xsl:when test="tokenize($ops, '\.')[1] = $prevOp">
<xsl:element name="def">
<xsl:attribute name="ref"><xsl:value-of select="tokenize($ids, '\.')[1]"/></xsl:attribute>
</xsl:element>
<xsl:copy-of select="foo:BUILDLOGIC(tokenize($ops, '\.')[1], substring-after($ids, concat(tokenize($ids, '\.')[1], '.')), substring-after($ops, concat(tokenize($ops, '\.')[1], '.')))"/>
</xsl:when>
<xsl:otherwise>
<xsl:element name="criteria">
<xsl:choose>
<xsl:when test="tokenize($ops, '\.')[1]='NOT'">
<xsl:attribute name="operator"><xsl:value-of select="tokenize($ops, '\.')[2]"/></xsl:attribute>
<xsl:attribute name="negate">true</xsl:attribute>
<xsl:element name="def">
<xsl:attribute name="ref"><xsl:value-of select="tokenize($ids, '\.')[1]"/></xsl:attribute>
</xsl:element>
<xsl:copy-of select="foo:BUILDLOGIC(tokenize($ops, '\.')[2], substring-after($ids, concat(tokenize($ids, '\.')[1], '.')), substring-after($ops, concat(tokenize($ops, '\.')[2], '.')))"/>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="operator"><xsl:value-of select="tokenize($ops, '\.')[1]"/></xsl:attribute>
<xsl:element name="def">
<xsl:attribute name="ref"><xsl:value-of select="tokenize($ids, '\.')[1]"/></xsl:attribute>
</xsl:element>
<xsl:copy-of select="foo:BUILDLOGIC(tokenize($ops, '\.')[1], substring-after($ids, concat(tokenize($ids, '\.')[1], '.')), substring-after($ops, concat(tokenize($ops, '\.')[1], '.')))"/>
</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
</xsl:stylesheet>