问题描述
我有一个我似乎无法解决的特殊问题.
I have a particular problem that I can't seem to solve.
是否可以在不使用额外模板或 for-each 的情况下使用 xpath 和 xslt 选择所有节点?
Is it possible to select all nodes using xpath and xslt without the use of additional templates or for-each?
示例 xml:
<aaa id="11">
<aaa id="21"></aaa>
<bbb id="22">
<aaa id="31"></aaa>
<bbb id="32"></bbb>
<ccc id="33"></ccc>
<ddd id="34"></ddd>
<ddd id="35"></ddd>
<ddd id="36"></ddd>
</bbb>
<ccc id="23"></ccc>
<ccc id="24"></ccc>
</aaa>
用户可以通过表单输入 xpath 表达式,例如:
A user has the ability to type in an xpath expression through a form, such as:
//aaa/bbb/ddd/@id
用户希望从以下位置接收 ID:
The user would expect to receive the ids from:
<ddd id="34"></ddd>
<ddd id="35"></ddd>
<ddd id="36"></ddd>
输出:
34 35 36
我能够实现这一目标的唯一方法是使用额外的模板和 for-each:
The only ways I have been able to achieve this is by using additional templates and for-each:
For-each way:
For-each way:
<xsl:template match="/">
<html>
<body>
<xsl:for-each select="//aaa/bbb/ddd">
<tr>
<td>
<xsl:value-of select="@id" />
</td>
</tr>
</xsl:for-each>
</body>
</html>
</xsl:template>
附加模板方式:
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="//aaa/bbb/ddd">
<xsl:value-of select="@id"/>
</xsl:template>
这些示例中的每一个都需要额外的工作才能将@id 从原始表达式中分离出来.我想按原样使用用户输入的表达式,然后将其插入某处.
Each of these examples require extra work to detach the @id from the original expression. I would like to use the user inputted expression as is, and just plug it in somewhere.
我尝试了以下方法,我认为可以选择全部,但它只返回第一个实例:
I have tried the following, which I thought would select all, but it only returns the first instance:
<xsl:template match="/">
<html>
<body>
<xsl:value-of select="//aaa/bbb/ddd/@id"/>
</body>
</html>
</xsl:template>
是否有解决我的问题的方法(即按原样插入用户输入的表达式的方法?)
Is there a solution to my problem (i.e. a way to just plug in the user inputted expression as is?)
注意 - 我需要一个可以处理用户给出的任何 xpath 表达式的解决方案......无论多么复杂.
如果您需要进一步说明,请告诉我.我已尽力解释,但可能我做得不太好.在此先感谢您的耐心等待!
Let me know if you need any further clarification.. I tried my best to explain it, but maybe I didn't do that very well.. Thank you in advance for your patience!
谢谢!:)
推荐答案
使用此样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="node-set" select="/aaa/bbb//ddd/@id"/>
<xsl:template match="/">
<html>
<body>
<table>
<tr>
<th>Type</th>
<th>Name</th>
<th>Value</th>
</tr>
<xsl:apply-templates select="$node-set" mode="result"/>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="@*|node()" mode="result">
<tr>
<td>
<xsl:choose>
<xsl:when test="self::*">Element</xsl:when>
<xsl:when test="self::text()">Text</xsl:when>
<xsl:when test="self::comment()">Comment</xsl:when>
<xsl:when test="self::processing-instruction()">PI</xsl:when>
<xsl:when test="count(.|/)=1">Root</xsl:when>
<xsl:when test="count(.|../@*)=count(../@*)">Attribute</xsl:when>
<xsl:when test="count(.|../namespace::*)=count(../namespace::*)">Namespace</xsl:when>
</xsl:choose>
</td>
<td>
<xsl:value-of select="name()"/>
</td>
<th>
<xsl:value-of select="."/>
</th>
</tr>
</xsl:template>
</xsl:stylesheet>
结果:
<html>
<body>
<table>
<tr>
<th>Type</th>
<th>Name</th>
<th>Value</th>
</tr>
<tr>
<td>Attribute</td>
<td>id</td>
<th>34</th>
</tr>
<tr>
<td>Attribute</td>
<td>id</td>
<th>35</th>
</tr>
<tr>
<td>Attribute</td>
<td>id</td>
<th>36</th>
</tr>
</table>
</body>
</html>
注意:如果 $node-set 不是节点集会报错.
Note: It would be an error if $node-set isn't a node set.
编辑:添加了完整的节点类型测试,以证明此样式表适用于对节点集求值的任何 XPath 表达式.
Edit: Added complete node type test in order to prove that this stylesheet works with any XPath expression wich eval to a node set.
Edit 2:添加了 template/@mode
以免错过 root.
Edit 2: Added template/@mode
in order to not miss root.
这篇关于使用 xpath 和 xslt 选择所有匹配的节点(没有额外的模板或 for-each)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!