如何在 .NET 中使用 Saxon-HE 9.8 使用 XSLT 3.0
Posted
技术标签:
【中文标题】如何在 .NET 中使用 Saxon-HE 9.8 使用 XSLT 3.0【英文标题】:How to use XSLT 3.0 using Saxon-HE 9.8 in .NET 【发布时间】:2018-06-11 19:45:46 【问题描述】:我正在使用 Win7 并将我的 VSC# 项目设置为 .NETFramework4。
然后下载 SaxonHE9-8-0-7N-setup.exe 并安装。
然后将 saxon9he-api.dll 引用到 C# 项目和using Saxon.Api;
这是我的program.cs
:
static void Main(string[] args)
var xslt = new FileInfo(Path.GetFullPath(Path.Combine(Environment.CurrentDirectory.ToString(), @"..\..\..")) + @"\TEST.xslt");
var input = new FileInfo(Path.GetFullPath(Path.Combine(Environment.CurrentDirectory.ToString(), @"..\..\..")) + @"\TEST.xml");
var output = new FileInfo(Path.GetFullPath(Path.Combine(Environment.CurrentDirectory.ToString(), @"..\..\..")) + @"\result.txt");
var processor = new Processor();
var compiler = processor.NewXsltCompiler();
var executable = compiler.Compile(new Uri(xslt.FullName));
var transformer = executable.Load();
var serializer = new Serializer();
FileStream outStream = new FileStream(output.ToString(), FileMode.Create, FileAccess.Write);
serializer.SetOutputStream(outStream);
using (var inputStream = input.OpenRead())
transformer.SetInputStream(inputStream, new Uri(Path.GetTempPath()));
transformer.SetParameter(new QName("password"), new XdmAtomicValue("secret"));
transformer.Run(serializer);
outStream.Close();
这是我的TEST.xslt
:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:array="http://www.w3.org/2005/xpath-functions/array"
exclude-result-prefixes="xs math map array"
version="3.0">
<xsl:output method="json" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="root">
<xsl:map>
<xsl:map-entry key="local-name()">
<xsl:apply-templates/>
</xsl:map-entry>
</xsl:map>
</xsl:template>
<xsl:template match="items">
<xsl:variable name="items" as="item()*">
<xsl:apply-templates/>
</xsl:variable>
<xsl:sequence select="map local-name() : array $items "/>
</xsl:template>
<xsl:template match="item">
<xsl:sequence select="map 'foo' : xs:integer(foo), 'bar' : string(bar) "/>
</xsl:template>
</xsl:stylesheet>
在运行之前我收到两条错误消息:
命名空间“http://www.w3.org/1999/XSL/Transform”中的元素“模板”具有无效的子元素“地图”
和
'as' 属性未声明。
运行时我收到一条错误消息:
xsl:map-entry/@key TEST.xslt:FOTY0013 中的错误:无法在未命名模式下的 /root 的内置模板规则中将函数项写入 XML 树**
那么我应该怎么做才能不出错地运行这段代码呢?
【问题讨论】:
附言。 TEST.xml 内容:对于 9.9 使用 var serializer = processor.NewSerializer();
【讨论】:
您为什么推荐这种方法而不是其他建议?有没有值得一提的好处?这是一个很好的机会,不仅可以帮助人们了解做什么,还可以了解为什么要这样做。【参考方案2】:因为我在将此解决方案转换为 HE-9.9 时遇到问题,所以这是我的解决方案 - 需要注意的是它适用于 9.9 而不适用于 9.8:
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();
【讨论】:
【参考方案3】:改行创建Transformer创建Xslt30Transformer
var transformer = executable.Load30();
使用 XSLT 3 及其各种不同且更灵活的输入和输出选项,然后运行样式表使用
using (var inputStream = input.OpenRead())
transformer.ApplyTemplates(inputStream, serializer);
outStream.Close();
这样,我之前发布的 XSLT 代码和您用作示例的 XSLT 代码运行良好(我必须调整文件路径,但这显然取决于文件与 C# 项目相关的方式/位置)。
请注意,通常使用 XSLT 3,初始匹配选择和用于初始化全局变量的全局上下文项可能不同,示例样式表没有任何全局变量或参数,但如果有,您还需要设置GlobalContextItem (https://www.saxonica.com/html/documentation/dotnetdoc/Saxon/Api/Xslt30Transformer.html#GlobalContextItem) 到 XdmValue。
至于您在 Visual Studio 中编辑 XSLT 3 时收到的各种编辑器警告或错误消息,好吧,只是在您的系统上安装 XSLT 3 处理器不会将 VS 转换为 XSLT 3 编辑器,您需要检查是否/如何设置 Visual Studio 以使用 XSLT 3 架构,XSLT 3 规范在https://www.w3.org/TR/xslt-30/schema-for-xslt30.xsd 有一个链接,但我认为它使用架构语言 1.1,而 Microsoft 仅支持架构语言版本 1.0,因此可能有点困难为 VS 查找并安装一个架构,使其能够识别并支持 XSLT 3 编辑。
【讨论】:
拯救了我的一天!!但我很惊讶没有多少人有同样的问题。 我认为大多数从事 XSLT 开发的人都在使用基于 XML 的 IDE,例如 oXygen XML、Stylus Studio 或 XML Spy,与 Visual Studio 不同的是,它们都支持 XSLT 3.0 编辑。 扩大答案。这两个编译时错误消息是因为 VS 不理解 XSLT 3.0 - 这些消息来自 VS,而不是来自 Saxon。运行时错误消息是因为 Saxon 的 XsltTransformer API 无法处理“json”输出方法;这就是您需要切换到 Xslt30Transformer API 的原因。 @MichaelKay Visual Studio 支持 XSLT 3.0 编辑,如果您提供 XSLT 的 XSD 1.0 架构。以上是关于如何在 .NET 中使用 Saxon-HE 9.8 使用 XSLT 3.0的主要内容,如果未能解决你的问题,请参考以下文章
XRechnung Visualizer 和 Saxon-HE for .NET 的自闭合 DIV 标签问题
Saxon-HE Java 扩展 - 如何访问作为参数传递的 xsl 变量的值?
在 C# 中使用 Saxon-HE 对 XDocument 执行具有给定上下文的 XQuery