XSLT整数计算器,如何实现n元求和和和乘法?

XSLT整数计算器,如何实现n元求和和和乘法?,xslt,integer,xslt-2.0,evaluation,Xslt,Integer,Xslt 2.0,Evaluation,我正在尝试实现一个小的整数计算器。实际上,它处理的xml文档有一个表达式和一个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"

我正在尝试实现一个小的整数计算器。实际上,它处理的xml文档有一个表达式和一个
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>
应该能够被评估。为了让它工作,我必须修改
suma
xsl:template,但我不太确定如何做。我尝试了很多方法,但在把孩子们相加之前,我必须对他们进行评估,这让我很难找到解决办法

你能建议如何做到这一点吗


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

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

<xsl:template match="ej3:cons">
    <test><xsl:value-of select="."/></test>
</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 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>

1.
2.
3.
1.
2.
3.

我得到了输出
12

如何使用该方法实现n元乘法?@Trollkemada,我对答案进行了编辑,并提出了一些建议,应该有助于实现它,尽管未经测试,并且仅在SO编辑器中直接键入。mult和sum都将结果连接为字符串,这就是我所有努力的问题所在。我在一些在线xslt测试人员中进行了测试,得到了相同的结果。@Trollkemada,我做了一些编辑,并添加了一个简短但完整的示例来完成这项工作。如果仍然存在问题,请编辑问题并提供一些示例表达式的XML输入文档。请注意,使用
xsl:sequence
而不是
xsl:value of
是必不可少的。
<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: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>