2010-04-29 54 views
5

我有一些我想要使用xslt进行处理的xml。大量的数据通过关键值对传递(见下文)。我正在努力如何将密钥的价值基础提取到变量中。我希望能够做到这样的事情:我怎样才能从我xslt xpath中的xml键/值对获取值?

<xsl:variable name="foo" select="/root/entry[key = 'foo']/value"/> 

但这似乎并不奏效。这里是示例xml。

<?xml version="1.0" encoding="ISO-8859-1"?> 
<root> 
    <entry> 
    <key> 
     foo 
    </key> 
    <value> 
     bar 
    </value> 
    </entry> 
</root> 

正确的xpath会是什么?

+0

好问题(+1)。你知道你选择的答案通常不正确吗?请参阅我的回答以获得解释和两个真正的解决方案。 :) – 2010-04-29 16:48:12

回答

5

以下转化显示了两种方法来实现这一点 - 有和没有使用<xsl:key>key()功能:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes"/> 

<xsl:key name="kValueByKey" 
    match="value" use="normalize-space(../key)"/> 

<xsl:template match="/"> 
    1. By key: <xsl:text/> 

    <xsl:copy-of select="key('kValueByKey', 'foo')"/> 

    2. Not using key: <xsl:text/> 

    <xsl:copy-of select="/*/*[normalize-space(key)='foo']/value"/> 
</xsl:template> 
</xsl:stylesheet> 

别注意,使用了normalize-space()功能的从的<key>值中去掉任何前导或尾随空格字符。

+0

似乎是两全其美的,对吗? – TahoeWolverine 2010-04-29 17:20:04

+0

@TahoeWolverine:在纯XPath中,*有*可以使用这个表达式。每当XPath由XSLT托管时,我总是更喜欢使用键 - 是不是很明显,键表达式比“纯粹的”XPath更简单?支持密钥的另一个非常有力的论据是,在大多数情况下,使用密钥的速度要快很多。 – 2010-04-29 17:29:37

+0

是的,我现在明白了。我有点困惑,因为我没有看到你在哪里定义变量。一旦我开始用这种方式创建变量,事情变得更加清晰。谢谢。 – TahoeWolverine 2010-04-29 17:47:31

4

你的XPath工作正常以下(等效)文件:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<root> 
<entry> 
    <key>foo</key> 
    <value> 
    bar 
    </value> 
</entry> 
</root> 

您可以使用XPath contains功能来获得相同的结果,而不重组的XML:

<xsl:variable name="foo" select="/root/entry[contains(key,'foo')]/value"/> 
+0

我应该知道它会是这样的。不幸的是,向创建xml的人解释xml更改将非常困难。我将使用xpath。非常感谢。 – TahoeWolverine 2010-04-29 15:10:05

+0

非常直接的解决方案,但如果你的XML中的是'fooz',那么它仍然包含'foo',并且你将会有错误的匹配。 – derloopkat 2013-12-12 10:14:16

2
<xsl:variable name="foo" select="/root/entry[key='foo']/value" /> 

这是完全匹配,从而确保有没有多余的空格或围绕富新行字符在XML。否则use replace function和一个正则表达式来修剪它们。