Ilya
Ilya

Reputation: 29693

xslt, fn:subsequance, java transformation

I have XML data

   <logData>
      <log>
         <id>1</id>
      </log> 
      <log>
         <id>2</id>
      </log> 
      <log>
         <id>3</id>
      </log> 
      <log>
         <id>4</id>
      </log> 
   </logData>  

I want get only part of logs using xslt transformation using fn:subsequence function

here is my xslt

<?xml version="1.0" encoding="UTF-8"?> 
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:fn="http://www.w3.org/2006/xpath-functions" version="1.0" >
       <xsl:output method="xml" indent="yes" />     
       <xsl:strip-space elements="*"/>

       <xsl:template match="/logData" >
          <xsl:element name="log">
             <xsl:copy-of select="fn:subsequence(./log, 2, 3)"/>
          </xsl:element>
       </xsl:template>
    </xsl:stylesheet>   

and I get

ERROR:  'The first argument to the non-static Java function 'subsequence' is not a valid object reference.'  

I am using Java transformation API, part of Java SE 1.6.
Can you help me?

Upvotes: 1

Views: 584

Answers (2)

Michael Kay
Michael Kay

Reputation: 163458

Since you are using Java, all you need to do is to ensure that your code loads an XSLT 2.0 processor instead of XSLT 1.0. The default XSLT processor in the JDK only supports XSLT 1.0.

Download Saxon-HE, and set the system property

-Djavax.xml.transform.TransformerFactory=net.sf.saxon.TransformerFactoryImpl

and your code should work.

(Of course, as Dimitre shows, this transformation can be done easily enough in XSLT 1.0. But by sticking to XSLT 1.0 you are are trying to move with your feet tied together at the ankles. XSLT 2.0 is vastly more powerful and easier to use, and it's available in your environment, so use it.)

Upvotes: 1

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243529

<xsl:copy-of select="fn:subsequence(./log, 2, 3)"/>

The function subsequence() is defined in XPath 2.0 and is available only in an XSLT 2.0 processor.

In XSLT 1.0 use:

<xsl:copy-of select="log[position() > 1 and not(position() > 4)]"/>

Here is a complete transformation:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/*">
     <xsl:copy-of select="log[position() > 1 and not(position() > 4)]"/>
 </xsl:template>
</xsl:stylesheet>

When this is applied on the provided XML document:

<logData>
    <log>
        <id>1</id>
    </log>
    <log>
        <id>2</id>
    </log>
    <log>
        <id>3</id>
    </log>
    <log>
        <id>4</id>
    </log>
</logData>

the wanted, correct result is produced:

<log>
   <id>2</id>
</log>
<log>
   <id>3</id>
</log>
<log>
   <id>4</id>
</log>

Upvotes: 1

Related Questions