You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在.NET Core(.NET 5)中基于XSLT 2.0文件实现Schematron验证的可行方案咨询

解决.NET 5中使用XSLT 2.0进行XML验证的问题

嘿,我来帮你梳理这个问题——首先得纠正你一个小误解:Saxon其实已经完全支持.NET Core/.NET 5及以上版本了!最新的SaxonCS是专门针对.NET平台开发的原生版本,支持XSLT 2.0/3.0,这应该是最省心的方案,先给你讲这个。

方案1:用SaxonCS直接跑你的XSLT 2.0文件

这是最优解,不需要修改现有XSLT,直接就能在.NET 5里用。

首先通过NuGet安装SaxonCS:

Install-Package SaxonCS

然后写一段简单的C#代码调用它执行验证(假设你的XSLT是用来输出验证错误信息的):

using Saxon.Api;
using System.IO;
using System.Xml;

// 初始化Saxon处理器
var processor = new Processor();
var compiler = processor.NewXsltCompiler();

// 加载你的XSLT 2.0文件
var xsltExecutable = compiler.Compile(new Uri(@"C:\path\to\your\validation-rules.xsl"));
var transformer = xsltExecutable.Load();

// 加载要验证的XML文档
var inputXml = new XmlDocument();
inputXml.Load(@"C:\path\to\your\input.xml");
var inputNode = processor.NewDocumentBuilder().Build(inputXml);
transformer.InitialContextNode = inputNode;

// 捕获验证输出结果
using var sw = new StringWriter();
var serializer = processor.NewSerializer(sw);
transformer.Run(serializer);

// 处理验证结果(比如打印错误或保存到文件)
var validationResult = sw.ToString();
Console.WriteLine(validationResult);

方案2:把XSLT 2.0降级为XSLT 1.0(如果必须用原生.NET)

如果因为某些限制不能用第三方库,那得手动把XSLT 2.0的特性转换成1.0的写法,这里列举几个常见的转换点:

1. 替换XSLT 2.0专属函数

像tokenize()、matches()、replace()这类2.0函数,XSLT 1.0本身不支持,但可以用EXSLT的扩展库(http://exslt.org/strings),或者自己写递归模板实现:

  • 比如2.0的tokenize($text, '\s+'),换成1.0+EXSLT的写法:
<!-- 先引入EXSLT命名空间 -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:str="http://exslt.org/strings" extension-element-prefixes="str">
  <!-- 使用str:tokenize替代原生tokenize -->
  <xsl:variable name="split-text" select="str:tokenize($text, ' ')"/>
</xsl:stylesheet>

2. 替换分组逻辑

XSLT 2.0的xsl:for-each-group要换成1.0里的Muenchian分组:

  • 2.0写法:
<xsl:for-each-group select="item" group-by="@category">
  <group category="{current-grouping-key()}">
    <xsl:copy-of select="current-group()"/>
  </group>
</xsl:for-each-group>
  • 1.0 Muenchian分组写法:
<!-- 先定义分组键 -->
<xsl:key name="item-by-category" match="item" use="@category"/>

<!-- 遍历每个分组的第一个节点 -->
<xsl:for-each select="item[generate-id() = generate-id(key('item-by-category', @category)[1])]">
  <group category="{@category}">
    <!-- 输出当前分组的所有节点 -->
    <xsl:copy-of select="key('item-by-category', @category)"/>
  </group>
</xsl:for-each>

3. 处理序列和多值变量

XSLT 2.0支持序列(比如$vals = ('a','b','c')),但1.0只能处理节点集或单个值。你可以把序列转换成虚拟节点集,比如:

<xsl:variable name="vals">
  <val>a</val>
  <val>b</val>
  <val>c</val>
</xsl:variable>
<!-- 使用exsl:node-set把树转换成节点集 -->
<xsl:variable name="vals-set" select="exsl:node-set($vals)/val" xmlns:exsl="http://exslt.org/common"/>

4. 移除强类型声明

XSLT 2.0的强类型(比如xs:int、xs:string)在1.0里不存在,需要去掉类型声明,改用number()这类函数做类型转换。

方案3:调用外部命令行工具

如果不想引入.NET库,还可以调用Saxon的Java命令行版本(Saxon-HE是免费的),通过.NET的Process类执行命令并捕获输出:

using System.Diagnostics;

var process = new Process();
process.StartInfo.FileName = "java";
// 假设你已经下载了Saxon-HE的jar包
process.StartInfo.Arguments = "-jar saxon-he-12.4.jar -s:C:\\path\\to\\input.xml -xsl:C:\\path\\to\\your-xslt2.xsl -o:C:\\path\\to\\validation-result.xml";
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
process.Start();

var output = process.StandardOutput.ReadToEnd();
process.WaitForExit();

// 处理输出结果
Console.WriteLine(output);

这个方案需要安装Java环境,适合对.NET依赖要求非常严格的场景。


内容的提问来源于stack exchange,提问作者S. Aziz Kazdal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 05:32:44