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

UBL XML的Schematron验证:ISO XSL与SVRL XSL选型及实现咨询

针对Schematron转XSL后验证XML的解决方案

首先,先帮你理清ISO XSL和SVRL XSL的区别,再结合你的代码给出具体调整建议:

一、ISO Schematron XSL vs SVRL XSL

  • ISO Schematron XSL:是直接把Schematron规则转换成通用XSLT,运行时会直接对XML进行验证并抛出错误(或自定义处理逻辑),不会生成标准化的验证报告。
  • SVRL XSL:转换后的XSL会生成符合Schematron Validation Report Language规范的XML报告,报告里包含<svrl:failed-assert>、<svrl:text>这类标准化错误节点——这正是你的代码里在读取的内容,所以你现在用的应该是SVRL类型的XSL(Oxygen默认转换选项一般就是生成SVRL)。

二、你的代码问题与优化建议

1. 替换过时的API

XmlTextReader已被标记为过时,建议改用XmlReader.Create来避免潜在的兼容性问题。

2. 处理命名空间的ID查找

你代码里用document.GetElementsByTagName("cbc:ID")可能会因为命名空间前缀不匹配找不到元素,因为cbc只是前缀,实际XML里对应的命名空间URI才是关键。建议改用XPath查询来处理命名空间:

XmlNamespaceManager nsManager = new XmlNamespaceManager(document.NameTable);
nsManager.AddNamespace("cbc", "http://你的cbc命名空间URI"); // 替换成XML中cbc前缀对应的实际URI
XmlElement elementId = document.SelectSingleNode("//cbc:ID", nsManager) as XmlElement;

3. 优化验证流程

不需要把XmlDocument转成StringReader再用XmlTextReader加载,可以直接从XmlDocument构建Saxon输入节点,减少冗余转换。

调整后的完整代码示例

转换方法(优化版)

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

public static Stream Transform(XmlDocument xmlDoc)
{
    try
    {
        var processor = new Processor();
        // 直接从XmlDocument构建Saxon的XdmNode
        var docBuilder = processor.NewDocumentBuilder();
        docBuilder.BaseUri = new Uri("file:///"); // 设置基础URI避免路径问题
        var input = docBuilder.Build(xmlDoc);

        var compiler = processor.NewXsltCompiler();
        // 用XmlReader.Create替换过时的XmlTextReader
        using var xslReader = XmlReader.Create(@"C:\Tools\Schematron\Schematron.xsl");
        var transformer = compiler.Compile(xslReader).Load();
        transformer.InitialContextNode = input;

        var resultStream = new MemoryStream();
        var serializer = processor.NewSerializer(resultStream);
        transformer.Run(serializer);
        resultStream.Position = 0;
        return resultStream;
    }
    catch (Exception ex)
    {
        // 添加详细错误信息方便调试
        throw new InvalidOperationException("XSLT转换失败", ex);
    }
}

验证方法(优化版)

using System.Collections.Generic;
using System.Linq;
using System.Xml;

public class ValidationResult
{
    public List<string> ErrorMessageList { get; set; } = new List<string>();
    public bool IsValid { get; set; }
}

public static ValidationResult SchematronValidateXml(List<XmlDocument> xmlList)
{
    var result = new ValidationResult();
    // 提前定义命名空间管理器,避免重复创建
    XmlNamespaceManager nsManager = new XmlNamespaceManager(new NameTable());
    nsManager.AddNamespace("cbc", "http://你的cbc命名空间URI"); // 替换为实际URI
    nsManager.AddNamespace("svrl", "http://purl.oclc.org/dsdl/svrl"); // SVRL标准命名空间

    foreach (var document in xmlList)
    {
        using var resultStream = Transform(document);
        using var xmlReader = XmlReader.Create(resultStream);
        // 加载SVRL报告文档,用XPath批量查询错误
        XmlDocument svrlReport = new XmlDocument();
        svrlReport.Load(xmlReader);

        var errorNodes = svrlReport.SelectNodes("//svrl:text", nsManager);
        if (errorNodes != null && errorNodes.Count > 0)
        {
            // 获取当前XML的ID
            string id = "无ID";
            XmlElement elementId = document.SelectSingleNode("//cbc:ID", nsManager) as XmlElement;
            if (elementId != null) id = elementId.InnerText;

            foreach (XmlNode errorNode in errorNodes)
            {
                result.ErrorMessageList.Add($"Schematron ({id}) : {errorNode.InnerText}");
            }
        }
    }

    result.IsValid = !result.ErrorMessageList.Any();
    return result;
}

三、后续操作步骤

  1. 确认XSL类型:打开Oxygen的Schematron转换设置,确保选择的是"Generate SVRL"(或类似选项),这样转换后的XSL才会输出你代码依赖的SVRL格式报告。
  2. 替换命名空间URI:把代码里的http://你的cbc命名空间URI替换成你XML中cbc前缀对应的实际命名空间(可查看XML根元素的xmlns:cbc属性值)。
  3. 测试验证逻辑:分别用合格和不合格的XML测试,检查ErrorMessageList是否正确捕获错误,IsValid是否准确反映验证结果。
  4. 增强错误处理:建议添加日志记录,方便调试转换或验证过程中出现的异常。

内容的提问来源于stack exchange,提问作者Tester3

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 10:37:30