Home > Net >  Saxon EE 11.2 TransformToString() produces JET RUNTIME with an exit code of 9
Saxon EE 11.2 TransformToString() produces JET RUNTIME with an exit code of 9

Time:03-08

So Ive been using "XsltExecutable::TransformtoString()" , it works with most of my xslts , but i have an xslt that produces a JET RUNTIME ERROR and returns with an exit code of 9.

I've searched what "exit code 9" means , and it said that it means that the OS is killing the program because I dont have enough memory ?????

This works with "TransformFiletoFile()" and all my other xslts but not this one.

This Xslt is using "xsl:result document" to output multiple files. Ive tried setting "BaseOutputURI()" but it still doesn't work . here is some more info :

Xml size : 192,957 KB

Xslt size (The One That Fails) : 24 KB

Code :

SaxonProcessor* processor = new SaxonProcessor(false);
Xslt30Processor* xslt = processor->newXslt30Processor();

XdmNode* xmlfile = processor->parseXmlFromFile( Xml File );
XsltExecutable* xslte = xslt->compileFromFile( Xslt File );

std::string File = xslte->transformToString();   // Fails here

Output : enter image description here

Example xml file :

<xml>
 <value>5</value>
</xml>

Example xslt file :

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output method="xml" encoding="utf-8" standalone="yes" indent="yes"/>

  <xsl:template match="/">
    <xsl:message>producing sheet</xsl:message>
    <xsl:result-document href="output.xml">
      <result>
        <value>You put a <xsl:value-of select="/xml/value"/></value>
      </result>
    </xsl:result-document>
  </xsl:template>
</xsl:stylesheet>

CodePudding user response:

I can run the sample XSLT against the sample XML fine, creating output.xml fine (and an empty applyTemplatesReturnFileTest3.xml as the main template does not output anything) with applyTemplatesReturningFile e.g. sample C code is

#include <sstream>
#include <stdio.h>

#include "../../Saxon.C.API/SaxonProcessor.h"
#include "../../Saxon.C.API/XdmValue.h"
#include "../../Saxon.C.API/XdmItem.h"
#include "../../Saxon.C.API/XdmNode.h"
#include "../../Saxon.C.API/XdmFunctionItem.h"
#include "../../Saxon.C.API/DocumentBuilder.h"
#include "../../Saxon.C.API/XdmMap.h"
#include "../../Saxon.C.API/XdmArray.h"
//#include "cppExtensionFunction.h"
#include "CppTestUtils.h"
#include <string>
//#include <thread>




using namespace std;


#ifdef MEM_DEBUG
#define new new(__FILE__, __LINE__)
#endif





/*
* Test applyTemplatesReturningFile. Source and stylesheet and output supplied as arguments
*/
void testApplyTemplatesReturningFile(SaxonProcessor* processor, Xslt30Processor* trans, sResultCount* sresult) {

    cout << "Test: transformToFile:" << endl;

    const char* xsltFile = "result-document-test2.xsl";
    const char* inputFile = "source2.xml";
    const char* resultFile = "applyTemplatesReturningFileTest3.xml";

    remove(resultFile);

    XdmNode* xmlfile = processor->parseXmlFromFile(inputFile);
    XsltExecutable* xslte = trans->compileFromFile(xsltFile);

    xslte->setGlobalContextItem(xmlfile);

    xslte->setInitialMatchSelection(xmlfile);

    xslte->applyTemplatesReturningFile(resultFile);


    if (CppTestUtils::exists(resultFile)) {
        cout << "The file " << resultFile << " exists" << endl;
        //remove(resultFile);
        sresult->success  ;
    }

    else {
        cout << "The file " << resultFile << " does not exist" << endl;
        if (xslte->exceptionOccurred()) {
            cout << xslte->getErrorMessage() << endl;
        }
        sresult->failure  ;
        sresult->failureList.push_back("testApplyTemplatesReturningFile");
    }

}



int main(int argc, char* argv[]) {


    const char* cwd = nullptr;
    if (argc > 0) {
        cwd = argv[1];
    }

    SaxonProcessor* processor = new SaxonProcessor(true);

    cout << "Test: Xslt30Processor with Saxon version=" << processor->version() << endl << endl;

    char buff[FILENAME_MAX]; //create string buffer to hold path
    GetCurrentDir(buff, FILENAME_MAX);
    cout << "CWD = " << buff << endl;
    if (cwd != nullptr) {
        processor->setcwd(cwd);
    }
    else {
        processor->setcwd(buff);
    }
    if (processor->isSchemaAwareProcessor()) {

        std::cerr << "Processor is Schema Aware" << std::endl;
    }
    else {
        std::cerr << "Processor is not Schema Aware" << std::endl;
    }

    sResultCount* sresult = new sResultCount();

    Xslt30Processor* trans = processor->newXslt30Processor();

    if (trans == nullptr) {
        cout << "Error creating Xslt30Processor" << endl;
        if (processor->exceptionOccurred()) {
            cout << "Error message: " << processor->getErrorMessage() << endl;

        }
        return -1;
    }
 

    testApplyTemplatesReturningFile(processor, trans, sresult);

    cout << endl << "=============================================================" << endl << endl;


    fflush(stdout);



    delete trans;
    delete processor;
    processor->release();


    cout << endl << "======================== Test Results ========================" << endl << endl;

    std::cout << "\nTest Results - Number of tests= " << (sresult->success   sresult->failure) << ", Successes = "
        << sresult->success << ",  Failures= " << sresult->failure << std::endl;

    std::list<std::string>::iterator it;
    std::cout << "Failed tests:" << std::endl;
    // Make iterate point to beginning and increment it one by one until it reaches the end of list.
    for (it = sresult->failureList.begin(); it != sresult->failureList.end(); it  ) {
        //Print the contents
        std::cout << it->c_str() << std::endl;

    }

    delete sresult;

#ifdef MEM_DEBUG
    SaxonProcessor::getInfo();
#endif

    return 0;
}

CodePudding user response:

For the code

SaxonProcessor* processor = new SaxonProcessor(false);
Xslt30Processor* xslt = processor->newXslt30Processor();

XdmNode* xmlfile = processor->parseXmlFromFile( Xml File );
XsltExecutable* xslte = xslt->compileFromFile( Xslt File );

std::string File = xslte->transformToString(); 

you have show, I don't see any use of xmlfile, I think you want xslte->transformToString(xmlfile).

But there might indeed be a problem with transformToString and xsl:result-document, I run into

Error in xsl:result-document/@href on line 6 column 42 of result-document-test2.xsl:
  SXRD0002  The system identifier of the principal output file is unknown
  In template rule with match="/" on line 4 of result-document-test2.xsl
     invoked by xsl:result-document at file:///C:/Program Files/Saxonica/SaxonC EE 11.2/samples/cppTests/result-document-test2.xsl#6

although at least setcwd on the processor was done. Will need to check more details.

You can check for any errors during XSLT execution in your C code with e.g.

   const char* result = xslte->transformToString(NULL);
   if (!xslte->exceptionOccurred()) {
        cout << "The result " << result << " was created." << endl;
        sresult->success  ;
    }
    else {
        cout << "An error occured." << endl;
        cout << xslte->getErrorMessage() << endl;
    }

I think, to avoid the base output URI problem, if you load the XSLT from a file and you want the main result as a string (e.g. with transformToString) while providing relative URIs/file names for secondary result documents, in the XSLT you can use e.g. <xsl:result-document href="{resolve-uri('output.xml', static-base-uri())}"> to do that. In that case you don't have to set the base output URI from the C API.

  • Related