2

我有来自第三方的 XSLT 负载,我需要用它来转换一些数据。

如果我使用 xsltproc 它可以正常工作并按预期输出数据。

我有以下 C# 代码可以尝试在进程中使用它:

sXML 是 XML oJob 的块。ContentTemplate 是 XSLT 文件的本地文件路径

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)
{}

抛出的异常是:

附加信息:找不到实现前缀“http://dlxs.org”的脚本或外部对象。

XSLT 相当复杂,目前我大部分都不懂。有没有一种方法可以在不深入研究 XSLT 的情况下完成这项工作?

Visual Studio 2010 应该支持 EXSLT 对吧?

编辑:如果我启用调试并进入它,我可以在该行看到错误:

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

这些函数应该已经包含在内,本地 XSLT 文件之一包含以下内容:

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

是因为 Visual Studio 使用 UNIX 路径而无法打开这些文件,还是因为安全问题而无法打开本地文件?

编辑 2:

我正在使用的扩展是:

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

我是一个 XSLT 初学者,所以不确定你需要什么。

4

3 回答 3

2

.NET XSLT 引擎仅支持 EXSLT Common 模块。要使用所有 EXSLT,您必须使用此处列出的兼容引擎之一(或重写样式表):

EXSLT - 函数:函数

编辑:您可能会幸运地使用由一些 Microsoft MVP 开发的 Mvp.Xml 库,该库可在 Codeplex 获得。它提供了一些 EXSLT 支持:

Mvp.XML 项目

于 2011-02-14T21:47:43.523 回答
1

感谢所有的帮助。

我无法使用任何本机 .NET 库来解决这个问题,所以我解决了这个问题。使用它的程序只打算运行一次以填充数据库,因此性能并不是非常重要。对于那些对此感兴趣的人,我的解决方案是。我使用 XSLTProc.exe 转换数据,以临时文件的形式流式传输到磁盘,然后再次将输出读回。讨厌但有效。

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));
        }
    }
}    
于 2011-02-21T11:13:42.460 回答
1

您需要查看命名空间http://dlxs.org的 XSLT 文档。我会去这里的网站:

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

看起来您的 XSLT 正在使用一些需要的扩展。

于 2011-02-14T21:27:40.250 回答