2

I have a load of XSLT from a third party which i need to use to transform some data.

If I use xsltproc it works fine and outputs data as expected.

I have the following C# code to try and use it in-process:

sXML is the lump of XML oJob.ContentTemplate is the local file path to the XSLT file

try
{
    using (StringWriter oOutputString = new StringWriter())
    {
        using (XmlTextWriter oOutputWriter = new XmlTextWriter(oOutputString))
        {
            using (StringReader oInputString = new StringReader(sXML))
            {
                using (XmlTextReader oInputReader = new XmlTextReader(oInputString))
                {
                    XslCompiledTransform oXSLTTransform = new XslCompiledTransform();
                    oXSLTTransform.Load(oJob.ContentTemplate, XsltSettings.TrustedXslt, new XmlUrlResolver());
                    oXSLTTransform.Transform(oInputReader, oOutputWriter);
                    String sHTML = oOutputWriter.ToString();
                }
            }
        }
    }
}
catch (Exception e)
{}

The exception thrown is:

Additional information: Cannot find the script or external object that implements prefix 'http://dlxs.org'.

The XSLT is fairly complicated and I don't understand most of it currently. Is there a way I can get this working without delving too far into the XSLT?

Visual Studio 2010 should support EXSLT right?

Edit : If i enable debug and step into it I can see the error on the line:

<xsl:import href="../../lib/xslfunctions.xsl"/>
......
<xsl:when test="contains($BibRegions, dlxs:normAttr($searchRgn))">

These functions should be included already, one of the local XSLT files contains this:

 <?xml version="1.0" encoding="UTF-8" ?>
 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:str="http://exslt.org/strings" xmlns:exsl="http://exslt.org/common" xmlns:func="http://exslt.org/functions" xmlns:dlxs="http://dlxs.org" extension-element-prefixes="str exsl dlxs func" exclude-result-prefixes="str exsl dlxs func">
<!-- extension functions -->
<func:function name="dlxs:normAttr">
    <xsl:param name="attr"/>
    <!-- strip out spaces,commas,question marks -->
    <xsl:variable name="temp" select="translate($attr,' ,?','')"/>
    <func:result select="translate($temp,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')"/>
</func:function>
.....
</xsl:stylesheet>

Is it that Visual Studio can't open these files because they use UNIX paths or because it can't open the local files due to security issues?

Edit 2 :

The extensions that I'm using are:

 <xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:str="http://exslt.org/strings"
  xmlns:exsl="http://exslt.org/common"
  xmlns:func="http://exslt.org/functions"
  xmlns:dlxs="http://dlxs.org"
  extension-element-prefixes="str exsl dlxs func"
  exclude-result-prefixes="str exsl dlxs func">

I'm very much an XSLT beginner so aren't sure what you need.

1
  • 1
    Seems you are using some XSLT extensions. You need to correctly specify where to find them. How this is done depends on the extensions that you use. Could you please post some more details? Commented Feb 14, 2011 at 21:39

3 Answers 3

2

Only the EXSLT Common module is supported by the .NET XSLT engine. To use all of EXSLT, you must use one of the compatible engines listed here (or rewrite your stylesheets):

EXSLT - func:function

EDIT: You might get lucky using the Mvp.Xml library developed by some Microsoft MVPs which is available at Codeplex. It offers some EXSLT support:

Mvp.Xml Project

Sign up to request clarification or add additional context in comments.

6 Comments

that's a shame, none of those seem to be available for .NET.
thanks but i don't think mvp.xml helps. I've tried my code with these libraries but i still have the same error.
@Gordon Carpenter-Thompson: If you are bound to .NET you might want to have a look at the (commercial) version of SAXON which brings support for EXSLT on .NET too. I haven't tried it myself though.
@Gordon Carpenter-Thompson: Explanation of error message: because func:function is a top level element in not null namespace and .Net doesn't implement the http://exslt.org/functions module of EXSLT, this element is going to be ignored by the processor. Then, dlxs:normAttr() extension function invocation rise an error because the implementation isn't found. Stylesheet functions definitions is not the standard XSLT 1.0 mechanism. You should consider to upgrade to XSLT 2.0 for this feature.
"EXSLT is not supported by the .NET XSLT engine." - This is wrong, or if I'm being charitable, imprecise. XslCompiledTransform supports at least part of EXSL - I know that because I'm using it. It seems not to support the strings module however.
|
1

You need to look at your XSLT document for the namespace http://dlxs.org. I would go out to the website here:

http://www.dlxs.org/products/index.html

Looks like your XSLT is using some extensions that are needed.

Comments

1

Thanks for all of the help.

I couldn't get this working using any of the native .NET libraries so worked around it. The program that this is used in is only ever intended to be run once to populate a database so performance isn't incredibly important. For those of you who are interested here is my solution. I use XSLTProc.exe to transform the data, streaming out to disk in a temporary file and then read the output back in again. Nasty but works.

using (TemporaryFile oTempInputFile = new TemporaryFile())
{
    //write the content out to the temporary file
    using (StreamWriter oWriter = new StreamWriter(oTempInputFile.FilePath, false, System.Text.Encoding.UTF8))
    {
        oWriter.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
        oWriter.WriteLine(oTextNode.OuterXml);
        oWriter.Close();
    }


    using (TemporaryFile oTempOutputFile = new TemporaryFile())
    {
        try
        {
            String sXSLTProcArguments = "-o \"" + oTempOutputFile.FilePath + "\" \"" + oJob.ContentTemplate + "\" \"" + oTempInputFile.FilePath + "\"";

            Process oProcess = new Process();
            oProcess.StartInfo.UseShellExecute = false;
            oProcess.StartInfo.FileName = oJob.XSLTParser;
            oProcess.StartInfo.Arguments = sXSLTProcArguments;
            oProcess.StartInfo.RedirectStandardOutput = true;
            oProcess.StartInfo.RedirectStandardError = true;
            oProcess.StartInfo.CreateNoWindow = true;
            oProcess.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
            oProcess.Start();
            oProcess.WaitForExit(5000);

            if (File.Exists(oTempOutputFile.FilePath))
            {
                using (StreamReader oReader = new StreamReader(oTempOutputFile.FilePath))
                {
                    String sHTML = oReader.ReadToEnd();

                    if (sHTML.Length == 0)
                    {
                        Logger.Write(new DebugLogEntry("No HTML content was generated"));
                    }
                    else
                    {
                        //Do something with sHTML
                    }
                }
            }
            else
            {
                Logger.Write(new GeneralLogEntry("Failed to transform content for " + sDocumentID));
            }
        }
        catch (Exception e)
        {
            Logger.Write(new GeneralLogEntry("Exception thrown when transforming content for " + sDocumentID));
            Logger.Write(new DebugLogEntry(e.Message));
            Logger.Write(new DebugLogEntry(e.StackTrace));
        }
    }
}    

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.