我试图理解“exsl:node-set”的概念及其用法,它可以处理XML中的已处理/生成元素。任何人都可以帮忙
我开始开发一个可以按顺序执行以下活动的XSL代码:
实施例: 在下面的示例输入文件中为每条记录
输入XML
<?xml version="1.0" encoding="UTF-8"?>
<top>
<Level1>
<Results>
<a>no</a>
<b>10</b>
<b_nom>1.66</b_nom>
<c>12</c>
<d>9</d>
</Results>
</Level1>
<Level1>
<Results>
<a>no</a>
<b>8</b>
<b_nom>1.33</b_nom>
<c>50</c>
<d>12</d>
</Results>
<Level1>
</Level1>
<Results>
<a>no</a>
<b>6</b>
<b_nom>1</b_nom>
<c>55</c>
<d>56</d>
</Results>
<Level1>
</Level1>
<Results>
<a>yes</a>
<b>23</b>
<b_nom>1</b_nom>
<c>32</c>
<d>34</d>
</Results>
</Level1>
</top>
代码:此代码为provided as a response to earlier question,其中示例XML在树中只有两个级别,即。 <top><Results>
对于这种方法非常好,但对于上面的XML输入,我丢失了<Level1>
的数据。我不理解代码并进行必要的更正。
<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>
我需要的不仅是对上述代码的修正以获得正确的输出,而且还要进一步理解代码。为此,我想在上面的例子中添加一个额外的步骤
因此最终输出应如下所示
<?xml version="1.0"?>
<top>
<Level1>
<Results>
<a>no</a>
<b>10</b>
<b_nom>1.66</b_nom>
<avg>10.5</avg>
<avg_nom>1</avg_nom>
<final>5.5</final>
<c>12</c>
<d>9</d>
</Results>
</Level1>
<Level1>
<Results>
<a>no</a>
<b>8</b>
<b_nom>1.33</b_nom>
<avg>31</avg>
<avg_nom>2.95238095238095</avg_nom>
<final>2.14</final>
<c>50</c>
<d>12</d>
</Results>
</Level1>
<Level1>
<Results>
<a>no</a>
<b>6</b>
<b_nom>1</b_nom>
<avg>55.5</avg>
<avg_nom>5.28571428571429</avg_nom>
<final>3.14</final>
<c>55</c>
<d>56</d>
</Results>
</Level1>
<Level1>
<Results>
<a>yes</a>
<b>23</b>
<b_nom>1</b_nom>
<avg>33</avg>
<avg_nom>3.14285714285714</avg_nom>
<final>2.07</final>
<c>32</c>
<d>34</d>
</Results>
</Level1>
</top>
答案 0 :(得分:1)
在XSLT 2.0中,您可以创建一个值为树的变量:
<xsl:variable name="temp">
<root>
<xsl:call-template name="do-something"/>
</root>
</xsl:variable>
然后您可以使用XSLT的全部功能来处理此树
<xsl:apply-templates select="$temp" mode="postprocess"/>
这允许样式表在几个阶段中运行:您可以创建一个中间结果,然后对其进行后处理:您可以根据需要在多个阶段中执行转换。
在XSLT 1.0中,由于在规范开发后期出现了糟糕的设计错误,因此不允许这样做。通过使$temp
成为“结果树片段”并禁止对结果树片段执行诸如xsl:apply-templates之类的操作来强制实施限制。
在XSLT 1.0发布后很快就实现了这个错误,并且处理器供应商通过引入扩展函数exslt:node-set()来解决它,而没有引入不符合规范的情况。这允许你写
<xsl:apply-templates select="exslt:node-set($temp)" mode="postprocess"/>
从概念上讲,exslt:node-set()将结果树片段(不允许xsl:apply-templates处理)转换为单例节点集(它是)。可能在大多数实现中,它都是非操作。
我希望这可以帮助您了解样式表正在做什么。