我必须根据XSL文件中的请求属性使xPath动态化,使用表达式语言制作JSP。所以现在我有这个东西:
<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&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类中,我在转换之前将参数放入请求中,但只需将其放入transformator参数中:
transformer.setParameter("categoryName", name);
答案 0 :(得分:2)
如果您确实需要动态构建XPath,则需要使用扩展功能。例如,您可以使用EXSTL Dynamic Extension Function。
但是,看看你相当简洁的代码示例,我不确定在这种情况下你需要额外的复杂性。你可以将两行简化为以下内容:
<xsl:for-each select="tar:products/category[@name=$categoryName]/subcategory">
答案 1 :(得分:2)
一般情况下,你不能这样做。但是有特定于供应商的解决方案:
另见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>
假设属性名称部分(此示例中的'name')和值部分(我认为你的意思是$ 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">
答案 2 :(得分:1)
总是很难回答一个问题,即需求是用“虚构”代码编写的 - 也就是说,代码是用不完全是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()。