Saxon-ce动态xpath评估

时间:2013-01-22 12:14:36

标签: xslt-2.0 saxon xpath-2.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>

用户可以通过Dropbox为数字,类型和子类型选择值。根据用户的选择,显示事物名称列表。因此,例如,如果用户选择11的数字和红色的子类型,则它将仅显示小部件2。如果他们选择蓝色的子类型,它将显示小部件2和3的名称。

所以基础xpath过滤器就是东西/东西。如果用户选择一个数字值,我想将[number = $ num]附加到xpath表达式,所以ti将是thing / thing [number = $ num]。如果他们选择多个项目,让我们说数字和类型,[number = $ num] [type = $ type]将附加到基础xpath,我会有东西/东西[number = $ num] [type = $型]。

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

这有帮助吗?

1 个答案:

答案 0 :(得分:0)

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

  

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

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

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

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

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

enter image description here

源代码:

<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元素的outerHTML视图)

<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>