Passing null to `XslCompiledTransform.Transform` m

2019-05-27 04:08发布

问题:

I am trying to transform and XML document using XSL. I am not too familiar with how to transform XML in .NET so I am using some example code ...

XslCompiledTransform xslTransformer = new XslCompiledTransform();
xslTransformer.Load(Server.MapPath("Test.xslt"));

MemoryStream ms = new MemoryStream();
xslTransformer.Transform(Server.MapPath("Test.xml"), null, ms);

ms.Seek(0, SeekOrigin.Begin);
StreamReader sr = new StreamReader(ms);
string output = sr.ReadToEnd();
ms.Close();

Response.Write(output); 

The problem I am running into is the following line ...

xslTransformer.Transform(Server.MapPath("Test.xml"), null, ms);

The compiler is showing an error in passing in null to the Transform method. In looking at the Transform method signatures it looks like the parameter null is representing is various options for the transformation. The Visual Studio IDE even shows that this value can be null. I also tried using DBNull.Value but that also shows an error. Any idea what I am missing?

UPDATE: The error I am receiving is two-fold. (1) First I am told that null is no longer supported and I should use System.DBNull. (2) Once I change null to System.DBNull I get an error saying overload resolution failed because no accessible Transform can be called with these arguments.

回答1:

You can try using a different XslCompiledTransform.Transform method overload, the one which accepts a String path and an XmlWriter:

XslCompiledTransform xslTransformer = new XslCompiledTransform();
xslTransformer.Load(Server.MapPath("Test.xslt"));

// XmlWriter allows you to specify additional settings
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.CloseOutput = false;

using (MemoryStream ms = new MemoryStream())
{
    using (XmlWriter writer = XmlWriter.Create(ms, settings))
    {
        xslTransformer.Transform(Server.MapPath("Test.xml"), writer);
    }

    ms.Seek(0, SeekOrigin.Begin);
    StreamReader sr = new StreamReader(ms);
    string output = sr.ReadToEnd();
    ms.Close();
}

Response.Write(output); 

Actually, if you are only interesting in rendering XML to a string, you can use a StringBuilder as the target, without a MemoryStream, and simplify your code to:

XslCompiledTransform xslTransformer = new XslCompiledTransform();
xslTransformer.Load(Server.MapPath("Test.xslt"));

StringBuilder sb = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(sb))
{
    xslTransformer.Transform(Server.MapPath("Test.xml"), writer);
}

Response.Write(sb.ToString()); 

[Edit] (based on your comment)

If the input XML is in a string, then you can use yet another XslCompiledTransform.Transform method overload: Transform(XmlReader, XmlWriter).

XmlReader can be (among other ways) instantiated using a concrete implementation of TextReader, in this case a StringReader. You can also use an other stream as input.

When you put all that together, you should end up with:

string input = @"<SomeXml />"
StringBuilder output = new StringBuilder();
using (StringReader strReader = new StringReader(input))
{
   using (XmlReader reader = XmlReader.Create(strReader))
   {
      using (XmlWriter writer = XmlWriter.Create(output))
      {
          xslTransformer.Transform(reader, writer);
      }
   }
}
Response.Write(output.ToString()); 

All of these classes implement IDisposable, so you need to make sure they are disposed after use.



回答2:

Are you sure it's the middle argument that's causing the error? Perhaps Server.MapPath("Test.xml") is returning null?