Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/29.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用MemoryStream的XSLT编译错误_C#_Asp.net_Xslt - Fatal编程技术网

C# 使用MemoryStream的XSLT编译错误

C# 使用MemoryStream的XSLT编译错误,c#,asp.net,xslt,C#,Asp.net,Xslt,我正在动态创建一个xslt和xml文件,以显示我的调查问卷并保存我的问题选项(用于下拉)。现在我想使用流,而不是在实际文件上写入。我就是这样做的: XmlReader xslt_reader; XmlReader xml_reader; PageLoad(){ Fn_CreateXSL(); Fn_CreateXML(); LoadQuestionnaire(); } Fn_CreateXSL(){ xslt_stream = new MemoryStream();

我正在动态创建一个xslt和xml文件,以显示我的调查问卷并保存我的问题选项(用于下拉)。现在我想使用流,而不是在实际文件上写入。我就是这样做的:

XmlReader xslt_reader;
XmlReader xml_reader;

PageLoad(){
  Fn_CreateXSL();
  Fn_CreateXML();
  LoadQuestionnaire();
}

Fn_CreateXSL(){
   xslt_stream = new MemoryStream();

   XmlTextWriter objXSLTWriter = new XmlTextWriter(xslt_stream, Encoding.UTF8);

   objXSLTWriter.Formatting = Formatting.Indented;
   objXSLTWriter.WriteStartDocument();
    ..........
   objXSLTWriter.WriteEndDocument();
   xslt_stream.Seek(0, SeekOrigin.Begin);
   xslt_reader = XmlReader.Create(xslt_stream);
}

Fn_CreateXML(){
   xmlt_stream = new MemoryStream();

   XmlTextWriter objXMLTWriter = new XmlTextWriter(xmlt_stream, Encoding.UTF8);

   objXMLTWriter.Formatting = Formatting.Indented;
   objXMLTWriter.WriteStartDocument();
    ..........
   objXMLTWriter.WriteEndDocument();
   xmlt_stream.Seek(0, SeekOrigin.Begin);
   xmlt_reader = XmlReader.Create(xmlt_stream);
}

LoadQuestionnaire(){
  XslCompiledTransform var_xsl_trans = new XslCompiledTransform();

  // also tried var_xsl_trans.Load(xslt_reader, null, new XmlUrlResolver());
  var_xsl_trans.Load(xslt_reader); // XSLT Compile Error occurs

  StringWriter sw = new StringWriter();

  var_xsl_trans.Transform(xml_reader, null, sw);
}

但是当我试图加载它时,我得到了“XSLT编译错误。有什么想法吗?

这里是适合我的方法

我不使用XmlWriter->MemoryStream->XmlReader,而是使用Microsoft在.NET 3.5中使用LINQ引入的
XElement
Load
Transform
方法的
XslCompiledTransform
类都有重载,这些重载将
IXPathNavigatable
作为传递XML的参数。这个接口只有一个m方法XPathNavigator CreateNavigator()和
XElement
都有这样的方法。我不知道为什么微软没有声明
XElement
实现了这个接口。可能他们忘记了:-)。所以,为了弥补这个疏忽,我实现了6行转换器类
XNavigable
。您将在下面看到它。下面是一个模拟的OP页面加载()

public void Generate()
{
    XElement inputXml = CreateInputXml();
    XElement transformXslt = CreateTransformXslt();

    XslCompiledTransform transform = new XslCompiledTransform();
    transform.Load(new XNavigable(transformXslt), null, null);

    MemoryStream outputStream = new MemoryStream(); 
    transform.Transform(new XNavigable(inputXml), null, outputStream);

    byte[] outputBytes = outputStream.ToArray();
    string outputString = Encoding.UTF8.GetString(outputBytes);
}
我使用
MemoryStream
而不是
StringWriter
,因为StringWriter总是为我创建UTF-16编码的XML作为输出。我认为UTF-16是StringWriter强加的,因为底层字符串每个字符有16位。通过MemoryStream,我们可以控制编码

为了完整起见,这里是我的
CreateInputXml
CreateTransformXslt
方法的代码。它们只是示例。当然,
XElement.Add()
方法可以用来生成内容。我只是使用了构造函数,其中列出了所有节点,可以快速硬编码

    private static XElement CreateTransformXslt()
    {
        //XSL to substitute <placeholder/> with <realElement/> and copy everything else.
        //<stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform">
        //  <output indent="yes" />
        //  <template match="@* | node()">
        //    <copy>
        //      <apply-templates select="@* | node()" />
        //    </copy>
        //  </template>
        //  <template match="placeholder">
        //    <realElement xmlns="" />
        //  </template>
        //</stylesheet>
        XNamespace xsl = "http://www.w3.org/1999/XSL/Transform";
        XNamespace empty = "";
        XElement transformXslt = new XElement(xsl + "stylesheet", new XAttribute("version", "1.0"),
            new XElement(xsl + "output", new XAttribute("indent", "yes")),
            //new XElement(xsl + "strip-space", new XAttribute("elements", "*")),
            new XElement(xsl + "template", new XAttribute("match", "@* | node()"),
                new XElement(xsl + "copy",
                    new XElement(xsl + "apply-templates", new XAttribute("select", "@* | node()"))
                )
            ),
            new XElement(xsl + "template", new XAttribute("match", "placeholder"),
                new XElement("realElement")
            )
        );
        return transformXslt;
    }

    private static XElement CreateInputXml()
    {
        XElement origXml = new XElement(new XElement("Root",
                                            new XElement("Child1", "data1"),
                                            new XElement("placeholder"),
                                            new XElement("Child2", "data2")));
        return origXml;
    }

以下是对我有效的方法

我不使用XmlWriter->MemoryStream->XmlReader,而是使用Microsoft在.NET 3.5中使用LINQ引入的
XElement
Load
Transform
方法的
XslCompiledTransform
类都有重载,这些重载将
IXPathNavigatable
作为传递XML的参数。这个接口只有一个m方法XPathNavigator CreateNavigator()和
XElement
都有这样的方法。我不知道为什么微软没有声明
XElement
实现了这个接口。可能他们忘记了:-)。所以,为了弥补这个疏忽,我实现了6行转换器类
XNavigable
。您将在下面看到它。下面是一个模拟的OP页面加载()

public void Generate()
{
    XElement inputXml = CreateInputXml();
    XElement transformXslt = CreateTransformXslt();

    XslCompiledTransform transform = new XslCompiledTransform();
    transform.Load(new XNavigable(transformXslt), null, null);

    MemoryStream outputStream = new MemoryStream(); 
    transform.Transform(new XNavigable(inputXml), null, outputStream);

    byte[] outputBytes = outputStream.ToArray();
    string outputString = Encoding.UTF8.GetString(outputBytes);
}
我使用
MemoryStream
而不是
StringWriter
,因为StringWriter总是为我创建UTF-16编码的XML作为输出。我认为UTF-16是StringWriter强加的,因为底层字符串每个字符有16位。通过MemoryStream,我们可以控制编码

为了完整起见,这里是我的
CreateInputXml
CreateTransformXslt
方法的代码。它们只是示例。当然,
XElement.Add()
方法可以用来生成内容。我只是使用了构造函数,其中列出了所有节点,可以快速硬编码

    private static XElement CreateTransformXslt()
    {
        //XSL to substitute <placeholder/> with <realElement/> and copy everything else.
        //<stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform">
        //  <output indent="yes" />
        //  <template match="@* | node()">
        //    <copy>
        //      <apply-templates select="@* | node()" />
        //    </copy>
        //  </template>
        //  <template match="placeholder">
        //    <realElement xmlns="" />
        //  </template>
        //</stylesheet>
        XNamespace xsl = "http://www.w3.org/1999/XSL/Transform";
        XNamespace empty = "";
        XElement transformXslt = new XElement(xsl + "stylesheet", new XAttribute("version", "1.0"),
            new XElement(xsl + "output", new XAttribute("indent", "yes")),
            //new XElement(xsl + "strip-space", new XAttribute("elements", "*")),
            new XElement(xsl + "template", new XAttribute("match", "@* | node()"),
                new XElement(xsl + "copy",
                    new XElement(xsl + "apply-templates", new XAttribute("select", "@* | node()"))
                )
            ),
            new XElement(xsl + "template", new XAttribute("match", "placeholder"),
                new XElement("realElement")
            )
        );
        return transformXslt;
    }

    private static XElement CreateInputXml()
    {
        XElement origXml = new XElement(new XElement("Root",
                                            new XElement("Child1", "data1"),
                                            new XElement("placeholder"),
                                            new XElement("Child2", "data2")));
        return origXml;
    }

正如@kevin在评论中提到的,以下内容解决了我的问题,但我不太清楚为什么它会起作用(有一些想法,但不确定)

在xmlt_stream.Seek(0)之前添加objXMLTWriter.Flush(), SeekOrigin.开始)


正如@kevin在评论中提到的,以下内容解决了我的问题,但我不太清楚为什么它会起作用(有一些想法,但不确定)

在xmlt_stream.Seek(0)之前添加objXMLTWriter.Flush(), SeekOrigin.开始)


您没有向我们展示这两个Fn_*函数的使用位置,也没有向xslt_reader分配值的内容。如果您提供一个简短但完整的程序来演示这个问题,这将非常有帮助。我在页面加载时调用这些函数(我修改了我的问题)。关于xslt_reader,我在Fn_CreateXSL中分配值[或者你的意思是什么?]在xmlt_stream.Seek(0,SeekOrigin.Begin);-edit-在Flush()之前添加objXMLTWriter.Flush()。@Kevin cool dude…它修复了我的问题,现在有一些其他问题。无论如何,如果你将你的评论作为答案发布,我会接受它。你能解释一下我为什么添加Flush()吗?@Black:将来,你会做一些工作,将其转换为简短但完整的内容。我们不需要完整的程序——只需要足够的时间来演示问题。我强烈怀疑,你能想到的最短有效XSLT转换和一个很小的XML文件,从控制台应用程序加载,只需一个
Main
方法,就可以准确地显示e同样的问题。您没有告诉我们这两个Fn_*函数在哪里使用,也没有告诉我们是什么给xslt_uReader赋值的。如果您提供一个简短但完整的程序来演示这个问题,这将非常有帮助。我在页面加载时调用这些函数(我修改了我的问题)。关于xslt_reader,我在Fn_CreateXSL中赋值[或者你的意思是什么?]在xmlt_stream.Seek(0,SeekOrigin.Begin);-edit-在Flush()之前添加objXMLTWriter.Flush()。@Kevin cool dude…它修复了我的问题,现在有一些其他问题。无论如何,如果你将你的评论作为答案发布,我会接受它。你能解释一下我为什么添加Flush()吗?@Black:将来,你会做一些工作,将其转换为简短但完整的内容。我们不需要完整的程序——只需要足够的时间来演示问题。我强烈怀疑,你能想到的最短有效XSLT转换和一个很小的XML文件,从控制台应用程序加载,只需一个
Main
方法,就可以准确地显示e同样的问题。