繁体   English   中英

XSLT整数评估器,如何实现n元求和与乘法?

XSLT integer evaluator, how to implement n-ary sum and multiplication?

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我正在尝试实现一个小的整数评估器。 varDef ,它处理的xml文档有一个varDef ,以及一个带有可能变量值的varDef列表。

XSLT将该XML文档转换为带有结果的另一个文档。

这是XML文档的XML模式:

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" 
    xmlns:ej3="http://procesadores.ejemplo.com/Ej3"
    targetNamespace="http://procesadores.ejemplo.com/Ej3" 
    elementFormDefault="qualified"> 

    <element name="documento">
        <complexType>
            <sequence>
                <element ref="ej3:expr"/>
                <element ref="ej3:varDef" maxOccurs="unbounded" minOccurs="0"/>
            </sequence>
        </complexType>
    </element>

    <element name="expr" abstract="true"/>

    <element name="suma" type="ej3:expBinaria" substitutionGroup="ej3:expr"/>
    <element name="resta" type="ej3:expBinaria" substitutionGroup="ej3:expr"/>
    <element name="mult" type="ej3:expBinaria" substitutionGroup="ej3:expr"/>
    <element name="div" type="ej3:expBinaria" substitutionGroup="ej3:expr"/>
    <element name="mod" type="ej3:expBinaria" substitutionGroup="ej3:expr"/>
    <element name="opuesto" type="ej3:expUnaria" substitutionGroup="ej3:expr"/>
    <element name="abs" type="ej3:expUnaria" substitutionGroup="ej3:expr"/>

    <element name="var" type="ej3:tipoNombreVar" substitutionGroup="ej3:expr"/>
    <element name="cons" type="integer" substitutionGroup="ej3:expr"/>

    <element name="varDef">
        <complexType>
            <simpleContent>
                <extension base="int">
                    <attribute name="nombre" type="ej3:tipoNombreVar"/>
                </extension>
            </simpleContent>
        </complexType>
    </element>

    <complexType name="expUnaria">
        <sequence>
            <element ref="ej3:expr" minOccurs="1" maxOccurs="1"/>
        </sequence>
    </complexType>

    <complexType name="expBinaria">
        <sequence>
            <element ref="ej3:expr" minOccurs="2" maxOccurs="2"/>
        </sequence>
    </complexType>

    <complexType name="expNaria">
        <sequence>
            <element ref="ej3:expr" minOccurs="0" maxOccurs="unbounded"/>
        </sequence>
    </complexType>


    <simpleType name="tipoNombreVar">
        <restriction base="string">
            <pattern value="[a-zA-Z][a-zA-Z0-9]*"/>
        </restriction>
    </simpleType>
</schema>

这是XSLT文档:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:ej3="http://procesadores.ejemplo.com/Ej3"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:strip-space elements="ej3:*"/>

    <xsl:output
        method="xml"
        indent="yes"
        encoding="utf-8"/>

    <xsl:key name="defVariables" match="ej3:varDef" use="@nombre"/>

    <xsl:template match="/ej3:documento"> 
        <cons><xsl:apply-templates select="*[not(local-name()='varDef')]"/></cons>
    </xsl:template>

    <xsl:template match="ej3:suma">
        <xsl:variable name="s1">  
            <xsl:apply-templates select="child::node()[1]"/>
        </xsl:variable>
        <xsl:variable name="s2">  
            <xsl:apply-templates select="child::node()[2]"/>
        </xsl:variable>
        <xsl:value-of select="$s1 + $s2"/>
    </xsl:template>

    <xsl:template match="ej3:resta">
        <xsl:variable name="s1">  
            <xsl:apply-templates select="child::node()[1]"/>
        </xsl:variable>
        <xsl:variable name="s2">  
            <xsl:apply-templates select="child::node()[2]"/>
        </xsl:variable>
        <xsl:value-of select="$s1 - $s2"/>
    </xsl:template>

    <xsl:template match="ej3:mult">
        <xsl:variable name="s1">  
            <xsl:apply-templates select="child::node()[1]"/>
        </xsl:variable>
        <xsl:variable name="s2">  
            <xsl:apply-templates select="child::node()[2]"/>
        </xsl:variable>
        <xsl:value-of select="$s1 * $s2"/>
    </xsl:template>

    <xsl:template match="ej3:div">
        <xsl:variable name="s1">  
            <xsl:apply-templates select="child::node()[1]"/>
        </xsl:variable>
        <xsl:variable name="s2">  
            <xsl:apply-templates select="child::node()[2]"/>
        </xsl:variable>

        <xsl:choose>
            <xsl:when test="$s2 = 0">
                <xsl:value-of select="$s1 div $s2"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="xs:integer($s1 div $s2)"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="ej3:mod">
        <xsl:variable name="s1">  
            <xsl:apply-templates select="child::node()[1]"/>
        </xsl:variable>
        <xsl:variable name="s2">  
            <xsl:apply-templates select="child::node()[2]"/>
        </xsl:variable>
        <xsl:value-of select="$s1 mod $s2"/>
    </xsl:template>

    <xsl:template match="ej3:opuesto">
        <xsl:variable name="s1">  
            <xsl:apply-templates select="child::node()[1]"/>
        </xsl:variable>
        <xsl:value-of select="- $s1"/>
    </xsl:template>

    <xsl:template match="ej3:abs">
        <xsl:variable name="s1">  
            <xsl:apply-templates select="child::node()[1]"/>
        </xsl:variable>
        <xsl:value-of select="abs($s1)"/>
    </xsl:template>

    <xsl:template match="ej3:var">
        <xsl:value-of select="key('defVariables',.)"/>
    </xsl:template>    

    <xsl:template match="ej3:cons">
        <test><xsl:value-of select="."/></test>
    </xsl:template>

</xsl:stylesheet>

这一切都按我的预期进行。 但是我想做suma (求和)和mult n元运算符。 也就是说,像这样:

<suma>
    <cons>1</cons>
    <cons>2</cons>
    <cons>3</cons>
</suma>

应该能够被评估。 为了使它起作用,我必须修改suma xsl:template,但是我不太确定该怎么做。 我尝试过一些服务器式的事情,但是我必须以某种方式评估这些孩子,然后再将它们加起来,这使我很难找到解决方案。

您能建议如何实现吗?

请注意,我希望summult操作数都以这种方式工作,因此基于xpath函数sum()的解决方案将不适用于mult

1 个回复

我将确保您的模板返回xs:integer序列,例如change

<xsl:template match="ej3:cons">
    <test><xsl:value-of select="."/></test>
</xsl:template>

<xsl:template match="ej3:cons">
    <xsl:sequence select="xs:integer(.)"/>
</xsl:template>

那么你可以使用

<xsl:template match="suma">
  <xsl:variable name="operands" as="xs:integer+">
    <xsl:apply-templates select="*"/>
  </xsl:variable>
  <xsl:sequence select="sum($operands)"/>
</xsl:template>

对于乘法,可以使用一个函数(需要声明绑定到某些名称空间的前缀mf

<xsl:function name="mf:multiply" as="xs:integer">
  <xsl:param name="operands" as="xs:integer+"/>
  <xsl:sequence select="if (not(exists($operands[2])))
                        then $operands[1]
                        else $operands[1] * mf:multiply($operands[position() gt 1])"/>
</xsl:function>

然后用在

<xsl:template match="multa">
  <xsl:variable name="operands" as="xs:integer+">
    <xsl:apply-templates select="*"/>
  </xsl:variable>
  <xsl:sequence select="mf:multiply($operands)"/>
</xsl:template>

这是一个例子:

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:mf="http://example.com/mf"
  exclude-result-prefixes="xs mf">

<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:function name="mf:multiply" as="xs:integer">
  <xsl:param name="operands" as="xs:integer+"/>
  <xsl:sequence select="if (not(exists($operands[2])))
                        then $operands[1]
                        else $operands[1] * mf:multiply($operands[position() gt 1])"/>
</xsl:function>

<xsl:template match="expression">
  <result>
    <xsl:apply-templates/>
  </result>
</xsl:template>

<xsl:template match="cons">
    <xsl:sequence select="xs:integer(.)"/>
</xsl:template>

<xsl:template match="suma">
  <xsl:variable name="operands" as="xs:integer+">
    <xsl:apply-templates select="*"/>
  </xsl:variable>
  <xsl:sequence select="sum($operands)"/>
</xsl:template>

<xsl:template match="multa">
  <xsl:variable name="operands" as="xs:integer+">
    <xsl:apply-templates select="*"/>
  </xsl:variable>
  <xsl:sequence select="mf:multiply($operands)"/>
</xsl:template>

</xsl:stylesheet>

输入示例

<expression>
  <suma>
    <cons>1</cons>
    <cons>2</cons>
    <cons>3</cons>
    <multa>
      <cons>1</cons>
      <cons>2</cons>
      <cons>3</cons>
    </multa>
  </suma>
</expression>

我得到输出<result>12</result>

2 Python元循环评估器

一个介绍编程类编写一个Lisp metacircular评估器并不罕见。 有没有试图为Python做这个? 是的,我知道Lisp的结构和语法很适合于一个元模型评估器等等.Python很可能会更难。 我只是好奇是否已经做出这样的尝试。 ...

3 评估器的数据导向实现 [SICP]

我正在解决 SICP 练习 4.3 它是关于编写一个数据导向的评估器( eval过程),而不是本书第 4.1.1 节中介绍的评估器。 基本思想是根据每种类型的表达式而不是使用条件从表中获取eval使用的过程。 书中介绍的 eval 过程的开头是这样实现的: 数据导向版本可能是: 除了self ...

5 后缀评估器

我想创建一个可以处理多位数和十进制数字的Postfix评估程序。 该程序可以使用多位数,但不能使用小数。 我该怎么做? 我使用了中缀表达式:“ 10 + 20 *(50/3)+ 4”,在后缀中是“ 10 20 50 3 / * + 4 +”。 结果,我得到了347.33333333333 ...

6 逻辑评估器

我有一个需要支持“用户选项”来确定如何覆盖文件的程序,用户可以从“选项”中进行选择,这会导致几种组合,从而使得很难对所有可能的“ IF ... ELSE语句”进行编码,这种复杂的结果评估很难编写代码,而且时间太长,也让我发疯! 我希望通过某种“解析”来解决此问题,以便以更快,更有机的方式评 ...

7 模式评估器

我有一些字符串需要按以下模式进行评估- 上面提到的输入具有相同的模式,其中'()'或null表示为' * '。输出保存到int / string数组中,因此输出形式是这样的。 请提出一种评估这种形式的输出形式的方法。 ...

8 为Java表达式评估器提供通用实现

当前,我们在微服务中使用JEXL表达评估器。 但是,我们希望将来能够灵活地将其更改为其他一些表达式评估器。 这里的问题是来自不同供应商的表达式求值器不会从公共接口继承方法。 因此,尽管不同的表达式评估程序确实提供了相似的功能,但它们可能具有不同的方法以及不同的方法签名。 如果我们将来决定 ...

9 词法或动态范围 - Haskell 实现的评估器

我的教授在谈到词法作用域和动态作用域之间的区别后给了我们一个问题。 他向我们展示了一个用 Haskell 编码的简单评估器(一种虚构语言)。 以下是代码: 问题问: 这种实现的语言使用词法作用域还是动态作用域? 我们应该如何更改代码以使其具有另一种类型的作用域 坦率地说,这是一个非常难的 ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2021 STACKOOM.COM