【问题标题】:Saxon-ce dynamic xpath evaluationSaxon-ce 动态 xpath 评估
【发布时间】:2013-01-22 12:14:36
【问题描述】:

我正在尝试在带有 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。如果他们选择蓝色的子类型,它将显示小部件 2 和 3 的名称。

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

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

这有帮助吗?

【问题讨论】:

    标签: xslt-2.0 saxon xpath-2.0


    【解决方案1】:

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

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

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

    在少数需要动态 XPath 评估的情况下,Saxon-CE 没有内置功能,因此您需要生成一个简单的“包装器”XSLT 并使用 Saxon 执行它,而不是仅仅动态构建 XPath -CE JavaSCript 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>
    

    【讨论】:

    • 感谢您的信息。但是,这并不能完全满足我的需要。 (我的错,我在原始帖子中没有明确说明)。用户通过组合框选择各种输入参数($num、$type 和 $subtype)以过滤作为名称元素值列表的显示。所以我需要的是一种根据用户的选择动态地制作 xpath 的方法。我在 xpathExp 变量中的内容生成了正确的字符串,但我需要一种方法将其转换为可以在 for-each 语句中使用的内容。
    • @JeffreyHersh 请尝试提供更具代表性的示例或更多背景来说明您为什么需要动态 XPath - 然后我可以为您提供一个有代表性的解决方案。请注意,仅仅因为 XPath 中使用的 vsome 变量是由用户在运行时提供的,并不影响 XPath 本身是否可以预编译——这就是 XPath 变量的用途。
    • 当然。我在上面提供了我希望是一个更好的 XML 示例和我想要完成的解释。
    猜你喜欢
    • 2021-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    • 2011-06-03
    • 2010-11-03
    • 1970-01-01
    相关资源
    最近更新 更多