xslcompiledtransform 输出函数名和命名空间

Posted

技术标签:

【中文标题】xslcompiledtransform 输出函数名和命名空间【英文标题】:xslcompiledtransform outputs name of function and namespaces 【发布时间】:2013-11-02 05:40:10 【问题描述】:

背景: 我正在开发一个 XSLT 来将 XML 文档转换为 rtf 文档。 XSLT 有一个名为 GetImageString 的 msxsl:script 函数,它返回给定图像文件的字符串表示形式,因此我可以将图像嵌入到 rtf 文档中。

问题: 当 xslCompiledTransform 与 xmlWriterSettings 和 XmlWriter 一起使用时,转换的输出 (xsl:output method="text") 包括脚本函数的名称 (GetImageString) 以及 XSL 文件中包含的所有非默认名称空间的列表。如果我在没有 xmlWriterSettings 和 XmlWriter 类的情况下使用 XslCompiledTransform,则输出是正确的,除了在文件顶部插入 BOM(字节顺序标记),这会混淆(至少)MS Word rtf 阅读器。所以为了抑制 BOM,我必须使用 XmlWritterSettings(和 XmlWriter)类,但是当调用嵌入式 c# 代码时输出不正确。

这是我的 xsl 文件的 sn-p:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xpp="http://www.sdl.com/xpp"
    xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
    xmlns:v="urn:schemas-microsoft-com:vml"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt"
    xmlns:rend="urn:rend-scripts">
    <xsl:output method="text" encoding="utf-8"/>

    <xsl:template match="xpp:document">          
      <xsl:text>\rtf1\ansi \fonttbl </xsl:text>
      <xsl:apply-templates select="//xpp:style"/>
      <xsl:text> </xsl:text>

      <xsl:apply-templates select ="//xpp:image"/>
      <xsl:text>;</xsl:text>
    </xsl:template>

    <msxsl:script language="c#" implements-prefix="rend">
      <msxsl:assembly href="C:\Projects\LearningRTF\System.IO.dll"/>
      <msxsl:assembly href="C:\Projects\LearningRTF\System.Drawing.dll"/>
      <msxsl:using namespace="System.IO"/>
      <msxsl:using namespace="System.Drawing"/>
      <![CDATA[
        public string GetImageString(string path_to_image)
          MemoryStream stream = new MemoryStream();
          Image img = Image.FromFile(path_to_image);
          img.Save(stream, System.Drawing.Imaging.ImageFormat.Tiff);
          byte[] bytes = stream.ToArray();
          string output = BitConverter.ToString(bytes, 0).Replace("-", string.Empty);

          return output;
        
      ]]>
    </msxsl:script>

    <xsl:template match="xpp:image">
      <xsl:text>
      \pict\wmetafile8</xsl:text>
      <GetImageString>
        <xsl:text> </xsl:text>
        <xsl:value-of select="rend:GetImageString(@path)"/>
      </GetImageString>
      <xsl:text></xsl:text>
    </xsl:template>

这是调用转换的 c# 程序:

    public void TransformWithMS()
    
        XsltSettings xsltConfig = new XsltSettings(false,true);

        XslCompiledTransform xslt = new XslCompiledTransform();
        xslt.Load("scratch.xsl",xsltConfig,null);
        //xslt.Transform("divxml_modified.xml", "scratch.rtf");
        XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
        xmlWriterSettings.Encoding = new UTF8Encoding(false);
        xmlWriterSettings.ConformanceLevel = ConformanceLevel.Auto;
        XmlWriter results = XmlWriter.Create("scratch.rtf", xmlWriterSettings);
        xslt.Transform("divxml_modified.xml", results);
    

这是有问题的输出的样子:

\rtf1\ansi \fonttbl \f1 次新罗马; \pict\wmetafile8 GetImageString xmlns:xpp="http://www.sdl.com/xpp" >xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" >xmlns :v="urn:schemas-microsoft-com:vml" xmlns:msxsl="urn:schemas-microsoft-com:xslt" >xmlns:rend="urn:rend-scripts" 49492A00BC480000803...

(GetImageString 和命名空间列表周围有一个 ,但我无法弄清楚如何将其格式化为问题)

有人知道如何调用 msxsl:script 函数而不输出函数名称和额外的命名空间(并且没有 BOM)吗?

【问题讨论】:

【参考方案1】:

如果你想改变 .NET 代码的输出设置,那么你应该使用

XmlWriterSettings myOutputSettings = xslt.OutputSettings.Clone();
myOutputSettings.Encoding = new UTF8Encoding(false);

现在创建一个 XmlWriter 例如

using (XmlWriter result = XmlWriter.Create("scratch.rtf", myOutputSettings))

  xslt.Transform("divxml_modified.xml", result);

这允许您拥有一个根据xsl:output 输出但编码已更改的 XmlWriter。

我不确定这是否解决了输出中出现的代码问题,请尝试并报告。

【讨论】:

感谢您的回答!使用Clone 创建 XmlWriterSettings 就可以了。另一个论坛上的某人建议 标签是不必要的,通过删除这些标签,我也能够使其按预期工作。

以上是关于xslcompiledtransform 输出函数名和命名空间的主要内容,如果未能解决你的问题,请参考以下文章

C# XslCompiledTransform - 以 POCO 形式而不是 Html 输出

XslCompiledTransform 中的 XSLT 复制和排序转换引发异常

XslCompiledTransform 类的加载方法抛出 *** 异常

如何将VS2003的XslTransform转换为VS2005的XslCompiledTransform?

当输入 XML 和转换 XSL 是字符串时,如何使用 XslCompiledTransform。如何将转换结果作为字符串获取?

如何加快 XSL 转换?