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
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.