Problem using xslt key() function
(edited to include suggestions from Martin Honnen)
Hello All,
I've been trying to get the key function to work correctly in the stylesheet below.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:date="http://www.oracle.com/XSL/Transform/java/java.util.Date"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:m="http://mapping.tables" >
<xsl:key name="preferences" match="preferences/preference" use="@code"/>
<xsl:template match="Reservation/Detail" >
<xsl:for-each select="Preferences/Preference">
<xsl:if test ="string-length(./PreferenceCode)>0">
    * (<xsl:value-of select="./PreferenceCode"/>)
<xsl:choose>
<xsl:when test="./PreferenceCode!='PETS'">
<xsl:call-template name="prefmap">
<xsl:with-param name="code" select="./PreferenceCode"/&g开发者_运维百科t;
</xsl:call-template>
<br/><br/>
</xsl:when>
</xsl:choose>
</xsl:if>
</xsl:for-each>
</xsl:template
<xsl:template name="prefmap">
<xsl:param name="code"/>
You got here (called template) with code <xsl:value-of select="$code"/>
<xsl:for-each select="document('')">
<xsl:value-of select="key('preferences',$code)"/>
</xsl:for-each>
</xsl:template>
<m:Maps xmlns="">
<preferences>
<preference code="ANT">
Hypoallergenic Bedding
</preference>
<preference code="NSK">
Non-smoking Room
</preference>
<preference code="SMK">
Smoking Room
</preference>
</preferences>
</m:Maps>
</xsl:stylesheet>
It takes a input (that I don't control) and produces this:
* (ANT) You got here (called template) with code ANT
* (EARLY) You got here (called template) with code EARLY
* (NSK) You got here (called template) with code NSK
When I was expecting:
* (ANT) You got here (called template) with code ANT
Hypoallergenic Bedding
* (EARLY) You got here (called template) with code EARLY
* (NSK) You got here (called template) with code NSK
Non-smoking Room
I tried to include this snippet in the main template to debug, but it produced no output:
<xsl:for-each select="key('preferences',./PreferenceCode)">
<p>
Code: <xsl:value-of select="@code"/><br />
Description: <xsl:value-of select="."/>
</p>
</xsl:for-each>
Do I have a problem with my key definition or the way that I am trying to use it?
Thanks all in advance.
Are you trying to put data in your stylesheet with those preferences/pref
elements? Shouldn't those be in a separate namespace? And keys are built per each document and the key
function with XSLT 1.0 looks up nodes in the document the context node belongs to. If you want to look up nodes in the stylesheet itself then you need to change the context node first with e.g. <xsl:for-each select="document('')"><xsl:value-of select="key('preferences', $code)"/></xsl:for-each>
. Then drop the leading /
from the match
attribute value and make sure you put the elements in a container element in a separate namespace e.g.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:date="http://www.oracle.com/XSL/Transform/java/java.util.Date"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:m="http://mapping.tables"
xmlns:data="http://example.com/data">
<xsl:key name="preferences" match="preferences/pref" use="@code"/>
<data:data xmlns="">
<preferences>
<pref code="ANT">
Hypoallergenic Bedding
</pref>
<pref code="NSK">
Non-smoking Room
</pref>
<pref code="SMK">
Smoking Room
</pref>
</preferences>
</data:data>
Do I have a problem with my key definition or the way that I am trying to use it?
There is no problem with any of them:
I cannot reproduce the reported output. This means that if there really is any problem, it is in the code not shown to us.
The provided transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:date="http://www.oracle.com/XSL/Transform/java/java.util.Date"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:m="http://mapping.tables" >
<xsl:key name="preferences" match="preferences/preference" use="@code"/>
<xsl:template match="Reservation/Detail" >
<xsl:for-each select="Preferences/Preference">
<xsl:if test ="string-length(./PreferenceCode)>0">     * (
<xsl:value-of select="./PreferenceCode"/>)
<xsl:choose>
<xsl:when test="./PreferenceCode!='PETS'">
<xsl:call-template name="prefmap">
<xsl:with-param name="code" select="./PreferenceCode"/>
</xsl:call-template>
<br/>
<br/>
</xsl:when>
</xsl:choose>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template name="prefmap">
<xsl:param name="code"/> You got here (called template) with code
<xsl:value-of select="$code"/>
<xsl:for-each select="document('')">
<xsl:value-of select="key('preferences',$code)"/>
</xsl:for-each>
</xsl:template>
<m:Maps xmlns="">
<preferences>
<preference code="ANT">
Hypoallergenic Bedding
</preference>
<preference code="NSK">
Non-smoking Room
</preference>
<preference code="SMK">
Smoking Room
</preference>
</preferences>
</m:Maps>
</xsl:stylesheet>
when applied on the following XML document (no XML document was provided in the question!):
<Reservation>
<Detail>
<Preferences>
<Preference>
<PreferenceCode>ANT</PreferenceCode>
</Preference>
<Preference>
<PreferenceCode>NSK</PreferenceCode>
</Preference>
<Preference>
<PreferenceCode>SMK</PreferenceCode>
</Preference>
<Preference>
<PreferenceCode>PETS</PreferenceCode>
</Preference>
</Preferences>
</Detail>
</Reservation>
produces exactly the expected result:
<?xml version="1.0" encoding="utf-8"?>
* (
ANT)
You got here (called template) with code
ANT
Hypoallergenic Bedding
<br xmlns="http://www.w3.org/1999/xhtml" xmlns:date="http://www.oracle.com/XSL/Transform/java/java.util.Date" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:m="http://mapping.tables"/><br xmlns="http://www.w3.org/1999/xhtml" xmlns:date="http://www.oracle.com/XSL/Transform/java/java.util.Date" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:m="http://mapping.tables"/> * (
NSK)
You got here (called template) with code
NSK
Non-smoking Room
<br xmlns="http://www.w3.org/1999/xhtml" xmlns:date="http://www.oracle.com/XSL/Transform/java/java.util.Date" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:m="http://mapping.tables"/><br xmlns="http://www.w3.org/1999/xhtml" xmlns:date="http://www.oracle.com/XSL/Transform/java/java.util.Date" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:m="http://mapping.tables"/> * (
SMK)
You got here (called template) with code
SMK
Smoking Room
<br xmlns="http://www.w3.org/1999/xhtml" xmlns:date="http://www.oracle.com/XSL/Transform/java/java.util.Date" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:m="http://mapping.tables"/><br xmlns="http://www.w3.org/1999/xhtml" xmlns:date="http://www.oracle.com/XSL/Transform/java/java.util.Date" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:m="http://mapping.tables"/> * (
PETS)
Do Note:
All the following 7 XSLT processors produce exactly the same (above) result: MSXML3/4, XslCompiledTransform, XslTransform, Saxon 6.5.4, Saxon 9.1.05, AltovaXML (XmlSPY).
精彩评论