Result Tree Fragments and Node-Sets

When you use an XML fragment to initialize a variable or a parameter, then the variable or parameter is of the

  "result tree fragment" datatype. This is an XSLT 1.0 specific datatype [just like node-set, but slightly different].
  A result tree fragment is equivalent to a node-set that contains just the root node.
  You cannot apply operators like "/", "//" or predicate on a result tree fragments. They are only applicable for node-set datatypes.
  Typically,when you perform a "select" in XSLT, what you get is a node-set. 
  For instance, 
  <xsl:variable name="countryNames" select="/tns:Countries/tns:Country"/>
  means that the variable countryNames contains a node-set of "Country" nodes. You can apply operators like "/" on this variable, for instance 
  <xsl:for-each select="$countryNames/@name">
    . . . 
  </xsl:for-each>

  But you cannot perform this kind of an operation on a result tree fragment.

  There are two ways to solve this issue.

a) In XSLT 1.0

The resolution of this is to convert the result tree fragment into a node-set. I am not aware of any oracle specific xpath extension functions that can do this trick for you. You could use EXSLT to achieve this.
EXSLT provides some very useful extensions to XSLT.They have defined an extension function node-set() that converts result tree fragments into node-sets. Alternatively, you could also write your own java routine to convert between result tree fragments and node-sets. 
I am an XSLT with the EXSLT xpath function for your reference.  Note the namespace declaration for exsl, and the function usage.

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:p1="http://example.org"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:param name="param1">
  <FileList>
    <File Name='a' valid='true' automated='false'/>
    <File Name='b' valid='true' automated='false'/>
    <File Name='c' valid='true' automated='false'/>
    <File Name='d' valid='true' automated='false'/>
    <File Name='e' valid='true' automated='false'/>
    <File Name='f' valid='true' automated='false'/>
  </FileList>
</xsl:param>
<xsl:template match="/">
  <ExternalAccess>
    <Query>
        <Parameters>
            <xsl:for-each select="exsl:node-set($param1)/FileList/File">
                <xsl:variable name="secondary" select="."/>
                <RetrievedFile>
                    <xsl:attribute name="Name">
                        <xsl:value-of select='@Name'/>
                    </xsl:attribute>
                    <xsl:attribute name="valid">
                        <xsl:value-of select='@valid'/>
                    </xsl:attribute>
                    <xsl:attribute name="automated">
                        <xsl:value-of select='@automated'/>
                    </xsl:attribute>
                </RetrievedFile>
            </xsl:for-each>
        </Parameters>
    </Query>
  </ExternalAccess>
</xsl:template>

</xsl:stylesheet>

b) Use XSLT 2.0

You can code your transformations in XSLT 2.0.  XSLT 2.0 deprecates ResultTreeFragments i.e. if you are modeling an XSLT 2.0 transformation, and you create a variable or a parameter that holds a tree fragment, it is implicitly a node sequence. You could then use path expressions against these variables and parameters. To make your transformations executed by an XSLT 2.0 processor, simply change the "version" attribute on the &lt;xsl:stylesheet> to "2.0".

With this approach, you can use the select expression "$param1/FileList/File" to iterate over the File elements witihn the XSLT parameter.

Here is the XSLT 2.0 code for this approach.

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:p1="www.example.org">
<xsl:param name="param1">
<FileList>
<File Name='a' valid='true' automated='false'/>
<File Name='b' valid='true' automated='false'/>
<File Name='c' valid='true' automated='false'/>
<File Name='d' valid='true' automated='false'/>
<File Name='e' valid='true' automated='false'/>
<File Name='f' valid='true' automated='false'/>
</FileList>
</xsl:param>
<xsl:template match="/">
<ExternalAccess>
      <Query>
            <Parameters>
                <xsl:for-each select="$param1/FileList/File">
                       <xsl:variable name="secondary" select="."/>
                               <RetrievedFile>
                                       <xsl:attribute name="Name">
                                           <xsl:value-of select='@Name'/>
                                       </xsl:attribute>
                                       <xsl:attribute name="valid">
                                           <xsl:value-of select='@valid'/>
                                       </xsl:attribute>
                                       <xsl:attribute name="automated">
                                           <xsl:value-of
select='@automated'/>
                                       </xsl:attribute>
                                 </RetrievedFile>
                </xsl:for-each>
      </Parameters>
  </Query>
</ExternalAccess>
</xsl:template>
</xsl:stylesheet>

Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

Principal Product Manager

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today