<service>
<rule> </rule> and <rule> </rule>
<rule> </rule> or <rule> </rule>
</service>
好的,我会解释我的问题。 我想实现一个推理引擎。 问题如下: service有一组操作,每个操作都有一组规则。 规则可以由逻辑运算符链接。 我想过使用XML来表示我的规则。了解规则X我想提取与此规则关联的所有操作。 例如
action=admin_required, service=identity, rules=[role:admin or is_admin:1]
action=service_role, service=, rules=[role:service]
action=get_service, service=identity, rules=[admin_required or service_role]
action=list_services, service=identity, rules=[admin_required and admin_service]
action=create_service, service=identity, rules=[admin_required]
action=update_service, service=identity, rules=[admin_required]
最好的问候
答案 0 :(得分:1)
我认为这超出了Stack Overflow的范围,但我想我会这样做:
<service>
<match>all</match>
<rule>...</rule>
<rule>...</rule>
</service>
match
为all
或any
。或者您可以将其作为service
的属性。
不确定我理解你的第二个问题,需要详细说明吗?
答案 1 :(得分:1)
嗯,没有最好的&#34;但是,一种方法可能是使用运算符元素来链接两个规则,或者可能是其他运算符。例如,您的第一个规则rules=[role:admin or is_admin:1]
可以表示为
<rules>
<operator type="or">
<rule>role:admin</rule>
<rule>is_admin:1</rule>
</operator>
</rules>
这将允许嵌套&#39;运营商也是。例如,rules=[role:admin or (is_admin:1 and role:tester)]
可以表示为
<rules>
<operator type="or">
<rule>role:admin</rule>
<operator type="or">
<rule>is_admin:1</rule>
<rule>role:tester</rule>
</operator>
</operator>
</rules>
您已对此XSLT进行了标记,因此这里有一些可用于解析&#39;的XSLT。规则。它通过匹配运算符元素,然后递归解析第一个和第二个操作数来实现。然后,它根据操作员类型给出结果。通过检查规则是否存在于包含所有规则的参数中,可以简单地解析规则元素。
试试这个XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="rules">role:admin</xsl:param>
<xsl:variable name="checkrule" select="concat(',', $rules, ',')" />
<xsl:template match="actions">
<results>
<xsl:apply-templates />
</results>
</xsl:template>
<xsl:template match="action">
<xsl:variable name="evaluate">
<xsl:apply-templates select="rules/*" mode="rules" />
</xsl:variable>
<xsl:if test="$evaluate=1">
<xsl:value-of select="@*"/>
<xsl:text>;</xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="operator" mode="rules">
<xsl:variable name="left">
<xsl:apply-templates select="*[1]" mode="rules" />
</xsl:variable>
<xsl:variable name="right">
<xsl:apply-templates select="*[2]" mode="rules" />
</xsl:variable>
<xsl:choose>
<xsl:when test="@type='or'">
<xsl:choose>
<xsl:when test="$left=1 or $right=1">1</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="@type='and'">
<xsl:choose>
<xsl:when test="$left=1 and $right=1">1</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="rule" mode="rules">
<xsl:choose>
<xsl:when test="contains($rules, .)">1</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
应用于此XML(代表您的所有操作)
<actions>
<action name="admin_required">
<rules>
<operator type="or">
<rule>role:admin</rule>
<rule>is_admin:1</rule>
</operator>
</rules>
</action>
<action name="service_role">
<rules>
<rule>role:service</rule>
</rules>
</action>
<action name="get_service">
<rules>
<operator type="or">
<rule>admin_required</rule>
<rule>admin_service</rule>
</operator>
</rules>
</action>
<action name="list_services">
<rules>
<operator type="and">
<rule>admin_required</rule>
<rule>admin_service</rule>
</operator>
</rules>
</action>
<action name="create_service">
<rules>
<rule>admin_required</rule>
</rules>
</action>
<action name="update_service">
<rules>
<rule>admin_required</rule>
</rules>
</action>
</actions>
以下是输出
<results>admin_required;</results>
如果你想要一个递归的&#39;解决方案,尝试这个XSLT,它使用一个命名模板,该模板以前一次调用的结果递归调用。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:param name="rules">role:admin</xsl:param>
<xsl:variable name="checkrule" select="concat(',', $rules, ',')"/>
<xsl:template match="actions">
<results>
<xsl:call-template name="recursive"/>
</results>
</xsl:template>
<xsl:template name="recursive">
<xsl:param name="currentRules" select="$rules"/>
<xsl:param name="currentResults"/>
<xsl:variable name="newResults">
<xsl:apply-templates select="action">
<xsl:with-param name="currentRules" select="$currentRules"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:choose>
<xsl:when test="$newResults != $currentResults">
<xsl:call-template name="recursive">
<xsl:with-param name="currentRules" select="concat($rules, ';', $newResults)"/>
<xsl:with-param name="currentResults" select="$newResults"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$currentResults"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="action">
<xsl:param name="currentRules"/>
<xsl:variable name="evaluate">
<xsl:apply-templates select="rules/*" mode="rules">
<xsl:with-param name="currentRules" select="$currentRules"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:if test="$evaluate=1">
<xsl:value-of select="@*"/>
<xsl:text>;</xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="operator" mode="rules">
<xsl:param name="currentRules"/>
<xsl:variable name="left">
<xsl:apply-templates select="*[1]" mode="rules">
<xsl:with-param name="currentRules" select="$currentRules"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:variable name="right">
<xsl:apply-templates select="*[2]" mode="rules">
<xsl:with-param name="currentRules" select="$currentRules"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:choose>
<xsl:when test="@type='or'">
<xsl:choose>
<xsl:when test="$left=1 or $right=1">1</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="@type='and'">
<xsl:choose>
<xsl:when test="$left=1 and $right=1">1</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="rule" mode="rules">
<xsl:param name="currentRules"/>
<xsl:choose>
<xsl:when test="contains($currentRules, .)">1</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
这会产生以下结果
<results>admin_required;get_service;create_service;update_service;</results>