开发者

How can I select nodes from a tree whose markup is stored in a variable?

Consider the following XSLT script:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="text" encoding="iso-8859-1"/>

<xsl:variable name="stringmap">
<map>
<entry><key>red</key><value>rot<开发者_StackOverflow中文版;/value></entry>
<entry><key>green</key><value>gruen</value></entry>
<entry><key>blue</key><value>blau</value></entry>
</map>
</xsl:variable>

<xsl:template match="/">
<!-- IMPLEMENT ME -->
</xsl:template>

</xsl:stylesheet>

I'd like this script to print redgreenblue.

Is there any way to treat the XML markup which is stored in the stringmap variable as a document of its own which I can run XPath queries on? I'm basically looking for something like

<xsl:for-each select="document($stringmap)/map/entry">
    <xsl:value-of select="key"/>
</xsl:for-each>

(except that the document() function expects an URI).

Motivation: I have various long <xsl:choose> elements which map a given string to another string. I'd like to replace all those with a single template which takes a 'map' argument (which is a simple XML document). My hope is that I can then replace the <xsl:choose> with a simple statement like <xsl:value-of select="$stringmap/map/entry/value[../key='$givenkey']"/>

I'm using XSLT 1.0 using xsltproc.


You're almost right, using document('') will allow you to process node sets inside the current stylesheet:

<xsl:for-each select="document('')/xsl:stylesheet/xsl:variable[@name='stringmap']/map/entry">
    <xsl:value-of select="key"/>
</xsl:for-each>

It's not necessary to define the map node set as a variable in this case:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:data="some.uri" version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <data:map>
    <entry><key>red</key><value>rot</value></entry>
    <entry><key>green</key><value>gruen</value></entry>
    <entry><key>blue</key><value>blau</value></entry>
  </data:map>

  <xsl:template match="/">
    <xsl:for-each select="document('')/xsl:stylesheet/data:map/entry">
      <xsl:value-of select="key"/>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

If you do not use xsl:variable as a wrapper, you must remember that a top level elements must have a non null namespace URI.

In XSLT 2.0 it would've been possible to just iterate over the content in a variable:

<xsl:variable name="map">
  <entry><key>red</key><value>rot</value></entry>
  <entry><key>green</key><value>gruen</value></entry>
  <entry><key>blue</key><value>blau</value></entry>
</xsl:variable>

<xsl:template match="/">
  <xsl:for-each select="$map/entry">
    <xsl:value-of select="key"/>
  </xsl:for-each>
</xsl:template>


A posting by M. David Peterson just taught me how to make this work:

It's not necessary to have an <xsl:variable> for this case. Instead, I can embed the data document directly into the XSL stylesheet (putting it into a namespace for sanity) and then select elements from that. Here's the result:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:map="uri:map">

<xsl:output method="text" encoding="iso-8859-1"/>

<map:colors>
<entry><key>red</key><value>rot</value></entry>
<entry><key>green</key><value>gruen</value></entry>
<entry><key>blue</key><value>blau</value></entry>
</map:colors>

<xsl:template match="/">
<xsl:for-each select="document('')/*/map:colors/entry">
    <xsl:value-of select="key"/>
</xsl:for-each>
</xsl:template>

</xsl:stylesheet>

This generates the expected output redgreenblue.

The trick is to use document('') to get a handle to the XSLT document itself, then * to get into the toplevel xsl:stylesheet element and from there I can access the color map.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜