2

我有 xpath 查询:

        <xsl:variable name="fbids">
            <xsl:sequence select="
                feature_relationship[type_id/cvterm[name='molec_deletes' or name='deletes']]
                /object_id/feature/feature_synonym/synonym_id/synonym/synonym_sgml"/>
        </xsl:variable>

此查询不会将匹配节点序列作为序列本身返回,而是将它们作为单个#documentfragment 的子节点返回。即使没有元素满足此查询,$fbids 仍设置为空的#documentfragment。

这搞砸了我的代码,而下面的循环不是每个匹配的元素迭代一次,而是为#documentfragment 运行一次,仅此而已。如何强制它返回一个不错的 element()* 类型?

谢谢!

4

2 回答 2

2

XSLT 2.0 中变量的默认类型是文档片段。如果希望它是元素序列,则添加as属性并指定序列类型。您还可以使用select属性,而不是嵌套的序列元素:

<xsl:variable name="fbids" as="element()*" select="
            feature_relationship[type_id/cvterm[name='molec_deletes' or name='deletes']]
             /object_id/feature/feature_synonym/synonym_id/synonym/synonym_sgml"/>
于 2012-08-11T01:41:22.847 回答
2
      <xsl:variable name="fbids">
          <xsl:sequence select="
              feature_relationship[type_id/cvterm[name='molec_deletes' or name='deletes']]
              /object_id/feature/feature_synonym/synonym_id/synonym/synonym_sgml"/>
      </xsl:variable>

此查询不会将匹配节点序列作为序列本身返回,而是将它们作为单个#documentfragment 的子节点返回。

是的,因为变量体内有一个序列,并且变量没有指定类型。这种情况下的默认类型是:document-node().

解决方案

select指定不带正文的变量,并在 的属性中提供 XPath 表达式xsl:variable

<xsl:variable name="fbids" select="
  feature_relationship[type_id/cvterm[name='molec_deletes' or name='deletes']]
    /object_id/feature/feature_synonym/synonym_id/synonym/synonym_sgml"/>

as使用属性指定所需的变量类型仍然是一个好习惯。

一个完整的答案还必须涵盖变量的值(一系列元素)在其主体内动态创建的情况。

再次指定变量的类型是解决方案的关键

这是一个小而完整的例子:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/*">

  <xsl:variable name="vMapped" as="element()*">
    <xsl:for-each select="num">
      <num><xsl:value-of select=".*2"/></num>
    </xsl:for-each>
  </xsl:variable>

  <xsl:for-each select="$vMapped">
   <xsl:sequence select="."/>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于以下 XML 文档时:

<nums>
  <num>01</num>
  <num>02</num>
  <num>03</num>
  <num>04</num>
  <num>05</num>
  <num>06</num>
  <num>07</num>
  <num>08</num>
  <num>09</num>
  <num>10</num>
</nums>

命名的变量$vMapped在其主体内获取其动态创建的值。其余代码成功地将此变量用作元素序列——访问此序列中的每个元素并将其复制到输出:

<num>2</num>
<num>4</num>
<num>6</num>
<num>8</num>
<num>10</num>
<num>12</num>
<num>14</num>
<num>16</num>
<num>18</num>
<num>20</num>
于 2012-08-11T04:04:00.937 回答