Saxon 中的 BaseUri 在尝试编译 xslt 内容时导致问题
BaseUri in Saxon causing problems when trying to compile xslt content
这是我的代码:
static void Main(string[] args)
{
string xml = File.ReadAllText("C:/Users/Davíð/source/Saxon/Saxon/data.xml");
string xslt = File.ReadAllText("C:/Users/Davíð/source/Saxon/Saxon/dataXslt.xsl");
string xmlCopy = File.ReadAllText("C:/Users/Davíð/source/Saxon/Saxon/data.xml");
TransformData(xml, xmlCopy, xslt);
}
static public void TransformData(string data, string xmlCopy, string xslt)
{
// Create a Processor instance.
Processor processor = new Processor();
// Create a compiled stylesheet
processor.NewXsltCompiler().BaseUri = new Uri("C:/Users/Davíð/source/Saxon/Saxon");
XsltExecutable templates = processor.NewXsltCompiler().Compile(new XmlTextReader(new StringReader(xslt)));
// Note: we could actually use the same Xslt30Transformer in this case.
// But in principle, the two transformations could be done in parallel in separate threads.
// Do the first transformation
Console.WriteLine("\n\n----- transform of " + data + " -----");
Xslt30Transformer transformer1 = templates.Load30();
XdmNode input1 = processor.NewDocumentBuilder().Build(new XmlTextReader(new StringReader(data)));
transformer1.ApplyTemplates(input1, processor.NewSerializer(Console.Out)); // default destination is Console.Out
// Do the second transformation
Console.WriteLine("\n\n----- transform of " + xmlCopy + " -----");
Xslt30Transformer transformer2 = templates.Load30();
XdmNode input2 = processor.NewDocumentBuilder().Build(new XmlTextReader(new StringReader(xmlCopy)));
transformer2.ApplyTemplates(input2, processor.NewSerializer(Console.Out)); // default destination is Console.Out
}
这是无论我是否删除 BaseUri 都会出现的错误。
未处理的异常:System.ArgumentNullException:值不能为空。
参数名称:BaseUri
在 Saxon.Api.XsltCompiler.Compile(XmlReader reader)
在 Saxon.Program.TransformData(String data, String xmlCopy, String xslt) in C:\Users\Davíð\source\Saxon\Saxon\Program.cs:line 33
在 Saxon.Program.Main(String[] args) 在 C:\Users\Davíð\source\Saxon\Saxon\Program.cs:line 22
根据评论,修复了下面的工作代码:
static void Main(string[] args)
{
string xml = File.ReadAllText("C:/Users/Davíð/source/Saxon/Saxon/data.xml");
string xslt = File.ReadAllText("C:/Users/Davíð/source/Saxon/Saxon/dataXslt.xsl");
TransformData(xml, xml, xslt);
}
static public void TransformData(string data, string xmlCopy, string xslt)
{
// Create a Processor instance.
Processor processor = new Processor();
// Create a compiled stylesheet
var compiler = processor.NewXsltCompiler();
compiler.BaseUri = new Uri("C:/Users/Davíð/source/Saxon/Saxon");
XsltExecutable templates = compiler.Compile(XmlReader.Create(new StringReader(xslt)));
// Note: we could actually use the same Xslt30Transformer in this case.
// But in principle, the two transformations could be done in parallel in separate threads.
// Do the first transformation
Console.WriteLine("\n\n----- transform of " + data + " -----");
Xslt30Transformer transformer1 = templates.Load30();
XdmNode input1 = processor.NewDocumentBuilder().Build(XmlReader.Create(new StringReader(data)));
transformer1.ApplyTemplates(input1, processor.NewSerializer(Console.Out)); // default destination is Console.Out
// Do the second transformation
Console.WriteLine("\n\n----- transform of " + xmlCopy + " -----");
Xslt30Transformer transformer2 = templates.Load30();
XdmNode input2 = processor.NewDocumentBuilder().Build(new XmlTextReader(new StringReader(xmlCopy)));
transformer2.ApplyTemplates(input2, processor.NewSerializer(Console.Out)); // default destination is Console.Out
}
您有几个问题:
processor.NewXsltCompiler()
returns 每次调用一个新的 XsltCompiler
。你叫它两次:
processor.NewXsltCompiler().BaseUri = new Uri("C:/Users/Davíð/source/Saxon/Saxon");
XsltExecutable templates = processor.NewXsltCompiler().Compile(new XmlTextReader(new StringReader(xslt)));
代码首先设置BaseUri
,然后创建另一个进行编译。因此 BaseUri
永远不会设置在实际用于工作的 XsltCompiler
上。
这是异常的直接原因未处理的异常:System.ArgumentNullException:值不能为空。参数名称:Saxon.Api.XsltCompiler.Compile(XmlReader reader) 处的 BaseUri。
您应该只创建一个 XsltCompiler
。
您正在使用 XmlTextReader
,但 XmlTextReader
has been deprecated since .Net 2.0 over 10 years ago. Instead, use XmlReader.Create(TextReader)
。另外,请务必事后处理。
您将文件 data.xml
内容的两个副本加载到内存中,加载到字符串 xml
和 xmlCopy
中。但是 .Net 中的字符串是不可变的,所以没有必要这样做。
因此您的代码应该类似于:
public static void Main(string[] args)
{
string xml = File.ReadAllText("C:/Users/Davíð/source/Saxon/Saxon/data.xml");
string xslt = File.ReadAllText("C:/Users/Davíð/source/Saxon/Saxon/dataXslt.xsl");
TransformData(xml, xml, xslt);
}
static public void TransformData(string xml1, string xml2, string xslt)
{
// Create a Processor instance.
var processor = new Processor();
// Create a compiled stylesheet
var compiler = processor.NewXsltCompiler();
compiler.BaseUri = new Uri("C:/Users/Davíð/source/Saxon/Saxon");
XsltExecutable templates;
using (var reader = XmlReader.Create(new StringReader(xslt)))
templates = compiler.Compile(reader);
// Note: we could actually use the same Xslt30Transformer in this case.
// But in principle, the two transformations could be done in parallel in separate threads.
// Do the first transformation
Console.WriteLine("\n\n----- transform of " + xml1 + " -----");
TransformData(processor, templates, xml1, Console.Out);
// Do the second transformation
Console.WriteLine("\n\n----- transform of " + xml2 + " -----");
TransformData(processor, templates, xml2, Console.Out);
}
private static void TransformData(Processor processor, XsltExecutable templates, string xml, TextWriter output)
{
var transformer = templates.Load30();
using (var reader = XmlReader.Create(new StringReader(xml)))
{
var input = processor.NewDocumentBuilder().Build(reader);
transformer.ApplyTemplates(input, processor.NewSerializer(output));
}
}
这是我的代码:
static void Main(string[] args)
{
string xml = File.ReadAllText("C:/Users/Davíð/source/Saxon/Saxon/data.xml");
string xslt = File.ReadAllText("C:/Users/Davíð/source/Saxon/Saxon/dataXslt.xsl");
string xmlCopy = File.ReadAllText("C:/Users/Davíð/source/Saxon/Saxon/data.xml");
TransformData(xml, xmlCopy, xslt);
}
static public void TransformData(string data, string xmlCopy, string xslt)
{
// Create a Processor instance.
Processor processor = new Processor();
// Create a compiled stylesheet
processor.NewXsltCompiler().BaseUri = new Uri("C:/Users/Davíð/source/Saxon/Saxon");
XsltExecutable templates = processor.NewXsltCompiler().Compile(new XmlTextReader(new StringReader(xslt)));
// Note: we could actually use the same Xslt30Transformer in this case.
// But in principle, the two transformations could be done in parallel in separate threads.
// Do the first transformation
Console.WriteLine("\n\n----- transform of " + data + " -----");
Xslt30Transformer transformer1 = templates.Load30();
XdmNode input1 = processor.NewDocumentBuilder().Build(new XmlTextReader(new StringReader(data)));
transformer1.ApplyTemplates(input1, processor.NewSerializer(Console.Out)); // default destination is Console.Out
// Do the second transformation
Console.WriteLine("\n\n----- transform of " + xmlCopy + " -----");
Xslt30Transformer transformer2 = templates.Load30();
XdmNode input2 = processor.NewDocumentBuilder().Build(new XmlTextReader(new StringReader(xmlCopy)));
transformer2.ApplyTemplates(input2, processor.NewSerializer(Console.Out)); // default destination is Console.Out
}
这是无论我是否删除 BaseUri 都会出现的错误。
未处理的异常:System.ArgumentNullException:值不能为空。 参数名称:BaseUri 在 Saxon.Api.XsltCompiler.Compile(XmlReader reader) 在 Saxon.Program.TransformData(String data, String xmlCopy, String xslt) in C:\Users\Davíð\source\Saxon\Saxon\Program.cs:line 33 在 Saxon.Program.Main(String[] args) 在 C:\Users\Davíð\source\Saxon\Saxon\Program.cs:line 22
根据评论,修复了下面的工作代码:
static void Main(string[] args)
{
string xml = File.ReadAllText("C:/Users/Davíð/source/Saxon/Saxon/data.xml");
string xslt = File.ReadAllText("C:/Users/Davíð/source/Saxon/Saxon/dataXslt.xsl");
TransformData(xml, xml, xslt);
}
static public void TransformData(string data, string xmlCopy, string xslt)
{
// Create a Processor instance.
Processor processor = new Processor();
// Create a compiled stylesheet
var compiler = processor.NewXsltCompiler();
compiler.BaseUri = new Uri("C:/Users/Davíð/source/Saxon/Saxon");
XsltExecutable templates = compiler.Compile(XmlReader.Create(new StringReader(xslt)));
// Note: we could actually use the same Xslt30Transformer in this case.
// But in principle, the two transformations could be done in parallel in separate threads.
// Do the first transformation
Console.WriteLine("\n\n----- transform of " + data + " -----");
Xslt30Transformer transformer1 = templates.Load30();
XdmNode input1 = processor.NewDocumentBuilder().Build(XmlReader.Create(new StringReader(data)));
transformer1.ApplyTemplates(input1, processor.NewSerializer(Console.Out)); // default destination is Console.Out
// Do the second transformation
Console.WriteLine("\n\n----- transform of " + xmlCopy + " -----");
Xslt30Transformer transformer2 = templates.Load30();
XdmNode input2 = processor.NewDocumentBuilder().Build(new XmlTextReader(new StringReader(xmlCopy)));
transformer2.ApplyTemplates(input2, processor.NewSerializer(Console.Out)); // default destination is Console.Out
}
您有几个问题:
processor.NewXsltCompiler()
returns 每次调用一个新的XsltCompiler
。你叫它两次:processor.NewXsltCompiler().BaseUri = new Uri("C:/Users/Davíð/source/Saxon/Saxon"); XsltExecutable templates = processor.NewXsltCompiler().Compile(new XmlTextReader(new StringReader(xslt)));
代码首先设置
BaseUri
,然后创建另一个进行编译。因此BaseUri
永远不会设置在实际用于工作的XsltCompiler
上。这是异常的直接原因未处理的异常:System.ArgumentNullException:值不能为空。参数名称:Saxon.Api.XsltCompiler.Compile(XmlReader reader) 处的 BaseUri。
您应该只创建一个
XsltCompiler
。您正在使用
XmlTextReader
,但XmlTextReader
has been deprecated since .Net 2.0 over 10 years ago. Instead, useXmlReader.Create(TextReader)
。另外,请务必事后处理。您将文件
data.xml
内容的两个副本加载到内存中,加载到字符串xml
和xmlCopy
中。但是 .Net 中的字符串是不可变的,所以没有必要这样做。
因此您的代码应该类似于:
public static void Main(string[] args)
{
string xml = File.ReadAllText("C:/Users/Davíð/source/Saxon/Saxon/data.xml");
string xslt = File.ReadAllText("C:/Users/Davíð/source/Saxon/Saxon/dataXslt.xsl");
TransformData(xml, xml, xslt);
}
static public void TransformData(string xml1, string xml2, string xslt)
{
// Create a Processor instance.
var processor = new Processor();
// Create a compiled stylesheet
var compiler = processor.NewXsltCompiler();
compiler.BaseUri = new Uri("C:/Users/Davíð/source/Saxon/Saxon");
XsltExecutable templates;
using (var reader = XmlReader.Create(new StringReader(xslt)))
templates = compiler.Compile(reader);
// Note: we could actually use the same Xslt30Transformer in this case.
// But in principle, the two transformations could be done in parallel in separate threads.
// Do the first transformation
Console.WriteLine("\n\n----- transform of " + xml1 + " -----");
TransformData(processor, templates, xml1, Console.Out);
// Do the second transformation
Console.WriteLine("\n\n----- transform of " + xml2 + " -----");
TransformData(processor, templates, xml2, Console.Out);
}
private static void TransformData(Processor processor, XsltExecutable templates, string xml, TextWriter output)
{
var transformer = templates.Load30();
using (var reader = XmlReader.Create(new StringReader(xml)))
{
var input = processor.NewDocumentBuilder().Build(reader);
transformer.ApplyTemplates(input, processor.NewSerializer(output));
}
}