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

前端 未结 2 999
北荒
北荒 2021-01-06 19:38

Consider the following XSLT script:




        
相关标签:
2条回答
  • 2021-01-06 20:07

    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 讨论(0)
  • 2021-01-06 20:15

    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>
    
    0 讨论(0)
提交回复
热议问题