如何使用XML和XSLT进行计算

时间:2017-03-25 17:49:58

标签: xml xslt xsd

我正在使用 XSD XML XSLT 构建表达式计算器。

目前只执行memo_ResponseData操作。

我已经开发了Sum和有效的xml-schema文档。

SCHEMA(XSD)

xml

XML(在此XML中,我想执行以下操作:<xs:complexType name="typeSum"> <xs:sequence> <xs:element ref="exp:Expression"/> <xs:element ref="exp:Expression"/> </xs:sequence> </xs:complexType> <xs:complexType name="EE"> <xs:sequence> <xs:element ref="exp:Expression" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> <xs:element name="Expression" abstract="true"/> <xs:element name="EE" type="exp:EE"/> <xs:element name="Const" type="xs:integer" substitutionGroup="exp:Expression"/> <xs:element name="Sum" type="exp:typeSum" substitutionGroup="exp:Expression"/>

Sum(Sum(8,4),Sum(1,2))

问题来自 XSLT 。这是我到目前为止所尝试的:

<?xml version="1.0" encoding="UTF-8"?>
<e:EE xmlns:e="expr"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="xxx/xxx/xxx...">
    <e:Sum>
       <e:Sum>
           <e:Const>
               8
           </e:Const>
           <e:Const>
               4
           </e:Const>
       </e:Sum>
        <e:Sum>
            <e:Const>
                1
            </e:Const>
            <e:Const>
                2
            </e:Const>
        </e:Sum>
    </e:Sum>
</e:EE>

<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:e="expr" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes" encoding="iso-8859-1"/> <xsl:template match="e:EE"> <xsl:copy> <xsl:apply-templates select="e:Sum" /> </xsl:copy> </xsl:template> <xsl:template match="e:Sum"> <xsl:variable name="v1"> <xsl:apply-templates select="e:Const[1]"></xsl:apply-templates> </xsl:variable> <xsl:variable name="v2"> <xsl:apply-templates select="e:Const[2]"></xsl:apply-templates> </xsl:variable> <Operation> <xsl:value-of select="$v1" /> + <xsl:value-of select="$v2" /> </Operation> <result> <xsl:value-of select="$v1 + $v2"/> </result> </xsl:template> </xsl:stylesheet> 仅{2} sum时,此功能正常。即Sum(8,4)

但是,我想以递归方式将Const应用于XML中的每个表达式。

1 个答案:

答案 0 :(得分:2)

您可以通过有效使用模板来完成此操作 - 定义模板,以便他们知道如何处理手头的操作。

在Sum的情况下,那将是:

  1. 获取第一个操作数(第一个子元素)的结果值
  2. 获取第二个操作数(第二个子元素)的结果值
  3. 将它们组合在一起。
  4. Sum不需要知道它具有什么样的操作数。它可以只为它们应用模板,让XSLT解决这个问题。这就是我们得到的:

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
      FillGrid()
    End Sub
    
    Private Sub FillGrid()
      For i = 1 To 15
        DataGridView1.Rows.Add("Row" + i.ToString() + "C1", "Row" + i.ToString() + "C2", "Row" + i.ToString() + "C3")
      Next
    End Sub
    
    Private Sub btSelectedRows_Click(sender As Object, e As EventArgs) Handles btSelectedRows.Click
      TextBox1.Text += "Reverse selected values --------" + Environment.NewLine
      TextBox1.Text += "There are " + DataGridView1.SelectedRows.Count.ToString() + " selected Rows" + Environment.NewLine
      For Each curSelectedRow As DataGridViewRow In DataGridView1.SelectedRows
        If Not curSelectedRow.IsNewRow Then  ' ignore new row if selected
          TextBox1.Text += curSelectedRow.Cells(0).Value + ", " + curSelectedRow.Cells(1).Value + ", " + curSelectedRow.Cells(2).Value + Environment.NewLine
        End If
      Next
      TextBox1.Text += "End of Reverse selected values --------" + Environment.NewLine
    End Sub
    
    Private Sub btOriginalSelection_Click(sender As Object, e As EventArgs) Handles btOriginalSelection.Click
      TextBox1.Text += "Original order of selected values --------" + Environment.NewLine
      TextBox1.Text += "There are " + DataGridView1.SelectedRows.Count.ToString() + " selected Rows" + Environment.NewLine
      Dim selectedRows As DataGridViewSelectedRowCollection = DataGridView1.SelectedRows
      For rowIndex = selectedRows.Count - 1 To 0 Step -1
        If Not selectedRows(rowIndex).IsNewRow Then  ' ignore new row if selected
          TextBox1.Text += selectedRows(rowIndex).Cells(0).Value + ", " + selectedRows(rowIndex).Cells(1).Value + ", " +
                           selectedRows(rowIndex).Cells(2).Value + Environment.NewLine
        End If
      Next
      TextBox1.Text += "End of Original selection order of selected values --------"
    End Sub
    

    <xsl:template match="e:Sum"> <xsl:variable name="v1"> <xsl:apply-templates select="*[1]" /> </xsl:variable> <xsl:variable name="v2"> <xsl:apply-templates select="*[2]" /> </xsl:variable> <xsl:value-of select="$v1 + $v2"/> </xsl:template> 定义模板可能也是有意义的,只是明确定义了:

    e:Const

    这是一个完整的XSLT,增加了<xsl:template match="e:Const"> <xsl:value-of select ="."/> </xsl:template> 和一元操作(e:Multiply):

    e:Invert

    在此输入XML上运行时:

    <xsl:stylesheet version="1.0"
        xmlns:e="expr"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
      <xsl:output
          method="xml"
          indent="yes"
          encoding="iso-8859-1"/>
    
      <xsl:template match="e:EE">
        <xsl:copy>
          <xsl:apply-templates select="*[1]" />
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="e:Sum">
        <xsl:variable name="v1">
          <xsl:apply-templates select="*[1]" />
        </xsl:variable>
        <xsl:variable name="v2">
          <xsl:apply-templates select="*[2]" />
        </xsl:variable>
    
        <xsl:value-of select="$v1 + $v2"/>
      </xsl:template>
    
      <xsl:template match="e:Multiply">
        <xsl:variable name="v1">
          <xsl:apply-templates select="*[1]" />
        </xsl:variable>
        <xsl:variable name="v2">
          <xsl:apply-templates select="*[2]" />
        </xsl:variable>
    
        <xsl:value-of select="$v1 * $v2"/>
      </xsl:template>
    
      <xsl:template match="e:Invert">
      <xsl:variable name="v1">
          <xsl:apply-templates select="*[1]" />
      </xsl:variable>
    
        <xsl:value-of select="1 div $v1"/>
      </xsl:template>
    
      <xsl:template match="e:Const">
        <xsl:value-of select ="."/>
      </xsl:template>
    
    </xsl:stylesheet>
    

    结果是:

    <?xml version="1.0" encoding="UTF-8"?>
    <e:EE xmlns:e="expr"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="xxx/xxx/xxx...">
      <e:Sum>
        <e:Sum>
          <e:Const>8</e:Const>
          <e:Const>4</e:Const>
        </e:Sum>
        <e:Sum>
          <e:Multiply>
            <e:Invert>
              <e:Const>3</e:Const>
            </e:Invert>
            <e:Const>6</e:Const>
          </e:Multiply>
          <e:Const>2</e:Const>
        </e:Sum>
      </e:Sum>
    </e:EE>