views:

317

answers:

2

I have some xml that I want to process using xslt. A good amount of the data comes through in key value pairs (see below). I am struggling with how to extract the value base on the key into a variable. I would like to be able to do something like this:

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

but that doesn't seem to work. Here is sample xml.

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

What would the correct xpath be for this?

+2  A: 

Your XPath works fine for the following (equivalent) document:

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

You can use the xpath contains function to get the same result without restructuring your XML:

<xsl:variable name="foo" select="/root/entry[contains(key,'foo')]/value"/>
Oded
I should have known it would have been something like that. Unfortunately explaining the xml change to the people creating the xml would be overly difficult. I will use the xpath. Thanks a lot.
TahoeWolverine
+2  A: 

The following transformation shows two ways to achieve this -- with and without the use of <xsl:key> and the key() function:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
 <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>

Do note the use of the normalize-space() function to strip any leading or trailing whitespace characters from the value of <key>.

Dimitre Novatchev
<xsl:variable name="foo" select="/root/entry[normalize-space(key) = 'foo']/value"/>seems to be the best of both worlds, correct?
TahoeWolverine
@TahoeWolverine: In pure XPath one *has* to use this expression. Whenever XPath is hosted by XSLT I'd always prefer using keys -- isn't it noticeable how the key-expression is simpler than the "pure" XPath one? Another very strong argument in favor of keys is that in most cases using keys is many factors of magnitude faster.
Dimitre Novatchev
Yes I do see that now. I was a bit confused because I did not see where you were defining variables. Once I started to create the variables this way, things became quite a bit cleaner. Thanks.
TahoeWolverine