Transforming XML with XSL to HTML Saxon library in .NET - c#

I am programming in C#. I was previously using the following command line to convert an xml with a xsl and output it as a html.
java -jar "C:\Data\saxon-he-9.4.0.7.jar" View.xml Stylesheet.xsl -o:output.html
However, I am now trying to use the Saxon .Net API to do the same process using the following code:
var xslt = new FileInfo(#"C:\\Data\\Stylesheet.xsl");
var input = new FileInfo(#"C:\\Data\\View.xml");
var output = new FileInfo(#"C:\\Data\\test.html");
// Compile stylesheet
var processor = new Processor();
var compiler = processor.NewXsltCompiler();
var executable = compiler.Compile(new Uri(xslt.FullName));
// Do transformation to a destination
var destination = new DomDestination();
using (var inputStream = input.OpenRead())
{
var transformer = executable.Load();
transformer.SetInputStream(inputStream, new Uri(input.DirectoryName));
transformer.Run(destination);
}
// Save result to a file (or whatever else you wanna do)
destination.XmlDocument.Save(output.FullName);
However I recieve the error:
"An unhandled exception of type 'Saxon.Api.DynamicError' occurred in saxon9he-api.dll"
When running the line "transformer.Run(destination);"
The following screenshots are from the Visual Studio's Locals Debugging:
$exception {"XSLT 1.0 compatibility mode is not available in this configuration"} Saxon.Api.DynamicError
transformer {Saxon.Api.XsltTransformer} Saxon.Api.XsltTransformer

The first thing you need to do is to get more specific information about the nature of the error. Catching the exception and printing the exception message would be a good start. But Saxon will have written diagnostics to the standard error output, which probably ends up in some log file somewhere, depending on how your application is configured and run. If you can't track it down, try redirecting it as described here: How to capture a Processes STDOUT and STDERR line by line as they occur, during process operation. (C#)
Once you've established the actual error, edit the question and we can start investigating what's wrong if it's not obvious.
A common cause of problems when writing to a DomDestination is that your result tree isn't well-formed, e.g, it has text nodes or multiple elements at the top level. It's not clear why you are writing to a DomDestination - if you just want to produce serialized XML, then write to a Serializer.
LATER
Now you've found the error message ("XSLT 1.0 compatibility mode is not available in this configuration") it should be fairly clear. When a stylesheet specifies version="1.0" and is run with an XSLT 2.0 or 3.0 processor, it runs in a compatibility mode where certain things behave differently (for example xsl:value-of ignores all but the first selected item). This compatibility mode, from Saxon 9.8 onwards, is not available in Saxon-HE. You need to do one of three things: upgrade to Saxon-PE or -EE; revert to an earlier Saxon-HE version; or convert your stylesheet to XSLT 2.0 (which basically means (i) change the value of the version attribute (ii) test that it still works.)

Related

Saxon .net how handle external resources xml

I have a batch and want to rebuild this in a .net application. How can I handle this in .net?
-xsl:"style.xsl" resource-path="%runtimepath%%respath%" srcAutotexte="%runtimepath%%respath%\autotext\autotext.xml"
My attempt. How can I include the autotext.xml?
// Create a transformer for the stylesheet.
XsltCompiler compiler = processor.NewXsltCompiler();
compiler.BaseUri = new Uri(styleXslFilePath);
XsltTransformer transformer = compiler.Compile(File.OpenRead(styleXslFilePath)).Load();
The command line options
resource-path="%runtimepath%%respath%"
srcAutotexte="%runtimepath%%respath%\autotext\autotext.xml"
set the values of stylesheet parameters in the transformation.
The equivalent when using the Saxon.Api interface is to call
transformer.SetParameter(
new QName("resource-path"),
new XdmAtomicValue("%runtimepath%%respath%"));
etc.
(Perhaps your shell interprets %xxxx% as a reference to a shell/system variable of some kind - it's a long time since I wrote batch scripts under Windows. If that's the case then you'll need to get hold of the values of these variables. You can do that at the C# level using the .NET API, or you might be able to do it from within XSLT 3.0 using the environment-variable() function.)

DotNetRDF & AllegroGraph

I'm working on an application for bulk parsing and uploading to an AllegroGraph triplestore, but have run into a snag. I am able to open and read the graph in question using the below code:
AllegroGraphConnector conn = new AllegroGraphConnector(myHost, myGraph, myUsername, myPassword);
Graph g = new Graph();
conn.LoadGraph(g, "");
g.BaseUri = new Uri(MOG);
foreach (RTSNode r in _nodes)
{
IUriNode sbj = g.CreateUriNode(new Uri(RTSuri + r.myName));
IUriNode pred = g.CreateUriNode(new Uri(MOG));
ILiteralNode obj = g.CreateLiteralNode(r.myName, "en");
g.Assert(new Triple(sbj, pred, obj));
}
conn.SaveGraph(g);
As mentioned the graph loads fine and triples are being added to the local version. But when I attempt to save it, I get an 400- Bad request error. Turning on full debugging shows the error to be due to:
UNSUPPORTED FILE FORMAT: 'application/n-triples' is not a supported content-type
Is there an option for changing the default format with which AllegroGraphConnector communicates?
Thank you for your time.
What version of dotNetRDF are you using?
This sounds like a bug which was fixed in our recent 1.0.8 release so I would first try upgrading to the latest version which should resolve the issue
Update
So it looks like this is a bug in AllegroGraph, according to their documentation they are expecting the MIME type for NTriples to be text/plain whereas most current systems (including dotNetRDF) use the now standard application/n-triples as the MIME type for NTriples.
Currently there is no workaround for this, filed as CORE-447 to be fixed for the next release

BizTalk Dynamic Disassembler Problems - The body part is NULL

I started with the solution here http://social.technet.microsoft.com/wiki/contents/articles/20547.biztalk-server-dynamic-schema-resolver-real-scenario.aspx
which matches my scenario perfectly except for the send port, but that isn't necessary. I need the receive port to choose the file and apply a schema to disassemble. From their the orchestration does the mapping, some of it custom, etc.
I've done everything in the tutorial but I keep getting the following error.
"There was a failure executing the receive pipeline... The body part is NULL"
The things I don't get from the tutorial but don't believe they should be an issue are:
I created a new solution and project to make the custompipeline component (reference figure 19) and thus the dll file. Meaning it is on it's own namespace. However, it looks like from the tutorial they created the project within the main biztalk solution (ie the one with the pipeline and the orchestration) and thus the namespace has "TechNetWiki.SchemaResolver." in it. Should I make the custompipeline component have the namespace of my main solution? I'm assuming this shouldn't matter because I should be able to use this component in other solutions as it is meant to be generic to the business rules that are associated with the biztalk application.
The other piece I don't have is Figure 15 under the "THEN Action" they have it equal the destination schema they would like to disassemble to but then they put #Src1 at the end of "http://TechNetWiki.SchemaResolver.Schemas.SRC1_FF#Src1". What is the #Src1 for?
In the sample you've linked to, the probe method of the pipeline component is pushing the first 4 characters from the filename into a typed message that is then passed into the rules engine. Its those 4 characters that match the "SRC1" in the example.
string srcFileName = pInMsg.Context.Read("ReceivedFileName", "http://schemas.microsoft.com/BizTalk/2003/file-properties This link is external to TechNet Wiki. It will open in a new window. ").ToString();
srcFileName = Path.GetFileName(srcFileName);
//Substring the first four digits to take source code to use to call BRE API
string customerCode = srcFileName.Substring(0, 4);
//create an instance of the XML object
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(string.Format(#"<ns0:Root xmlns:ns0='http://TechNetWiki.SchemaResolver.Schemas.SchemaResolverBRE This link is external to TechNet Wiki. It will open in a new window. '>
<SrcCode>{0}</SrcCode>
<MessageType></MessageType>
</ns0:Root>", customerCode));
//retreive source code in case in our cache dictionary
if (cachedSources.ContainsKey(customerCode))
{
messageType = cachedSources[customerCode];
}
else
{
TypedXmlDocument typedXmlDocument = new TypedXmlDocument("TechNetWiki.SchemaResolver.Schemas.SchemaResolverBRE", xmlDoc);
Microsoft.RuleEngine.Policy policy = new Microsoft.RuleEngine.Policy("SchemaResolverPolicy");
policy.Execute(typedXmlDocument);
So the matching rule is based on the 1st 4 characters of the filename. If one isn't matched, the probe returns a false - i.e. unrecognised.
The final part is that the message type is pushed into the returned message - this is made up of the namespace and the root schema node with a # separator - so your #src1 is the root node.
You need to implement IProbeMessage near to class
I forgot to add IProbeMessage in the code of article. It is updated now.
but it is there in sample source code
Src1 is the the root node name of schema. I mentioned that in article that message type is TargetNamespace#Root
I recommend to download the sample code
I hope this will help you

JScript.NET vs ECMA

I am programming a small console app that is an intelligent front-end to a set of batch files with ungodly parameters.
I have decided to use JScript.Net for this though it may be ill advised compared to C# because I am finding the flexibility of it useful, and it feels a bit more RAD than C# for this kind of thing.
The problem I have is not being able to find adequate resources on the net showing how JScript.Net != ECMA when it gets down to the nuts and bolts level. I have to be constantly vigilant of the gotchas, and how things are actually implemented are a bit puzzling.
Does anyone have good links to information on this subject?
Edit--
To be specific, I want a resource that will stop me from writing tests like this -- which compiles and runs, despite the weirdness going on in the synax:
var int16:Int16=0;
w_(typeof int16); // =number
//w_(int16.getType()); //runtime error function expected
//
var ds:String="dot,net,class";
w_(typeof ds); // =string
var da1:Array=ds.Split(','); // proper case
var da2:Array=ds.split(','); // camel case !works too!
w_(typeof da1); // =object
var ds1_:String=da1.join(',');// NOT proper. "Join" is **runtime error**
var ds2_:String=da2.join(',');// NOT proper. "Join" is **runtime error**
w_('ds1_:'+ds1_); // prints dot,net,class
w_('ds2_:'+ds2_); // prints dot,net,class
//
var js="jscript.object";
w_(typeof js); // =string
var ja1=js.split(','); // camel case
var ja2=js.Split(','); // proper case
w_(typeof ja1); // =object
var js1_=ja1.join(',');// camel
var js2_=ja2.join(',');// camel
w_('js1_:'+js1_); // prints jscript.object
w_('js2_:'+js2_); // prints jscript.object
//
// and then
//
var dss:System.String="dot,net,sys,class";
w_('dss:'+(typeof ds)); // =undefined !!!
//w_('dss:'+dss.getType()); //runtime error function expected
var daa:Array=dss.Split(',');// proper case ???? what is this object type!
var daa2:Array=dss.split(',');// camel case ???? what is this object type!
w_(daa.join(',')); // prints dot,net,sys,class
w_(daa2.join(',')); // prints dot,net,sys,class
//
You see?
Also
// in library 'package' JLib_Test.jsc
import System;
import System.IO;
import System.Diagnostics;
import System.Text;
import System.Drawing;
package JLib_Test{
class Test{
public function Test(){
//var re=new RegExp('^s$','gi'); // **runtime error** !
}
}
//
// in main 'exe' module
var re=new RegExp('^s$','gi'); // no errors
As you are on Windows, just run your .js file with cscript.exe: this is the Windows Scripting Host (WSH) environment from Microsft that uses the other Microsoft implementation (a standard Windows 7 system has currently 3: JScript, JScript.NET and JavaScript in IE9). The JScript from WSH is the one that was used in IE up to IE8, and so has probably less .NET-isms.
Note that you'll probably have issues with your I/O and argument parsing as the API in .NET and WSH are different, so I suggest to make a common API wrapper.
Do you mean ECMAScript ? ECMAScript is a standard scripting language, standardized by ECMA and
JScript.Net is an "implementation" of EMCAScript which has been created by Microsoft (actually based on JScript) to be used upon .Net platform. It means JScript.Net supports all ECMAScript specifications:
http://msdn.microsoft.com/en-us/library/49zhkzs5(v=vs.71).aspx
and also provides users with some extra Non-ECMA features:
http://msdn.microsoft.com/en-us/library/894hfyb4(v=vs.71).aspx

Debugging XSLT with extension objects in Visual Studio 2010

I'm currently working on a project that involves a lot of XSLT transformations and I really need a debugger (I have XSLTs that are 1000+ lines long and I didn't write them :-).
The project is written in C# and makes use of extension objects:
xslArg.AddExtensionObject("urn:<obj>", new <Obj>());
From my knowledge, in this situation Visual Studio is the only tool that can help me debug the transformations step-by-step. The static debugger is no use because of the extension objects (it throws an error when it reaches elements that reference their namespace). Fortunately, I've found this thread which gave me a starting point (at least I know it can be done).
After searching MSDN, I found the criteria that makes stepping into the transform possible. They are listed here. In short:
the XML and the XSLT must be loaded via a class that has the IXmlLineInfo interface (XmlReader & co.)
the XML resolver used in the XSLTCompiledTransform constructor is file-based (XmlUriResolver should work).
the stylesheet should be on the local machine or on the intranet (?)
From what I can tell, I fit all these criteria, but it still doesn't work. The relevant code samples are posted below:
// [...]
xslTransform = new XslCompiledTransform(true);
xslTransform.Load(XmlReader.Create(new StringReader(contents)), null, new BaseUriXmlResolver(xslLocalPath));
// [...]
// I already had the xml loaded in an xmlDocument
// so I have to convert to an XmlReader
XmlTextReader r = new XmlTextReader(new StringReader(xmlDoc.OuterXml));
XsltArgumentList xslArg = new XsltArgumentList();
xslArg.AddExtensionObject("urn:[...]", new [...]());
xslTransform.Transform(r, xslArg, context.Response.Output);
I really don't get what I'm doing wrong. I've checked the interfaces on both XmlReader objects and they implement the required one. Also, BaseUriXmlResolver inherits from XmlUriResolver and the stylesheet is stored locally. The screenshot below is what I get when stepping into the Transform function. First I can see the stylesheet code after stepping through the parameters (on template-match), I get this:
If anyone has any idea why it doesn't work or has an alternative way of getting it to work I'd be much obliged :).
Thanks,
Alex
I'm not sure about usage of extension objects but as I understand your problem is with debugging of XSLT transformation in code in VS2010.
Here is the function that we use to debug XSLT transformation:
public string ApplyTransformation(string inputFilePath, string xsltFileContent)
{
XslCompiledTransform transform = new XslCompiledTransform(debugEnabled);
File.WriteAllText(xsltTempFilePath,xsltFileContent);
transform.Load(xsltTempFilePath, XsltSettings.TrustedXslt, new XmlUrlResolver());
XmlReader reader = XmlReader.Create(inputFilePath);
StringWriter output = new StringWriter();
XmlWriter writer = XmlWriter.Create(output,transform.OutputSettings);
transform.Transform(reader,writer);
return output.ToString();
}
Unfortunately, there is a bug with VS2010 XSLT debugger which will make your debugging experience worse than in VS2008.
Consider debugging using XML Spy XSLT debugger. It works for me all the time.

Categories

Resources