【问题标题】:Building dynamical xPath构建动态 xPath
【发布时间】:2012-06-19 20:35:13
【问题描述】:

我必须根据我在使用表达式语言制作 JSP 的 XSL 文件中的请求属性来使 xPath 动态化。所以现在我有了这个东西:

<xsl:variable name="xPath">@name='${categoryName}'</xsl:variable>
<xsl:for-each select="tar:products/category[$xPath]/subcategory">

但这不起作用。那么问题是如何解决这个问题并使 xPath 工作?


输入 XML:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tar:products SYSTEM "products.dtd" >
<?xml-stylesheet type='text/xsl' href='products2HTML.xsl'?>
<tar:products xmlns:tar="http://www.epam.com/products"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.epam.com/products products.xsd ">
<category name="Electronics">
    <subcategory name="mp3">
        <product name="iPod 4g">
            <provider>Apple</provider>
            <model>Qd246</model>
            <dateOfIssue>11-11-2012</dateOfIssue>
            <color>white</color>
            <notInStock/>
        </product>
        <product name="Cowon">
            <provider>Cowon</provider>
            <model>sF223</model>
            <dateOfIssue>13-12-2012</dateOfIssue>
            <color>black</color>
            <price>13456</price>
        </product>
        <product name="IRiver">
            <provider>IRiver e30</provider>
            <model>Ir234</model>
            <dateOfIssue>13-12-2012</dateOfIssue>
            <color>black</color>
            <price>13456</price>
        </product>
    </subcategory>
    <subcategory name="Computers">
        <product name="iMac">
            <provider>Apple</provider>
            <model>Mm232</model>
            <dateOfIssue>20-02-2012</dateOfIssue>
            <color>silver</color>
            <notInStock/>
        </product>
        <product name="PC">
            <provider>Acer</provider>
            <model>Ae135</model>
            <dateOfIssue>22-11-2012</dateOfIssue>
            <color>black</color>
            <price>13456</price>
        </product>
    </subcategory>
</category>
<category name="Toys">
    <subcategory name="Electronical toys">
        <product name="Cat">
            <provider>UrkToy</provider>
            <model>cC246</model>
            <dateOfIssue>11-11-2012</dateOfIssue>
            <color>grey</color>
            <price>1100</price>
        </product>
        <product name="Dog">
            <provider>LatToy</provider>
            <model>Ld223</model>
            <dateOfIssue>03-12-2012</dateOfIssue>
            <color>white</color>
            <price>13456</price>
        </product>
    </subcategory>
    <subcategory name="Fabric toys">
        <product name="Bear">
            <provider>RusToy</provider>
            <model>BB122</model>
            <dateOfIssue>20-02-2012</dateOfIssue>
            <color>brown</color>
            <notInStock/>
        </product>
        <product name="Bird">
            <provider>BelToy</provider>
            <model>Bb110</model>
            <dateOfIssue>05-11-2012</dateOfIssue>
            <color>red</color>
            <price>500</price>
        </product>
    </subcategory>
</category>
</tar:products>

我将参数categoryName 放入上一页的请求中,它已成功显示在我的页面上,所以问题不在其中。 以下是有关xsl 文件的更多信息:

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:tar="http://www.epam.com/products"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.epam.com/products products.xsd ">
<xsl:output method="html" />
<xsl:param name="categoryName" select="'${categoryName}'"></xsl:param>
<xsl:template match="/">
    <table border="1">
        <tr bgcolor="#CCCCCC">
            <td align="center">
                <strong>
                    Subcategories
                            </strong>
            </td>
        </tr>
        <xsl:value-of select="$categoryName"/><!-- this string works -->
        <xsl:for-each select="tar:products/category[@name=$categoryName]/subcategory">
            <xsl:sort order="descending" select="count(product)"
                data-type="number" />
            <a href="controller?command=products&amp;name={@name}">
            <tr bgcolor="#F5F5F5">
                <td>
                    <xsl:value-of select="@name" />
                    (
                    <xsl:value-of select="count(product)" />
                    )
                </td>

            </tr>
            </a>
        </xsl:for-each>
    </table>
    <form method="post" action="/controller?command=back">
        <input type="submit" value="Back"/>
    </form>
</xsl:template>
 </xsl:stylesheet>

当请求参数categoryName等于'Toys'时的预期输出:


实际输出:


已解决

在我的 java 类中,我在转换之前将参数放入请求中,但只需将其放入转换器参数中:

transformer.setParameter("categoryName", name);

【问题讨论】:

  • 您的 XSLT 引擎/版本是什么?

标签: jsp xslt xpath el dynamically-generated


【解决方案1】:

如果您真的需要动态构建 XPath,则需要使用扩展函数。例如,您可以使用EXSTL Dynamic Extension Function

但是,查看您相当简洁的代码示例,我不确定在这种情况下您是否需要额外的复杂性。您能否将两行简化为以下内容:

<xsl:for-each select="tar:products/category[@name=$categoryName]/subcategory">

【讨论】:

  • 您好!感谢您的宝贵时间,但很抱歉,这不起作用。它给了我没有任何错误的空白列表
  • 顺便说一句,categoryName 是一个请求参数,我试图在 EL 的帮助下得到它。据我了解,您建议将其定义为 xsl 变量。我做到了,但它不起作用......
  • 我认为如果您扩展您的问题以提供更多详细信息会有所帮助。例如,显示输入 XML 和预期输出会使事情更清楚。
【解决方案2】:

一般来说,你做不到。但也有供应商特定的解决方案:

  1. Tim 对 EXSLT 的引用是绝对正确的。 (dyn:evaluate())
  2. XALAN 有一个评估函数(参考:Using dynamic xpath in XSLT
  3. Saxon 有一个评估函数 (http://saxon.sourceforge.net/saxon7.9/extensions.html#evaluate)

另请参阅 Dimitre 的回答:dynamic xpath in xslt?

另外请注意,XSLT 3.0 将具有和 evaluate() 函数 (http://www.w3.org/TR/xslt-21/#element-evaluate)

最后,如果要评估的动态 XPATH 被限制为非常简单的形式(例如:由 / 运算符分隔的术语,没有轴和谓词),那么可以编写一个命名模板执行动态 XPATH 评估。但当然,这个模板的外观很大程度上取决于您对表达式的简单约束。

示例:

获取您的示例动态路径:

<xsl:variable name="xPath">@name='${categoryName}'</xsl:variable>

假设属性名称部分(本示例中的“名称”)和值部分(我认为您的意思是 $categoryName 而不是 ${categoryName} )都是可变的,但整体形式是其他表达式,换句话说: @some-name='some-string-value' 是固定的。然后你可以像这样解析路径表达式:

<xsl:variable name="name" select="'name'" /><!-- or use another computed value. -->
<xsl:variable name="value" select="'my-category-name'" /><!-- or use another computed value. -->
<xsl:for-each select="tar:products/category[@*[name()=$name][.=$value]]/subcategory">

【讨论】:

    【解决方案3】:

    如果要求是用“想象的”代码编写的,即用一种不完全是 XSLT 的语言编写的代码,总是很难回答这个问题。所以这个答案假设我已经正确地想象了你想要做什么。如果是这种情况,请替换:

    <xsl:variable name="xPath">@name='${categoryName}'</xsl:variable>
    <xsl:for-each select="tar:products/category[$xPath]/subcategory">
    

    通过这个:

    <xsl:for-each select="tar:products/category[@name = $categoryName]/subcategory">
    

    对于更一般的问题,XSLT 中没有标准工具可以从字符串动态生成 XPath 表达式。但是许多产品都提供了扩展功能来实现这一点:例如参见 saxon:evaluate()。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-05
      • 2017-02-26
      • 2013-09-15
      • 1970-01-01
      • 1970-01-01
      • 2021-06-09
      • 1970-01-01
      相关资源
      最近更新 更多