0

我正在尝试使用 xslt 2.0 在 Saxon-ce 中使用 ixsl:eval() 评估动态 xpath,但似乎无法正常工作。这是说明性的 XML

<things>
  <thing>
    <name>widget one</name>
    <number>10</number>
    <type>metal</type>
    <subtypes>
      <subtype>red<subtype>
    </subtypes>
  </thing>
  <thing>
    <name>widget two</name>
    <number>11</number>
    <type>wood</type>
    <subtypes>
      <subtype>red</subtype>
      <subtype>blue</subtype>
    </subtypes>
  </thing>
</things>

以及我正在尝试评估的 xsl 2.0 样式表的一部分(各种参数由较大的 xsl 样式表的另一部分传递)

<template name="display" match="things">
  <xsl:param name="num"/>
  <xsl:param name="type" as="xs:string"/>
  <xsl:param name="subtype" as="xs:string"/>

  <xsl:variable name="xpathExp" as="xs:string">
     <xsl:text>things/thing</xsl:text>
     <xsl:if test="not($num = 'all')>
       <xsl:copy-of select="concat('[number=',$num,']')"/>
     </xsl:if>
     <xsl:if test="not($type = 'all')>
        <xsl:copy-of select="concat('[type=''',$type,''']')"/>
     </xsl:if>
     <xsl:if test="note($subtype = 'all')>
         <xsl:copy-of select="concat('[subtype/subtypes=''',$subtype,''']')/>
     </xsl:if>
   </xsl:variable>

   <xsl:result-document href="#display" method="ixsl:replace-content">

   <xsl:for-each select="ixsl:eval($xpathExp)">
      <xsl:sort select="name"/>
   </xsl:for-each>

</template>

当我用显式 xpath 语句替换 eval 语句时,代码可以工作,因此由于某种原因,$xpathExp 上的 eval 不起作用。想法?

* 编辑 * 这是一个更好的 XML 示例:

<things>
  <thing>
    <name>widget one</name>
    <number>10</number>
    <type>metal</type>
    <subtypes>
      <subtype>red<subtype>
    </subtypes>
  </thing>
  <thing>
    <name>widget two</name>
    <number>11</number>
    <type>wood</type>
    <subtypes>
      <subtype>red</subtype>
      <subtype>blue</subtype>
    </subtypes>
  </thing>
  <thing>
    <name>widget three</name>
    <number>11</number>
    <type>metal</type>
    <subtypes>
      <subtype>blue</subtype>
    </subtypes>
  </thing>
</things>

用户可以通过数字、类型和子类型的下拉框选择值。根据用户的选择,将显示事物名称列表。例如,如果用户选择数字 11 和红色子类型,它只会显示小部件 2。如果他们选择蓝色的子类型,它将显示小部件二和三的名称。

所以基本的 xpath 过滤器是 things/thing。如果用户选择一个数字值,我想将 [number=$num] 附加到 xpath 表达式,因此 ti 将是 things/thing[number=$num]。如果他们选择了多个项目,比如说数字和类型,[number=$num][type=$type] 将被附加到基本 xpath 并且我将拥有 things/thing[number=$num][type=$类型]。

基本上,我试图避免的是必须单独编码所有可能的排列和可能的用户选择的组合。

这有帮助吗?

4

1 回答 1

0

ixsl :eval函数用于动态评估 JavaScript,而不是 XPath。来自Saxon-CE 文档

...执行 Javascript 代码,以字符串形式提供。提供的脚本作为一个函数注入到 DOM 中,该函数会立即评估以返回结果。

对于您提供的代码示例,不需要动态评估。只有某些类别的 XSLT 应用程序实际上需要动态 XPath 评估。

在需要动态 XPath 评估的少数情况下,Saxon-CE 没有内置功能,因此您需要生成一个简单的“包装器”XSLT 并使用 Saxon-CE JavaSCript 执行它,而不是动态构建 XPath API。该技术用于PathEnq在线 XPath 2.0 评估程序。

以下代码使用单个“静态”XPath 表达式实现了与您的代码类似的内容 - 在此示例中,将另一个模板应用于所需的“事物”元素以创建可用的 HTML:

呈现的代码(语法高亮和格式化)

在此处输入图像描述

源代码:

<xsl:transform
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ixsl="http://saxonica.com/ns/interactiveXSLT"
xmlns:js="http://saxonica.com/ns/globalJS"
xmlns:prop="http://saxonica.com/ns/html-property"
xmlns:style="http://saxonica.com/ns/html-style-property"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs prop"
extension-element-prefixes="ixsl"
version="2.0"
>
<xsl:template name="main" match="/">
<xsl:call-template name="display"/>
</xsl:template>

<xsl:template name="display">
<xsl:param name="num" as="xs:string" select="'none'"/>
<xsl:param name="type" as="xs:string" select="'all'"/>
<xsl:param name="subtype" as="xs:string" select="'red'"/>

<xsl:variable name="thingsEl" select="things" as="element(things)"/>

<xsl:variable name="widget" as="element()+"
select="if ($num eq 'all')
then $thingsEl/thing[number = $num]
else if ($type ne 'all')
    then $thingsEl/thing[type = $type]
else $thingsEl/thing[subtypes/subtype = $subtype]"/>

<xsl:result-document href="#display" method="append-content">
<xsl:apply-templates select="$widget">
<xsl:sort select="name"/>
</xsl:apply-templates>
</xsl:result-document>

</xsl:template>

<xsl:template match="thing">
<ol>
<li>name: <xsl:value-of select="name"/></li>
<li>number: <xsl:value-of select="number"/></li>
<li>type: <xsl:value-of select="type"/></li>
<li>subtypes: 
<ol>
<xsl:apply-templates select="subtypes/subtype"/>
</ol>
</li>
</ol>
</xsl:template>

<xsl:template match="subtype">
<li><xsl:value-of select="."/></li>
</xsl:template>

</xsl:transform>

HTML 输出('display' div 元素的外部 HTML 视图)

<div id="display">
    <ol>
        <li>name: widget one</li>
        <li>number: 10</li>
        <li>type: metal</li>
        <li>subtypes: 
            <ol>
                <li>red</li>
            </ol></li>
    </ol>
    <ol>
        <li>name: widget two</li>
        <li>number: 11</li>
        <li>type: wood</li>
        <li>subtypes: 
            <ol>
                <li>red</li>
                <li>blue</li>
            </ol></li>
    </ol>
</div>
于 2013-01-22T17:41:25.840 回答