最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

xslt - Running schematron validation from seperated schematron files - Stack Overflow

programmeradmin0浏览0评论

I have a schematron file which is seperated to 3 files. One file contains using codes list, other one contains details and messages which will be fired and other one contains declaration of these rules. I don't have a version or queryBinding property on root. So i guess it is a XSLT 1.0. I have used SaxonCS and SchXslt before while running a Xslt 2.0 validation. What do i have to do on this case? I am providing some sample blocks from files below.

File 1

<?xml version="1.0" encoding="UTF-8"?>
<sch:schema xmlns="; 
            xmlns:sch="; 
            xmlns:sh="; 
            xmlns:ef=";>
    
    <sch:include href="UBL-TR_Codelist.xml#codes"/>
    <sch:include href="UBL-TR_Common_Schematron.xml#abstracts"/>    
        
    <sch:ns prefix="sh" uri="; />
    <sch:ns prefix="ef" uri="; />
    <sch:ns prefix="inv" uri="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" />
    <sch:ns prefix="apr" uri="urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2" />
    <sch:ns prefix="desp" uri="urn:oasis:names:specification:ubl:schema:xsd:DespatchAdvice-2" />
    <sch:ns prefix="recp" uri="urn:oasis:names:specification:ubl:schema:xsd:ReceiptAdvice-2" />
    
    <sch:ns prefix="cac" uri="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" />
    <sch:ns prefix="cbc" uri="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" />
    <sch:ns prefix="ext" uri="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" />
    <sch:ns prefix="ds" uri="; />
    <sch:ns prefix="xades" uri=".3.2#" />   
    <sch:ns prefix="hr" uri="; />
    <sch:ns prefix="oa" uri="; />
    <sch:ns prefix="xsi" uri="; />
    
    <let name="envelopeType" value="/sh:StandardBusinessDocument/sh:StandardBusinessDocumentHeader/sh:DocumentIdentification/sh:Type"/>
    <let name="senderId" value="/sh:StandardBusinessDocument/sh:StandardBusinessDocumentHeader/sh:Sender/sh:ContactInformation[sh:ContactTypeIdentifier = 'VKN_TCKN']/sh:Contact"/>
    <let name="senderAlias" value="/sh:StandardBusinessDocument/sh:StandardBusinessDocumentHeader/sh:Sender/sh:Identifier"/>
    <let name="receiverId" value="/sh:StandardBusinessDocument/sh:StandardBusinessDocumentHeader/sh:Receiver/sh:ContactInformation[sh:ContactTypeIdentifier = 'VKN_TCKN']/sh:Contact"/>
    <let name="receiverAlias" value="/sh:StandardBusinessDocument/sh:StandardBusinessDocumentHeader/sh:Receiver/sh:Identifier"/>
    <let name="responseCode" value="//apr:ApplicationResponse/cac:DocumentResponse/cac:Response/cbc:ResponseCode" />
     
    <!-- Invoice -->
    <sch:pattern id="invoice">   
        <sch:rule context="inv:Invoice">
            <sch:extends rule="UBLVersionIDCheck"/>
            <sch:extends rule="CustomizationIDCheck"/>
            <sch:extends rule="ProfileIDCheck"/>
            <sch:extends rule="InvoiceIDCheck"/>
            <sch:extends rule="CopyIndicatorCheck"/>
            <!--<sch:extends rule="TimeCheck"/>-->
            <sch:extends rule="InvoiceTypeCodeCheck"/>
            <sch:extends rule="CurrencyCodeCheck"/>
            <!-- <sch:extends rule="URI2IDCheck"/> -->
            <sch:extends rule="SignatureCountCheck"/>
            <sch:extends rule="GeneralWithholdingTaxTotalCheck"/>
            <sch:extends rule="DeliveryCodeCheck"/>
            <sch:extends rule="TaxRepresentativePartyCheck"/>
            <sch:extends rule="HKSInvioceCheck"/>
            <sch:extends rule="IADEInvioceCheck"/>
            <sch:extends rule="IlacTibbiCihazInvoiceTypeCodeCheck"/>            
        </sch:rule> 
 
    </sch:pattern> 
</sch:schema>

File 2

<sch:schema xmlns="; 
            xmlns:sch=";>

    <sch:pattern name="AbstractRules" id="abstracts">
        <sch:p>Pattern for storing abstract rules</sch:p>
        
        <!-- Rule to validate UBLVersionID -->
        <sch:rule abstract="true" id="UBLVersionIDCheck">
            <sch:assert test="cbc:UBLVersionID = '2.1'">Geçersiz cbc:UBLVersionID elemanı değeri : '<sch:value-of select="cbc:UBLVersionID"/>'. cbc:UBLVersionID değeri '2.1' olmalıdır.</sch:assert>
        </sch:rule>
        
        
        <!-- Rule to validate CustomizationID -->
        <sch:rule abstract="true" id="CustomizationIDCheck">
            <sch:assert test="cbc:CustomizationID = 'TR1.2' or cbc:CustomizationID = 'TR1.2.1'">Geçersiz cbc:CustomizationID elemanı değeri : '<sch:value-of select="cbc:CustomizationID"/>' cbc:CustomizationID elemanı değeri 'TR1.2' veya 'TR1.2.1' olmalıdır.</sch:assert>
        </sch:rule>
        
        <!-- Rule to validate ProfileID -->
        <sch:rule abstract="true" id="ProfileIDCheck">
            <sch:assert test="not($type = 'efatura' or $type = '' or not($type)) or contains($ProfileIDType, concat(',',cbc:ProfileID,','))">Geçersiz cbc:ProfileID elemanı değeri : '<sch:value-of select="cbc:ProfileID"/>'. Geçerli cbc:ProfileID değerleri için ProfileIDType listesine bakınız.</sch:assert>
            <sch:assert test="not($type = 'earchive') or contains($ProfileIDTypeEarchive, concat(',',cbc:ProfileID,','))">Geçersiz cbc:ProfileID elemanı değeri : '<sch:value-of select="cbc:ProfileID"/>'. Geçerli cbc:ProfileID değerleri için ProfileIDTypeEarchive listesine bakınız.</sch:assert>
            <sch:assert test="not($type = 'goruntuleme') or contains($ProfileIDTypeGoruntuleme, concat(',',cbc:ProfileID,','))">Geçersiz cbc:ProfileID elemanı değeri : '<sch:value-of select="cbc:ProfileID"/>'. Geçerli cbc:ProfileID değerleri için ProfileIDTypeGoruntuleme listesine bakınız.</sch:assert>
            <sch:assert test="not(@xsi:schemaLocation) or contains(@xsi:schemaLocation,'UBL-Invoice-2.1.xsd')">Invoice alanın  xsi:schemaLocation özeliği 'UBL-Invoice-2.1.xsd' olmalıdır</sch:assert>
        </sch:rule> 
    </sch:pattern>
</sch:schema>

Source Code :

var fileName = Path.GetFileName(inputXml); 
var inputSch = "E:/aa/schematrontest/UBL-TR_Main_Schematron.xml";

string schxsltSvrlXsltResource = @"SchematronSchxsltSaxonCSValidator\schxslt_xslt1\iso_svrl_for_xslt1.xsl";
var schxsltResourceUri = UriUtils.GetLocationUri(schxsltSvrlXsltResource, Assembly.GetExecutingAssembly());

var resolver = new Resolver();

var settings = new XmlReaderSettings() { XmlResolver = resolver };

var processor = new Processor(true);
var xsltCompiler = processor.NewXsltCompiler();

using var schxsltReader = XmlReader.Create(schxsltResourceUri.AbsoluteUri, settings);


var transformer = xsltCompiler.Compile(schxsltReader).Load30();

var compiledSchematron = new XdmDestination();
compiledSchematron.BaseUri = new Uri(new FileInfo(inputSch).FullName);

using var schemaStream = File.OpenRead(inputSch);

transformer.Transform(schemaStream, compiledSchematron);

var xsltCompiler2 = processor.NewXsltCompiler();

var schematronValidator = xsltCompiler2.Compile(compiledSchematron.XdmNode).Load30();

var svrlResult = new DomDestination();

using var instanceStream = File.OpenRead(inputXml);
schematronValidator.Transform(instanceStream, new Uri(new FileInfo(inputXml).FullName), svrlResult);
List<ErrorModel> errors = new List<ErrorModel>();

var failedNodes = svrlResult.XmlDocument.GetElementsByTagName("svrl:failed-assert");

I have a schematron file which is seperated to 3 files. One file contains using codes list, other one contains details and messages which will be fired and other one contains declaration of these rules. I don't have a version or queryBinding property on root. So i guess it is a XSLT 1.0. I have used SaxonCS and SchXslt before while running a Xslt 2.0 validation. What do i have to do on this case? I am providing some sample blocks from files below.

File 1

<?xml version="1.0" encoding="UTF-8"?>
<sch:schema xmlns="http://purl.oclc./dsdl/schematron" 
            xmlns:sch="http://purl.oclc./dsdl/schematron" 
            xmlns:sh="http://www.unece./cefact/namespaces/StandardBusinessDocumentHeader" 
            xmlns:ef="http://www.efatura.gov.tr/envelope-namespace">
    
    <sch:include href="UBL-TR_Codelist.xml#codes"/>
    <sch:include href="UBL-TR_Common_Schematron.xml#abstracts"/>    
        
    <sch:ns prefix="sh" uri="http://www.unece./cefact/namespaces/StandardBusinessDocumentHeader" />
    <sch:ns prefix="ef" uri="http://www.efatura.gov.tr/package-namespace" />
    <sch:ns prefix="inv" uri="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" />
    <sch:ns prefix="apr" uri="urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2" />
    <sch:ns prefix="desp" uri="urn:oasis:names:specification:ubl:schema:xsd:DespatchAdvice-2" />
    <sch:ns prefix="recp" uri="urn:oasis:names:specification:ubl:schema:xsd:ReceiptAdvice-2" />
    
    <sch:ns prefix="cac" uri="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" />
    <sch:ns prefix="cbc" uri="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" />
    <sch:ns prefix="ext" uri="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" />
    <sch:ns prefix="ds" uri="http://www.w3./2000/09/xmldsig#" />
    <sch:ns prefix="xades" uri="http://uri.etsi./01903/v1.3.2#" />   
    <sch:ns prefix="hr" uri="http://www.hr-xml./3" />
    <sch:ns prefix="oa" uri="http://www.openapplications./oagis/9" />
    <sch:ns prefix="xsi" uri="http://www.w3./2001/XMLSchema-instance" />
    
    <let name="envelopeType" value="/sh:StandardBusinessDocument/sh:StandardBusinessDocumentHeader/sh:DocumentIdentification/sh:Type"/>
    <let name="senderId" value="/sh:StandardBusinessDocument/sh:StandardBusinessDocumentHeader/sh:Sender/sh:ContactInformation[sh:ContactTypeIdentifier = 'VKN_TCKN']/sh:Contact"/>
    <let name="senderAlias" value="/sh:StandardBusinessDocument/sh:StandardBusinessDocumentHeader/sh:Sender/sh:Identifier"/>
    <let name="receiverId" value="/sh:StandardBusinessDocument/sh:StandardBusinessDocumentHeader/sh:Receiver/sh:ContactInformation[sh:ContactTypeIdentifier = 'VKN_TCKN']/sh:Contact"/>
    <let name="receiverAlias" value="/sh:StandardBusinessDocument/sh:StandardBusinessDocumentHeader/sh:Receiver/sh:Identifier"/>
    <let name="responseCode" value="//apr:ApplicationResponse/cac:DocumentResponse/cac:Response/cbc:ResponseCode" />
     
    <!-- Invoice -->
    <sch:pattern id="invoice">   
        <sch:rule context="inv:Invoice">
            <sch:extends rule="UBLVersionIDCheck"/>
            <sch:extends rule="CustomizationIDCheck"/>
            <sch:extends rule="ProfileIDCheck"/>
            <sch:extends rule="InvoiceIDCheck"/>
            <sch:extends rule="CopyIndicatorCheck"/>
            <!--<sch:extends rule="TimeCheck"/>-->
            <sch:extends rule="InvoiceTypeCodeCheck"/>
            <sch:extends rule="CurrencyCodeCheck"/>
            <!-- <sch:extends rule="URI2IDCheck"/> -->
            <sch:extends rule="SignatureCountCheck"/>
            <sch:extends rule="GeneralWithholdingTaxTotalCheck"/>
            <sch:extends rule="DeliveryCodeCheck"/>
            <sch:extends rule="TaxRepresentativePartyCheck"/>
            <sch:extends rule="HKSInvioceCheck"/>
            <sch:extends rule="IADEInvioceCheck"/>
            <sch:extends rule="IlacTibbiCihazInvoiceTypeCodeCheck"/>            
        </sch:rule> 
 
    </sch:pattern> 
</sch:schema>

File 2

<sch:schema xmlns="http://purl.oclc./dsdl/schematron" 
            xmlns:sch="http://purl.oclc./dsdl/schematron">

    <sch:pattern name="AbstractRules" id="abstracts">
        <sch:p>Pattern for storing abstract rules</sch:p>
        
        <!-- Rule to validate UBLVersionID -->
        <sch:rule abstract="true" id="UBLVersionIDCheck">
            <sch:assert test="cbc:UBLVersionID = '2.1'">Geçersiz cbc:UBLVersionID elemanı değeri : '<sch:value-of select="cbc:UBLVersionID"/>'. cbc:UBLVersionID değeri '2.1' olmalıdır.</sch:assert>
        </sch:rule>
        
        
        <!-- Rule to validate CustomizationID -->
        <sch:rule abstract="true" id="CustomizationIDCheck">
            <sch:assert test="cbc:CustomizationID = 'TR1.2' or cbc:CustomizationID = 'TR1.2.1'">Geçersiz cbc:CustomizationID elemanı değeri : '<sch:value-of select="cbc:CustomizationID"/>' cbc:CustomizationID elemanı değeri 'TR1.2' veya 'TR1.2.1' olmalıdır.</sch:assert>
        </sch:rule>
        
        <!-- Rule to validate ProfileID -->
        <sch:rule abstract="true" id="ProfileIDCheck">
            <sch:assert test="not($type = 'efatura' or $type = '' or not($type)) or contains($ProfileIDType, concat(',',cbc:ProfileID,','))">Geçersiz cbc:ProfileID elemanı değeri : '<sch:value-of select="cbc:ProfileID"/>'. Geçerli cbc:ProfileID değerleri için ProfileIDType listesine bakınız.</sch:assert>
            <sch:assert test="not($type = 'earchive') or contains($ProfileIDTypeEarchive, concat(',',cbc:ProfileID,','))">Geçersiz cbc:ProfileID elemanı değeri : '<sch:value-of select="cbc:ProfileID"/>'. Geçerli cbc:ProfileID değerleri için ProfileIDTypeEarchive listesine bakınız.</sch:assert>
            <sch:assert test="not($type = 'goruntuleme') or contains($ProfileIDTypeGoruntuleme, concat(',',cbc:ProfileID,','))">Geçersiz cbc:ProfileID elemanı değeri : '<sch:value-of select="cbc:ProfileID"/>'. Geçerli cbc:ProfileID değerleri için ProfileIDTypeGoruntuleme listesine bakınız.</sch:assert>
            <sch:assert test="not(@xsi:schemaLocation) or contains(@xsi:schemaLocation,'UBL-Invoice-2.1.xsd')">Invoice alanın  xsi:schemaLocation özeliği 'UBL-Invoice-2.1.xsd' olmalıdır</sch:assert>
        </sch:rule> 
    </sch:pattern>
</sch:schema>

Source Code :

var fileName = Path.GetFileName(inputXml); 
var inputSch = "E:/aa/schematrontest/UBL-TR_Main_Schematron.xml";

string schxsltSvrlXsltResource = @"SchematronSchxsltSaxonCSValidator\schxslt_xslt1\iso_svrl_for_xslt1.xsl";
var schxsltResourceUri = UriUtils.GetLocationUri(schxsltSvrlXsltResource, Assembly.GetExecutingAssembly());

var resolver = new Resolver();

var settings = new XmlReaderSettings() { XmlResolver = resolver };

var processor = new Processor(true);
var xsltCompiler = processor.NewXsltCompiler();

using var schxsltReader = XmlReader.Create(schxsltResourceUri.AbsoluteUri, settings);


var transformer = xsltCompiler.Compile(schxsltReader).Load30();

var compiledSchematron = new XdmDestination();
compiledSchematron.BaseUri = new Uri(new FileInfo(inputSch).FullName);

using var schemaStream = File.OpenRead(inputSch);

transformer.Transform(schemaStream, compiledSchematron);

var xsltCompiler2 = processor.NewXsltCompiler();

var schematronValidator = xsltCompiler2.Compile(compiledSchematron.XdmNode).Load30();

var svrlResult = new DomDestination();

using var instanceStream = File.OpenRead(inputXml);
schematronValidator.Transform(instanceStream, new Uri(new FileInfo(inputXml).FullName), svrlResult);
List<ErrorModel> errors = new List<ErrorModel>();

var failedNodes = svrlResult.XmlDocument.GetElementsByTagName("svrl:failed-assert");
Share Improve this question edited Feb 12 at 21:41 Cemal Çelik asked Feb 12 at 21:11 Cemal ÇelikCemal Çelik 117 bronze badges 12
  • It is not sure what you are asking about, if you use some Schematron implementation you would load the main Schematron file and it should resolve the includes. Have you tried something that failed? Then tell us exactly what you tried and how it failed. – Martin Honnen Commented Feb 12 at 21:35
  • sorry for the confusion. I have tried to compile the main schematron file with "iso_svrl_for_xslt1.xsl" file gained from "github/Schematron/schematron". But compiled XSLT doesn't contains error messages which is stored in "File 2". Also, It has to fail with given xml file. But its not raising any errors. I am also adding code snippet. – Cemal Çelik Commented Feb 12 at 21:39
  • When i put main schematron into Oxygen XML Developer and run transformation, it transforms it well with messages also. I guess, in this case my problem is finding the xsl file to compile this schematron file. Just trying to address the issue actually. – Cemal Çelik Commented Feb 12 at 21:43
  • I don't know for sure but I would rather think that oXygen, if it uses the Schematron skeleton implementation, uses the 2.0 version. Anyway, it is hard to tell what fails without seeing all the details. And if these are some official schemas produced by some agency or business it might be better to ask them which Schematron version/xquery binding/implementation the expect them to work with. It wouldn't hurt to try whether Schxslt gives you the result you want. And of course keep in mind that the iso_svrl_for_xslt1.xsl file imports at least another one so it is important that you have all files – Martin Honnen Commented Feb 12 at 21:51
  • I have seen that iso_svrl_for_xslt1.xsl also imports iso_schematron_skeleton_for_xslt1.xsl. And i have it in my directory too. I have tried with Schxslt before and it requires "QueryBinding" parameter. Which version do i have to go for? Also, i can share details and what i have tried before on some apps like discord or something if it is okay for you. – Cemal Çelik Commented Feb 12 at 21:57
 |  Show 7 more comments

1 Answer 1

Reset to default 0

Using the Schematron "skeleton" implementation, you need to resolve the includes and the abstracts before converting it to an XSL file that can be used to execute validation on your XML document. That's what Oxygen XML is doing behind the scenes. See the instructions in https://github/Schematron/schematron/blob/master/trunk/schematron/code/readme.txt, quoted here:

  1. First, preprocess your Schematron schema with iso_dsdl_include.xsl. This is a macro processor to assemble the schema from various parts. If your schema is not in separate parts, you can skip this stage. This stage also generates error messages for some common XPath syntax problems.

  2. Second, preprocess the output from stage 1 with iso_abstract_expand.xsl. This is a macro processor to convert abstract patterns to real patterns. If your schema does not use abstract patterns, you can skip this stage.

  3. Third, compile the Schematron schema into an XSLT script. This will typically use iso_svrl_for_xslt1.xsl or iso_svrl_for_xslt2.xsl (which in turn invoke iso_schematron_skeleton_for_xslt1.xsl or iso_schematron_skeleton_for_saxon.xsl) However, other "meta-stylesheets" are also in common use; the principle of operation is the same. If your schema uses Schematron phases, supply these as command line/invocation parameters to this process.

  4. Fourth, run the script generated by stage 3 against the document being validated. If you are using the SVRL script, then the output of validation will be an XML document. If your schema uses Schematron parameters, supply these as command line/invocation parameters to this process.

发布评论

评论列表(0)

  1. 暂无评论