class XML::XSLT
Constants
- DEFAULT_URL
- DEFAULT_VENDOR
- DEFAULT_VERSION
- ENGINE_VERSION
- LIBXML_VERSION
- LIBXSLT_VERSION
- MAX_DEPTH
- MAX_SORT
- NAMESPACE_LIBXSLT
- NAMESPACE_NORM_SAXON
- NAMESPACE_SAXON
- NAMESPACE_XALAN
- NAMESPACE_XT
- RUBY_XSLT_VERSION
- XSLT_NAMESPACE
Public Class Methods
oXSLT = ::new
Create a new XML::XSLT object
VALUE ruby_xslt_new( VALUE class ) { RbTxslt *pRbTxslt; pRbTxslt = (RbTxslt *)malloc(sizeof(RbTxslt)); if( pRbTxslt == NULL ) rb_raise(rb_eNoMemError, "No memory left for XSLT struct"); pRbTxslt->iXmlType = RUBY_XSLT_XMLSRC_TYPE_NULL; pRbTxslt->xXmlData = Qnil; pRbTxslt->oXmlObject = Qnil; pRbTxslt->xXmlString = Qnil; pRbTxslt->tXMLDocument = NULL; pRbTxslt->iXslType = RUBY_XSLT_XSLSRC_TYPE_NULL; pRbTxslt->xXslData = Qnil; pRbTxslt->oXslObject = Qnil; pRbTxslt->xXslString = Qnil; pRbTxslt->tParsedXslt = NULL; pRbTxslt->iXmlResultType = RUBY_XSLT_XMLSRC_TYPE_NULL; pRbTxslt->xXmlResultCache = Qnil; pRbTxslt->pxParams = Qnil; pRbTxslt->iNbParams = 0; xmlInitMemory(); xmlSubstituteEntitiesDefault( 1 ); xmlLoadExtDtdDefaultValue = 1; return( Data_Wrap_Struct( class, ruby_xslt_mark, ruby_xslt_free, pRbTxslt ) ); }
registers a block to be called when libxml2 or libxslt encounter an error eg:
XML::XSLT.registerErrorHandler do |error_str| $stderr.puts error_str end
# File lib/xml/xslt.rb, line 67 def self.registerErrorHandler(&block) @@error_handler = block end
sets up a block for callback when the XPath function namespace:name( … ) is encountered in a stylesheet.
XML::XSLT.registerExtFunc(namespace_uri, name) do |*args| puts args.inspect end
XPath arguments are converted to Ruby objects accordingly:
- number (eg.
1
) -
Float
- boolean (eg.
false()
) -
TrueClass/FalseClass
- nodeset (eg.
/entry/*
) -
Array of REXML::Elements
- variable (eg.
$var
) -
UNIMPLEMENTED
It works the same in the other direction, eg. if the block returns an array of REXML::Elements the value of the function will be a nodeset.
Note: currently, passing a nodeset to Ruby or REXML::Elements to libxslt serializes the nodes and then parses them. Doing this with large sets is a bad idea. In the future they'll be passed back and forth using Ruby's libxml2 bindings.
# File lib/xml/xslt.rb, line 47 def self.registerExtFunc(namespace, name, &block) @@extFunctions[namespace] ||= {} @@extFunctions[namespace][name] = block XML::XSLT.registerFunction(namespace, name) end
internal use only.
VALUE ruby_xslt_reg_function( VALUE class, VALUE namespace, VALUE name ) { xsltRegisterExtModuleFunction( BAD_CAST StringValuePtr(name), BAD_CAST StringValuePtr(namespace), xmlXPathFuncCallback ); return Qnil; } /** * string = oXSLT.xsl_to_s( ) */ VALUE ruby_xslt_to_s( VALUE self ) { VALUE vStrOut; RbTxslt *pRbTxslt; xsltStylesheetPtr vXSLTSheet = NULL; const char *xKlassName = rb_class2name( CLASS_OF( self ) ); Data_Get_Struct( self, RbTxslt, pRbTxslt ); //vXSLTSheet = xsltParseStylesheetDoc( xmlParseMemory( StringValuePtr( pRbTxslt->xXslData ), strlen( StringValuePtr( pRbTxslt->xXslData ) ) ) ); vXSLTSheet = pRbTxslt->tParsedXslt; if (vXSLTSheet == NULL) return Qnil; vStrOut = rb_str_new( 0, strlen(xKlassName)+1024 ); (void) sprintf( RSTRING_PTR(vStrOut), "#<%s: parent=%p,next=%p,imports=%p,docList=%p," "doc=%p,stripSpaces=%p,stripAll=%d,cdataSection=%p," "variables=%p,templates=%p,templatesHash=%p," "rootMatch=%p,keyMatch=%p,elemMatch=%p," "attrMatch=%p,parentMatch=%p,textMatch=%p," "piMatch=%p,commentMatch=%p,nsAliases=%p," "attributeSets=%p,nsHash=%p,nsDefs=%p,keys=%p," "method=%s,methodURI=%s,version=%s,encoding=%s," "omitXmlDeclaration=%d,decimalFormat=%p,standalone=%d," "doctypePublic=%s,doctypeSystem=%s,indent=%d," "mediaType=%s,preComps=%p,warnings=%d,errors=%d," "exclPrefix=%s,exclPrefixTab=%p,exclPrefixNr=%d," "exclPrefixMax=%d>", xKlassName, vXSLTSheet->parent, vXSLTSheet->next, vXSLTSheet->imports, vXSLTSheet->docList, vXSLTSheet->doc, vXSLTSheet->stripSpaces, vXSLTSheet->stripAll, vXSLTSheet->cdataSection, vXSLTSheet->variables, vXSLTSheet->templates, vXSLTSheet->templatesHash, vXSLTSheet->rootMatch, vXSLTSheet->keyMatch, vXSLTSheet->elemMatch, vXSLTSheet->attrMatch, vXSLTSheet->parentMatch, vXSLTSheet->textMatch, vXSLTSheet->piMatch, vXSLTSheet->commentMatch, vXSLTSheet->nsAliases, vXSLTSheet->attributeSets, vXSLTSheet->nsHash, vXSLTSheet->nsDefs, vXSLTSheet->keys, vXSLTSheet->method, vXSLTSheet->methodURI, vXSLTSheet->version, vXSLTSheet->encoding, vXSLTSheet->omitXmlDeclaration, vXSLTSheet->decimalFormat, vXSLTSheet->standalone, vXSLTSheet->doctypePublic, vXSLTSheet->doctypeSystem, vXSLTSheet->indent, vXSLTSheet->mediaType, vXSLTSheet->preComps, vXSLTSheet->warnings, vXSLTSheet->errors, vXSLTSheet->exclPrefix, vXSLTSheet->exclPrefixTab, vXSLTSheet->exclPrefixNr, vXSLTSheet->exclPrefixMax ); vStrOut = strlen(RSTRING_PTR(vStrOut)); if( OBJ_TAINTED(self) ) OBJ_TAINT(vStrOut); // xsltFreeStylesheet(vXSLTSheet); return( vStrOut ); }
Public Instance Methods
mediaTypeString = #mediaType( )
Return the XSL output's media type
VALUE ruby_xslt_media_type( VALUE self ) { RbTxslt *pRbTxslt; xsltStylesheetPtr vXSLTSheet = NULL; Data_Get_Struct( self, RbTxslt, pRbTxslt ); vXSLTSheet = pRbTxslt->tParsedXslt; if ( (vXSLTSheet == NULL) || (vXSLTSheet->mediaType == NULL) ) { return Qnil; } else { return rb_str_new2( (char *)(vXSLTSheet->mediaType) ); } }
oXSLT.parameters={ “key” => “value”, “key” => “value”, … }
VALUE ruby_xslt_parameters_set( VALUE self, VALUE parameters ) { RbTxslt *pRbTxslt; Check_Type( parameters, T_HASH ); Data_Get_Struct( self, RbTxslt, pRbTxslt ); if( !NIL_P(parameters) ){ pRbTxslt->pxParams = rb_ary_new( ); // each_pair and process_pair defined ind parameters.c (void)rb_iterate( each_pair, parameters, process_pair, pRbTxslt->pxParams ); pRbTxslt->iNbParams = FIX2INT( rb_funcall( parameters, rb_intern("size"), 0, 0 ) ) * 2 + 2; pRbTxslt->iXmlResultType = RUBY_XSLT_XMLSRC_TYPE_NULL; } return( Qnil ); }
#save( “result.xml” )
Save the stylesheet transformation to file
VALUE ruby_xslt_save( VALUE self, VALUE xOutFilename ) { char *xOut; VALUE rOut; FILE *fOutFile; rOut = ruby_xslt_serve( self ); if( rOut != Qnil ) { xOut = StringValuePtr( rOut ); fOutFile = fopen( StringValuePtr( xOutFilename ), "w" ); if( fOutFile == NULL ) { free( xOut ); rb_raise( rb_eRuntimeError, "Can't create file %s\n", StringValuePtr( xOutFilename ) ); rOut = Qnil; } else { fwrite( xOut, 1, strlen( xOut ), fOutFile ); fclose( fOutFile ); } } return( rOut ); }
output_string = #serve( )
Return the stylesheet transformation
VALUE ruby_xslt_serve( VALUE self ) { RbTxslt *pRbTxslt; char *xOut; char **pxParams = NULL; Data_Get_Struct( self, RbTxslt, pRbTxslt ); if( pRbTxslt->iXmlResultType == RUBY_XSLT_XMLSRC_TYPE_NULL ) { if( pRbTxslt->pxParams != Qnil ){ int iCpt; pxParams = (char **)ALLOCA_N( void *, pRbTxslt->iNbParams ); MEMZERO( pxParams, void *, pRbTxslt->iNbParams ); for( iCpt = 0; iCpt <= pRbTxslt->iNbParams - 3; iCpt++ ) { VALUE tmp = rb_ary_entry( pRbTxslt->pxParams, iCpt ); pxParams[iCpt] = StringValuePtr( tmp ); } } if( pRbTxslt->iXslType != RUBY_XSLT_XSLSRC_TYPE_NULL && pRbTxslt->iXmlType != RUBY_XSLT_XMLSRC_TYPE_NULL ) { xOut = parse( pRbTxslt->tParsedXslt, pRbTxslt->tXMLDocument, pxParams ); if( xOut == NULL ) { pRbTxslt->xXmlResultCache = Qnil; pRbTxslt->iXmlResultType = RUBY_XSLT_XMLSRC_TYPE_NULL; } else { pRbTxslt->xXmlResultCache = rb_str_new2( xOut ); pRbTxslt->iXmlResultType = RUBY_XSLT_XMLSRC_TYPE_STR; free( xOut ); } } else { pRbTxslt->xXmlResultCache = Qnil; pRbTxslt->iXmlResultType = RUBY_XSLT_XMLSRC_TYPE_NULL; } } return( pRbTxslt->xXmlResultCache ); }
#xml=<data|REXML::Document|XML::Smart|file>
Set XML data.
Parameter can be type String, REXML::Document, XML::Smart::Dom or Filename
Examples :
# Parameter as String oXSLT.xml = <<XML <?xml version="1.0" encoding="UTF-8"?> <test>This is a test string</test> XML # Parameter as REXML::Document require 'rexml/document' oXSLT.xml = REXML::Document.new File.open( "test.xml" ) # Parameter as XML::Smart::Dom require 'xml/smart' oXSLT.xml = XML::Smart.open( "test.xml" ) # Parameter as Filename oXSLT.xml = "test.xml"
VALUE ruby_xslt_xml_obj_set( VALUE self, VALUE xml_doc_obj ) { RbTxslt *pRbTxslt; Data_Get_Struct( self, RbTxslt, pRbTxslt ); pRbTxslt->oXmlObject = xml_doc_obj; pRbTxslt->xXmlString = object_to_string( xml_doc_obj ); if( pRbTxslt->xXmlString == Qnil ) { rb_raise( eXSLTError, "Can't get XML data" ); } pRbTxslt->iXmlType = RUBY_XSLT_XMLSRC_TYPE_STR; pRbTxslt->xXmlData = pRbTxslt->xXmlString; pRbTxslt->iXmlResultType = RUBY_XSLT_XMLSRC_TYPE_NULL; if( pRbTxslt->tXMLDocument != NULL ) { xmlFreeDoc(pRbTxslt->tXMLDocument); } pRbTxslt->tXMLDocument = parse_xml( StringValuePtr( pRbTxslt->xXmlData ), pRbTxslt->iXmlType ); if( pRbTxslt->tXMLDocument == NULL ) { rb_raise( eXSLTParsingError, "XML parsing error" ); } pRbTxslt->iXmlType = RUBY_XSLT_XMLSRC_TYPE_PARSED; return( Qnil ); }
object = #xmlobject
Return the XML object set by #xml=
VALUE ruby_xslt_xml_2obj_get( VALUE self ) { RbTxslt *pRbTxslt; Data_Get_Struct( self, RbTxslt, pRbTxslt ); return( pRbTxslt->oXmlObject ); }
#xsl=<data|REXML::Document|XML::Smart|file>
Set XSL data.
Parameter can be type String, REXML::Document, XML::Smart::Dom or Filename
Examples :
# Parameter as String oXSLT.xsl = <<XML <?xml version="1.0" ?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <xsl:apply-templates /> </xsl:template> </xsl:stylesheet> XML # Parameter as REXML::Document require 'rexml/document' oXSLT.xsl = REXML::Document.new File.open( "test.xsl" ) # Parameter as XML::Smart::Dom require 'xml/smart' oXSLT.xsl = XML::Smart.open( "test.xsl" ) # Parameter as Filename oXSLT.xsl = "test.xsl"
VALUE ruby_xslt_xsl_obj_set( VALUE self, VALUE xsl_doc_obj ) { RbTxslt *pRbTxslt; Data_Get_Struct( self, RbTxslt, pRbTxslt ); pRbTxslt->oXslObject = xsl_doc_obj; pRbTxslt->xXslString = object_to_string( xsl_doc_obj ); if( pRbTxslt->xXslString == Qnil ) { rb_raise( eXSLTError, "Can't get XSL data" ); } if( objectIsFile( xsl_doc_obj ) ) { pRbTxslt->iXslType = RUBY_XSLT_XSLSRC_TYPE_FILE; pRbTxslt->xXslData = pRbTxslt->oXslObject; } else { pRbTxslt->iXslType = RUBY_XSLT_XSLSRC_TYPE_STR; pRbTxslt->xXslData = pRbTxslt->xXslString; } pRbTxslt->iXmlResultType = RUBY_XSLT_XMLSRC_TYPE_NULL; if( pRbTxslt->tParsedXslt != NULL ) { xsltFreeStylesheet(pRbTxslt->tParsedXslt); } pRbTxslt->tParsedXslt = parse_xsl( StringValuePtr( pRbTxslt->xXslData ), pRbTxslt->iXslType ); if( pRbTxslt->tParsedXslt == NULL ) { rb_raise( eXSLTParsingError, "XSL Stylesheet parsing error" ); } pRbTxslt->iXslType = RUBY_XSLT_XSLSRC_TYPE_PARSED; return( Qnil ); }
string = #xsl_to_s( )
VALUE ruby_xslt_to_s( VALUE self ) { VALUE vStrOut; RbTxslt *pRbTxslt; xsltStylesheetPtr vXSLTSheet = NULL; const char *xKlassName = rb_class2name( CLASS_OF( self ) ); Data_Get_Struct( self, RbTxslt, pRbTxslt ); //vXSLTSheet = xsltParseStylesheetDoc( xmlParseMemory( StringValuePtr( pRbTxslt->xXslData ), strlen( StringValuePtr( pRbTxslt->xXslData ) ) ) ); vXSLTSheet = pRbTxslt->tParsedXslt; if (vXSLTSheet == NULL) return Qnil; vStrOut = rb_str_new( 0, strlen(xKlassName)+1024 ); (void) sprintf( RSTRING_PTR(vStrOut), "#<%s: parent=%p,next=%p,imports=%p,docList=%p," "doc=%p,stripSpaces=%p,stripAll=%d,cdataSection=%p," "variables=%p,templates=%p,templatesHash=%p," "rootMatch=%p,keyMatch=%p,elemMatch=%p," "attrMatch=%p,parentMatch=%p,textMatch=%p," "piMatch=%p,commentMatch=%p,nsAliases=%p," "attributeSets=%p,nsHash=%p,nsDefs=%p,keys=%p," "method=%s,methodURI=%s,version=%s,encoding=%s," "omitXmlDeclaration=%d,decimalFormat=%p,standalone=%d," "doctypePublic=%s,doctypeSystem=%s,indent=%d," "mediaType=%s,preComps=%p,warnings=%d,errors=%d," "exclPrefix=%s,exclPrefixTab=%p,exclPrefixNr=%d," "exclPrefixMax=%d>", xKlassName, vXSLTSheet->parent, vXSLTSheet->next, vXSLTSheet->imports, vXSLTSheet->docList, vXSLTSheet->doc, vXSLTSheet->stripSpaces, vXSLTSheet->stripAll, vXSLTSheet->cdataSection, vXSLTSheet->variables, vXSLTSheet->templates, vXSLTSheet->templatesHash, vXSLTSheet->rootMatch, vXSLTSheet->keyMatch, vXSLTSheet->elemMatch, vXSLTSheet->attrMatch, vXSLTSheet->parentMatch, vXSLTSheet->textMatch, vXSLTSheet->piMatch, vXSLTSheet->commentMatch, vXSLTSheet->nsAliases, vXSLTSheet->attributeSets, vXSLTSheet->nsHash, vXSLTSheet->nsDefs, vXSLTSheet->keys, vXSLTSheet->method, vXSLTSheet->methodURI, vXSLTSheet->version, vXSLTSheet->encoding, vXSLTSheet->omitXmlDeclaration, vXSLTSheet->decimalFormat, vXSLTSheet->standalone, vXSLTSheet->doctypePublic, vXSLTSheet->doctypeSystem, vXSLTSheet->indent, vXSLTSheet->mediaType, vXSLTSheet->preComps, vXSLTSheet->warnings, vXSLTSheet->errors, vXSLTSheet->exclPrefix, vXSLTSheet->exclPrefixTab, vXSLTSheet->exclPrefixNr, vXSLTSheet->exclPrefixMax ); vStrOut = strlen(RSTRING_PTR(vStrOut)); if( OBJ_TAINTED(self) ) OBJ_TAINT(vStrOut); // xsltFreeStylesheet(vXSLTSheet); return( vStrOut ); }
object = #xslobject
Return the XSL object set by #xsl=
VALUE ruby_xslt_xsl_2obj_get( VALUE self ) { RbTxslt *pRbTxslt; Data_Get_Struct( self, RbTxslt, pRbTxslt ); return( pRbTxslt->oXslObject ); }