使用 Saxon 进行 Xslt2.0 转换的序列化器问题
Problem with the Serializer for a Xslt2.0 transformation with Saxon
这是我第一次尝试在 C# 中使用 SaxonHE 9.9 编写 Xslt2.0 转换程序,所以这里的问题是当我创建 serilizer 时出现错误,即 class Saxon.Api.Serializer
不包含带 0 个参数的构造器.
我知道这个错误是什么意思,但不知道为什么会发生,因为我看到的每个示例都会像这样创建序列化程序。这个问题听起来有点愚蠢,但我找不到让它工作的答案。
using Saxon.Api;
namespace XY
{
class Program
{
static void Main(string[] args)
{
String SourceFilename = "./test/test.xml";
String StylesheetFilename = "./scripte/xml-to-html.xsl";
String OutputFilename = "./Output/test.html";
using (FileStream streamXml = File.OpenRead(SourceFilename))
{
using (FileStream streamXsl = File.OpenRead(StylesheetFilename))
{
Processor processor = new Processor();
DocumentBuilder builder = processor.NewDocumentBuilder();
Uri uri = new Uri("urn:test");
builder.BaseUri = uri;
XdmNode input = builder.Build(streamXml);
XsltTransformer transformer = processor.NewXsltCompiler().Compile(streamXsl).Load();
transformer.InitialContextNode = input;
Serializer serializer = new Serializer();
serializer.SetOutputFile(OutputFilename);
transformer.Run(serializer);
}
}
Console.WriteLine("test.html created successfully");
}
}
}
编辑
using System;
using Saxon.Api;
using System.IO;
using System.Reflection;
namespace XY
{
class Program
{
static void Main(string[] args)
{
string currentDirectory = Directory.GetCurrentDirectory();
String SourceFilename = ".\test\test.xml";
String StylesheetFilename = ".\scripte\xml-to-html.xsl";
String OutputFilename = ".\Output\result.html";
if (StylesheetFilename.StartsWith(".\"))
{
StylesheetFilename = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\" + StylesheetFilename;
}
if (SourceFilename.StartsWith(".\"))
{
SourceFilename = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\" + SourceFilename;
}
var uri_source = new System.Uri(SourceFilename);
var uri_xsl = new System.Uri(StylesheetFilename);
Processor processor = new Processor();
XdmNode input = processor.NewDocumentBuilder().Build(uri_source);
processor.SetProperty("http://saxon.sf.net/feature/preferJaxpParser", "true");
XsltCompiler compiler = processor.NewXsltCompiler();
XsltExecutable executable = compiler.Compile(uri_xsl);
XsltTransformer transformer = executable.Load();
transformer.InitialContextNode = input;
Serializer serializer = processor.NewSerializer();
System.IO.StreamWriter stream = new StreamWriter(OutputFilename);
serializer.SetOutputWriter(stream);
transformer.Run(serializer);
stream.Close();
}
}
}
我也改变了一些其他的想法,现在可以了,感谢您的回答。
在 9.9 中,您可以(或确实需要)使用 processor.NewSerializer
的各种重载创建 Serializer
(参见 http://saxonica.com/html/documentation/dotnetdoc/Saxon/Api/Processor.html#NewSerializer(Stream))..
我将记录一个错误,因为有示例应用 and/or 文档使用 "new Serializer()" 形式。
我们在 9.8 中从 Java 产品中删除了它,因为它导致序列化器无法(必然)访问所有配置选项(保存在处理器中)的持续麻烦;同样使用工厂方法 Processor.newSerializer()
可能允许我们创建 Serializer
的子类,因此它更灵活。然后,我们在 9.9 版本的 .NET 上遵循了这种模式,部分原因是相同的,部分原因是 .NET API 现在已被重写为 Java API,这有助于我们保持通用性,并简化测试。
我们努力在主要产品 API 中保持向后兼容性,但这并不是覆盖所有其他要求的要求;如果我们觉得我们有什么严重的错误,我们就会解决它。正如一些人所说的为政策辩护,"the future is longer than the past".
稍后
我们已经做了一些检查,我们认为 9.9 文档和示例应用程序是正确的;您必须使用旧版本。如果我错了,请指出您发现错误信息的具体位置。
这是我对问题的解决方案:
using System;
using System.IO;
using Saxon.Api;
namespace Project1
{
public static class ClassMain
{
public static string TransformXml(string xmlData, string xslData)
{
var xsltProcessor = new Processor();
var documentBuilder = xsltProcessor.NewDocumentBuilder();
documentBuilder.BaseUri = new Uri("file://");
var xdmNode = documentBuilder.Build(new StringReader(xmlData));
var xsltCompiler = xsltProcessor.NewXsltCompiler();
var xsltExecutable = xsltCompiler.Compile(new StringReader(xslData));
var xsltTransformer = xsltExecutable.Load();
xsltTransformer.InitialContextNode = xdmNode;
var results = new XdmDestination();
xsltTransformer.Run(results);
return results.XdmNode.OuterXml;
}
public static void Main()
{
var xmlData = File.ReadAllText("a.xml");
var xslData = File.ReadAllText("a.xsl");
var data = TransformXml(xmlData, xslData);
Console.WriteLine(data);
Console.ReadKey();
}
}
}
这是我第一次尝试在 C# 中使用 SaxonHE 9.9 编写 Xslt2.0 转换程序,所以这里的问题是当我创建 serilizer 时出现错误,即 class Saxon.Api.Serializer
不包含带 0 个参数的构造器.
我知道这个错误是什么意思,但不知道为什么会发生,因为我看到的每个示例都会像这样创建序列化程序。这个问题听起来有点愚蠢,但我找不到让它工作的答案。
using Saxon.Api;
namespace XY
{
class Program
{
static void Main(string[] args)
{
String SourceFilename = "./test/test.xml";
String StylesheetFilename = "./scripte/xml-to-html.xsl";
String OutputFilename = "./Output/test.html";
using (FileStream streamXml = File.OpenRead(SourceFilename))
{
using (FileStream streamXsl = File.OpenRead(StylesheetFilename))
{
Processor processor = new Processor();
DocumentBuilder builder = processor.NewDocumentBuilder();
Uri uri = new Uri("urn:test");
builder.BaseUri = uri;
XdmNode input = builder.Build(streamXml);
XsltTransformer transformer = processor.NewXsltCompiler().Compile(streamXsl).Load();
transformer.InitialContextNode = input;
Serializer serializer = new Serializer();
serializer.SetOutputFile(OutputFilename);
transformer.Run(serializer);
}
}
Console.WriteLine("test.html created successfully");
}
}
}
编辑
using System;
using Saxon.Api;
using System.IO;
using System.Reflection;
namespace XY
{
class Program
{
static void Main(string[] args)
{
string currentDirectory = Directory.GetCurrentDirectory();
String SourceFilename = ".\test\test.xml";
String StylesheetFilename = ".\scripte\xml-to-html.xsl";
String OutputFilename = ".\Output\result.html";
if (StylesheetFilename.StartsWith(".\"))
{
StylesheetFilename = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\" + StylesheetFilename;
}
if (SourceFilename.StartsWith(".\"))
{
SourceFilename = System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\" + SourceFilename;
}
var uri_source = new System.Uri(SourceFilename);
var uri_xsl = new System.Uri(StylesheetFilename);
Processor processor = new Processor();
XdmNode input = processor.NewDocumentBuilder().Build(uri_source);
processor.SetProperty("http://saxon.sf.net/feature/preferJaxpParser", "true");
XsltCompiler compiler = processor.NewXsltCompiler();
XsltExecutable executable = compiler.Compile(uri_xsl);
XsltTransformer transformer = executable.Load();
transformer.InitialContextNode = input;
Serializer serializer = processor.NewSerializer();
System.IO.StreamWriter stream = new StreamWriter(OutputFilename);
serializer.SetOutputWriter(stream);
transformer.Run(serializer);
stream.Close();
}
}
}
我也改变了一些其他的想法,现在可以了,感谢您的回答。
在 9.9 中,您可以(或确实需要)使用 processor.NewSerializer
的各种重载创建 Serializer
(参见 http://saxonica.com/html/documentation/dotnetdoc/Saxon/Api/Processor.html#NewSerializer(Stream))..
我将记录一个错误,因为有示例应用 and/or 文档使用 "new Serializer()" 形式。
我们在 9.8 中从 Java 产品中删除了它,因为它导致序列化器无法(必然)访问所有配置选项(保存在处理器中)的持续麻烦;同样使用工厂方法 Processor.newSerializer()
可能允许我们创建 Serializer
的子类,因此它更灵活。然后,我们在 9.9 版本的 .NET 上遵循了这种模式,部分原因是相同的,部分原因是 .NET API 现在已被重写为 Java API,这有助于我们保持通用性,并简化测试。
我们努力在主要产品 API 中保持向后兼容性,但这并不是覆盖所有其他要求的要求;如果我们觉得我们有什么严重的错误,我们就会解决它。正如一些人所说的为政策辩护,"the future is longer than the past".
稍后
我们已经做了一些检查,我们认为 9.9 文档和示例应用程序是正确的;您必须使用旧版本。如果我错了,请指出您发现错误信息的具体位置。
这是我对问题的解决方案:
using System;
using System.IO;
using Saxon.Api;
namespace Project1
{
public static class ClassMain
{
public static string TransformXml(string xmlData, string xslData)
{
var xsltProcessor = new Processor();
var documentBuilder = xsltProcessor.NewDocumentBuilder();
documentBuilder.BaseUri = new Uri("file://");
var xdmNode = documentBuilder.Build(new StringReader(xmlData));
var xsltCompiler = xsltProcessor.NewXsltCompiler();
var xsltExecutable = xsltCompiler.Compile(new StringReader(xslData));
var xsltTransformer = xsltExecutable.Load();
xsltTransformer.InitialContextNode = xdmNode;
var results = new XdmDestination();
xsltTransformer.Run(results);
return results.XdmNode.OuterXml;
}
public static void Main()
{
var xmlData = File.ReadAllText("a.xml");
var xslData = File.ReadAllText("a.xsl");
var data = TransformXml(xmlData, xslData);
Console.WriteLine(data);
Console.ReadKey();
}
}
}