为啥在 XSLT 转换期间出现此错误:XSLT 转换失败?
Posted
技术标签:
【中文标题】为啥在 XSLT 转换期间出现此错误:XSLT 转换失败?【英文标题】:Why I have this Error during XSLT transformation: XSLT transformation failed?为什么在 XSLT 转换期间出现此错误:XSLT 转换失败? 【发布时间】:2020-06-13 01:58:34 【问题描述】:我正在尝试根据烹饪内容动态创建一个附加元素 时间要素。我还按烹饪时间和食谱名称对食谱数据进行排序以显示其他元素。
如果烹饪时间超过 60 分钟,新元素应显示“Slow Burner”字样。如果烹饪时间小于或等于 60 分钟且大于或等于 30 分钟,则此新元素应显示“Medium Burner”字样。否则,新元素应显示 Quick and Easy 字样。
我收到一个错误,我不明白为什么 if 语句不起作用。
为什么?
XSL 在这里:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" doctype-system="about:legacy-compat" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" />
<xsl:template match="/collection">
<html>
</html>
【问题讨论】:
您确定可以使用 XSLT-2.0 吗?因为您似乎打算在浏览器环境中使用样式表... 是的,我确信 XSLT-2.0。谢谢 你说你遇到了一个错误,所以给我们一个线索 - 告诉我们错误是什么。我们喜欢解决难题,但没有必要通过隐瞒信息来使难题变得更加困难。 【参考方案1】:自从我弄乱 XSL 以来已经有很长时间了,但我的猜测是您将字符串“30 分钟”视为一个数字:if cooking_time >= 30
。如果是这种情况,一种可能的解决方法是在 XML 的属性中包含数字持续时间:
<cooking_time duration="30" unit="minutes">30 minutes</cooking_time>
另外,这可能是复制/粘贴问题,但这看起来不对:
cooking_Time > -or- > 30 < 60
【讨论】:
嗯,我明白了。生病试试这个,看看是否有效。我从这个网站上找到了这个faculty.madisoncollege.edu/schmidt/xml/xmlcond.html【参考方案2】:您可以将循环更改为以下内容。 recipe
元素的位置已更改为包含在对应的table
中(当然,如果需要,将其改回)。
<xsl:for-each select="recipe">
<xsl:sort select="cooking_Time" />
<xsl:variable name="time" select="number(replace(cooking_Time,'minutes',''))" />
<tr>
<td>
<h4>
<xsl:value-of select="title" />
</h4>
</td>
<td>
<recipe>
<xsl:value-of select="if ($time > 60) then 'Slow Burner' else if ($time >= 30) then 'Medium Burner' else 'Quick and Easy'" />
</recipe>
</td>
<td>
<xsl:value-of select="description" />
</td>
<td>
<xsl:value-of select="servings" />
</td>
<td>
<xsl:value-of select="preparetion_Time" />
</td>
<td>
<xsl:value-of select="cooking_Time" />
</td>
<td>
<xsl:value-of select="passiveTime" />
</td>
<td>
<xsl:value-of select="difficulty" />
</td>
<td>
<xsl:for-each select="ingredients">
<xsl:for-each select="ingredient">
<li>
<xsl:value-of select="." />
</li>
</xsl:for-each>
</xsl:for-each>
</td>
</tr>
</xsl:for-each>
这将按cooking_Time
对元素进行排序(您将xsl:sort
放在错误的位置;它必须立即跟随xsl:for-each
)。
主要逻辑在这个表达式中:
<xsl:value-of select="if ($time > 60) then 'Slow Burner' else if ($time >= 30) then 'Medium Burner' else 'Quick and Easy'" />
它根据$time
变量的值(为简化表达式而创建)输出适当的字符串。变量中的fn:replace
<xsl:variable name="time" select="number(replace(cooking_Time,'minutes',''))" />
注意$time
变量的值始终是一个数字,并且不包含字符串“分钟”。
如果您不能使用 XSLT-2.0,您也可以使用此 XSLT-1.0 解决方案:
<xsl:for-each select="recipe">
<xsl:sort select="normalize-space(cooking_Time)" />
<xsl:variable name="time">
<xsl:choose>
<xsl:when test="contains(cooking_Time,'minutes')">
<xsl:value-of select="number(substring-before(cooking_Time,'minutes'))" />
</xsl:when>
<xsl:when test="number(cooking_Time)">
<xsl:value-of select="number(cooking_Time)" />
</xsl:when>
<xsl:otherwise>
<!-- This value represents any items that don't have a 'cooking_Time' value present -->
<xsl:value-of select="0" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<tr>
<td>
<h4>
<xsl:value-of select="title" />
</h4>
</td>
<td>
<recipe>
<xsl:choose>
<xsl:when test="$time > 60">
<xsl:text>Slow Burner</xsl:text>
</xsl:when>
<xsl:when test="$time >= 30 and $time <= 60">
<xsl:text>Medium Burner</xsl:text>
</xsl:when>
<xsl:when test="$time < 30">
<xsl:text>Quick and Easy</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>Undefined</xsl:text>
</xsl:otherwise>
</xsl:choose>
</recipe>
</td>
<td>
<xsl:value-of select="description" />
</td>
<td>
<xsl:value-of select="servings" />
</td>
<td>
<xsl:value-of select="preparetion_Time" />
</td>
<td>
<xsl:value-of select="cooking_Time" />
</td>
<td>
<xsl:value-of select="passiveTime" />
</td>
<td>
<xsl:value-of select="difficulty" />
</td>
<td>
<xsl:for-each select="ingredients">
<xsl:for-each select="ingredient">
<li>
<xsl:value-of select="." />
</li>
</xsl:for-each>
</xsl:for-each>
</td>
</tr>
</xsl:for-each>
它通过使用normalize-space(...)
改进排序并使用xsl:choose
而不是内联if
s。
【讨论】:
我明确问过您是否可以使用 XSLT-2.0,您说“可以”。在 Firefox 中运行这个样式表是不可能的,因为 Firefox 只支持 XSLT-1.0。 等待几分钟......我正在创建一个应该在 Firefox 中工作的 XSLT-1.0 解决方案。 我添加了一个应该在 Firefox 中工作的 XSLT-1.0 解决方案。 Chrome 仍然值得怀疑。unit="minutes"
不是标准化的 XML 实体。在一个好的 XML 文件中,此属性将指示单位为 =minutes,并且该值的结尾“分钟”将被省略。因此,我做了从输入中删除“分钟”字符串(如果存在)的技巧。
编码分钟的标准方法是时间duration。您可以找到更多信息here at W3.org。以上是关于为啥在 XSLT 转换期间出现此错误:XSLT 转换失败?的主要内容,如果未能解决你的问题,请参考以下文章