XSL:使用'变量'条件'如果'

时间:2015-09-29 05:25:12

标签: xml xslt

我想使用'变量'有条件并应用模板。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<document>
    <body>
        <aaa right="abc" />
        <bbb right="zzz" />
    </body>
    <body>
        <aaa left="def" />
    </body>
</document>

我在下面展示了一个XSL(版本=&#34; 1.0&#34;)示例。

<xsl:template match="body">
    <xsl:variable name="leftA" select="body/aaa/@left" />
    <xsl:variable name="leftB" select="body/bbb/@left" />
    <xsl:variable name="left">
        <xsl:if test="not($leftA)">
            <xsl:value-of select="$leftB"/>
        </xsl:if>
        <xsl:value-of select="$leftA"/>
    </xsl:variable>
    <xsl:if test="$left">
        <xsl:apply-templates select="$left">
    </xsl:if>
</xsl:template>

<xsl:template match="@left">
    code here
</xsl:template>

$leftA$leftB都不存在于XML中时,我遇到了错误。我的XSL没有意义吗?我怎样才能避免错误?错误是Expression must evaluate to a node-set

3 个答案:

答案 0 :(得分:2)

我假设您要选择或输出body/bbb/@leftbody/aaa/@left中的任何一个,而不是两者,如果两者都存在,则引用body/bbb/@left

这个XSLT 1.0样式表......

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

<xsl:output method="html" indent="yes" encoding="utf-8"/>
<xsl:strip-space elements="*" />

<xsl:template match="/">
  <html>
    <head>
      <title>bbb or aaa</title>
    </head>
    <body>
      <h1>bbb or aaa</h1>
      <ul>
        <xsl:apply-templates select="test-cases/test-case" />
      </ul>  
    </body>
  </html>  
</xsl:template>

<xsl:template match="test-case">
  <xsl:variable name="test-result" select="body/bbb/@left | body/aaa/@left[not(../../bbb/@left)]" />
  <li>
    <xsl:value-of select="concat('Test case ',@id,' has result: ',$test-result)" />
  </li>
</xsl:template>

</xsl:stylesheet>

...当应用于此输入时......

<test-cases>
  <test-case id="1" description="a exists, but not b">
    <body>
      <aaa left="Moscow" />
    </body>
  </test-case>

  <test-case id="2" description="b exists, but not a">
    <body>
      <bbb left="Sydney" />
    </body>
  </test-case>

  <test-case id="3" description="both a and b exist">
    <body>
      <aaa left="Brandenburg" />
      <bbb left="Edinburgh" />
    </body>
  </test-case>

  <test-case id="4" description="neither a nor b exists">
    <body />
  </test-case>
</test-cases> 

...将导致此输出页面...

<html>
  <head>
    <META http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>bbb or aaa</title>
  </head>
  <body>
    <h1>bbb or aaa</h1>
    <ul>
      <li>Test case 1 has result: Moscow</li>
      <li>Test case 2 has result: Sydney</li>
      <li>Test case 3 has result: Edinburgh</li>
      <li>Test case 4 has result: </li>
    </ul>
  </body>
</html>

如果你在bbb和aaa之间没有特别的偏好,你可以简化$ test-result ...

  <xsl:variable name="test-result" select="(body/bbb/@left | body/aaa/@left)[1]" />

答案 1 :(得分:1)

最初,检查leftA,如果它为null,则将leftB指定为左变量的值。但是下一个语句在没有任何条件的情况下分配leftA值。所以它总是覆盖leftA值,即使它是null。

Platform.runLater(() -> { ... })

再使用一个条件或替换为where子句。除了在应用模板之前检查no null。

答案 2 :(得分:1)

您没有发布可重现的示例,因此这是猜测。

  

如何避免错误?错误是Expression必须评估为a   节点集。

一种方法是消除不必要的变量并直接执行您想要做的事情。例如,而不是所有这些:

<xsl:variable name="leftA" select="body/aaa/@left" />
<xsl:variable name="leftB" select="body/bbb/@left" />
<xsl:variable name="left">
    <xsl:if test="not($leftA)">
        <xsl:value-of select="$leftB"/>
    </xsl:if>
    <xsl:value-of select="$leftA"/>
</xsl:variable>
<xsl:if test="$left">
    <xsl:apply-templates select="$left">
</xsl:if>

做到这一点:

<xsl:variable name="leftA" select="body/aaa/@left" />
<xsl:apply-templates select="$leftA" />
<xsl:if test="not($leftA)">
    <xsl:apply-templates select="body/bbb/@left" />
</xsl:if>

现在的方式,$left变量包含结果树片段。您无法直接将模板应用于RTF,必须先使用扩展名node-set()函数将其转换为节点集:

<xsl:apply-templates select="exsl:node-set($left)">

添加后:

xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl"

xsl:stylesheet元素 - 请参阅:http://exslt.org/exsl/functions/node-set/index.html