Scott
Scott

Reputation: 1253

How do I retrieve error details when Saxon XSLT transformation fails?

I am using Saxon 9 HE 9.7.0.7 for .NET. Typically, when I run XsltTransformer.Run, the DomDestination.XmlDocument property will be populated. However, with some documents, that property will be null. When the property is null, I am assuming that some kind of error was encountered, but no exceptions are thrown, and I'm not seeing any errors on the console. How can I retrieve details regarding why the transformation failed?

For one such example document, I tried the transform from the command line and it completed without any issue.

Here is some example code. The destination.XmlDocument property on the last line will sometimes be null.

        // Compile stylesheet
        var processor = new Processor();
        var compiler = processor.NewXsltCompiler();
        var executable = compiler.Compile(new Uri(xsltFilePath));
        var declaredArgs = executable.GetGlobalParameters();

        // Do transformation to a destination
        var destination = new DomDestination();
        using (var inputStream = new MemoryStream())
        {
            xml.Save(inputStream);
            inputStream.Position = 0;
            var transformer = executable.Load();
            transformer.SetInputStream(inputStream, new Uri(inputXmlFileInfo.DirectoryName));
            foreach (var arg in args)
            {
                var matchingArgDeclaration = declaredArgs.FirstOrDefault(a => a.Key.LocalName.ToLower() == arg.Key.ToLower());
                if (matchingArgDeclaration.Key == null)
                {
                    transformer.SetParameter(new QName(arg.Key), new XdmAtomicValue(arg.Value));
                }
                else
                {
                    // try to load up the specific parameter type
                    // list is based on http://www.saxonica.com/documentation/#!dotnetdoc/Saxon.Api/XdmAtomicValue
                    XdmItemType argType = matchingArgDeclaration.Value.getDeclaredItemType();
                    var argTypeName = "";
                    if (argType != null &&
                        argType is XdmAtomicType)
                        argTypeName = ((XdmAtomicType)argType).Name.LocalName;
                    switch (argTypeName.ToLower())
                    {
                        case "boolean":
                            transformer.SetParameter(new QName(arg.Key), new XdmAtomicValue(Convert.ToBoolean(arg.Value)));
                            break;

                        case "integer":
                            transformer.SetParameter(new QName(arg.Key), new XdmAtomicValue(Convert.ToInt32(arg.Value)));
                            break;

                        case "decimal":
                            transformer.SetParameter(new QName(arg.Key), new XdmAtomicValue(Convert.ToDecimal(arg.Value)));
                            break;

                        case "float":
                            transformer.SetParameter(new QName(arg.Key), new XdmAtomicValue(Convert.ToSingle(arg.Value)));
                            break;

                        case "double":
                            transformer.SetParameter(new QName(arg.Key), new XdmAtomicValue(Convert.ToDouble(arg.Value)));
                            break;

                        case "anyuri":
                            transformer.SetParameter(new QName(arg.Key), new XdmAtomicValue(new Uri(arg.Value)));
                            break;

                        case "qname":
                            transformer.SetParameter(new QName(arg.Key), new XdmAtomicValue(new QName(arg.Value)));
                            break;

                        default:
                            transformer.SetParameter(new QName(arg.Key), new XdmAtomicValue(((arg.Value))));
                            break;
                    }
                }
            }

            transformer.Run(destination);
        }

        // Save result to a file (or whatever else you wanna do)
        destination.XmlDocument.Save(outputFileName);

Upvotes: 1

Views: 1495

Answers (2)

Michael Kay
Michael Kay

Reputation: 163322

There are two kinds of error: static errors and dynamic errors.

Static errors (for example, syntax errors, or use of an undeclared variable or function) are added to the ErrorList property of the XsltCompiler. The Compile() method will throw an exception, and you should then check the details in the ErrorList for detailed diagnostics.

Dynamic errors (for example divide by zero) result in the XsltTransformer.Run() method throwing an exception of class Saxon.Api.DynamicError.

Upvotes: 2

Scott
Scott

Reputation: 1253

It turned out that the stylesheet that I had been given was trying to output to a file using xsl:result-document. As a result, the XmlDocument property was null and no errors were thrown.

Per the documentation, when executing transformer.Run, errors should typically be thrown as a DynamicError exception.

Upvotes: 0

Related Questions