1

您能否帮助我开发一个可以按顺序执行以下活动的 xsl 代码:
1. 取两个元素
的平均值 2. 规范化记录的平均值。

我在开发 xsl 时遇到困难的地方是重用新添加的下一个元素。任何帮助,将不胜感激

示例:
在下面的示例输入文件中,每个记录
1. avg = (c + d)/2
- avg = (c+d)/2 = (12+12)/2 = 12, (8+12)/2 =10 ....
2. avg_nom = avg/min(avg)
- avg_nom = avg/min(avg) = 12/min(12,10,15,27)=1.2

<?xml version="1.0" encoding="UTF-8"?>
<top>
<Results>
    <a>no</a>
    <b>10</b>
    <c>12</c>
    <d>12</d>
</Results>
<Results>
    <a>no</a>
    <b>8</b>
    <c>8</c>
    <d>12</d>
</Results>
<Results>
    <a>no</a>
    <b>6</b>
    <c>10</c>
    <d>20</d>
</Results>
<Results>
    <a>yes</a>
    <b>23</b>
    <c>20</c>
    <d>34</d>
</Results>
 </top>

预期的结果应该是

<?xml version="1.0" encoding="UTF-8"?>
<top>
<Results>
    <a>no</a>
    <b>10</b>
    <avg>12</avg>
    <avg_nom>1.2</avg_nom>
    <c>12</c>
    <d>12</d>
</Results>
<Results>
    <a>no</a>
    <b>8</b>
    <avg>10</avg>
    <avg_nom>1</avg_nom>
    <c>8</c>
    <d>12</d>
</Results>
<Results>
    <a>no</a>
    <b>6</b>
    <avg>15</avg>
    <avg_nom>1.5</avg_nom>
    <c>10</c>
    <d>20</d>
</Results>
<Results>
    <a>yes</a>
    <b>23</b>
    <avg>27</avg>
    <avg_nom>2.7</avg_nom>
    <c>20</c>
    <d>34</d>
</Results>
</top>
4

1 回答 1

1

使用 XSLT 2.0,您可以使用

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output indent="yes"/>

<xsl:variable name="step1-result">
  <xsl:apply-templates select="top" mode="step1"/>
</xsl:variable>

<xsl:template match="@* | node()" mode="#all">
  <xsl:copy>
    <xsl:apply-templates select="@* , node()" mode="#current"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="c" mode="step1">
  <avg><xsl:value-of select="(. + ../d) div 2"/></avg>
  <xsl:next-match/>
</xsl:template>

<xsl:template match="/*">
  <xsl:copy>
    <xsl:variable name="min-avg" select="min($step1-result/top/Results/avg)"/>
    <xsl:apply-templates select="$step1-result/top/*">
      <xsl:with-param name="min-avg" tunnel="yes" select="$min-avg"/>
    </xsl:apply-templates>
  </xsl:copy>
</xsl:template>

<xsl:template match="avg">
  <xsl:param name="min-avg" tunnel="yes"/>
  <xsl:next-match/>
  <avg_nom><xsl:value-of select=". div $min-avg"/></avg_nom>
</xsl:template>

</xsl:stylesheet>

这是上述样式表的 XSLT 1.0 版本:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="exsl">

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

<xsl:variable name="step1-result-fragment">
  <xsl:apply-templates select="top" mode="step1"/>
</xsl:variable>

<xsl:variable name="step1-result" select="exsl:node-set($step1-result-fragment)"/>

<xsl:template match="@* | node()" name="identity">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="@* | node()" mode="step1" name="step1-identity">
  <xsl:copy>
    <xsl:apply-templates select="@* | node()" mode="step1"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="c" mode="step1">
  <avg><xsl:value-of select="(. + ../d) div 2"/></avg>
  <xsl:call-template name="step1-identity"/>
</xsl:template>

<xsl:template match="/*">
  <xsl:copy>
    <xsl:variable name="min-avg">
      <xsl:for-each select="$step1-result/top/Results/avg">
        <xsl:sort select="." data-type="number"/>
        <xsl:if test="position() = 1">
          <xsl:value-of select="."/>
        </xsl:if>
      </xsl:for-each>
    </xsl:variable>
    <xsl:apply-templates select="$step1-result/top/Results">
      <xsl:with-param name="min-avg" select="$min-avg"/>
    </xsl:apply-templates>
  </xsl:copy>
</xsl:template>

<xsl:template match="Results">
  <xsl:param name="min-avg"/>
  <xsl:copy>
    <xsl:apply-templates select="@* | node()">
      <xsl:with-param name="min-avg" select="$min-avg"/>
    </xsl:apply-templates>
  </xsl:copy>
</xsl:template>

<xsl:template match="avg">
  <xsl:param name="min-avg"/>
  <xsl:call-template name="identity"/>
  <avg_nom><xsl:value-of select=". div $min-avg"/></avg_nom>
</xsl:template>

</xsl:stylesheet>
于 2013-10-19T13:21:33.223 回答