Search code examples
c#xmlxsltsaxonschematron

svrl:failed-assert location attribute normalize element names


Just made a validation of my xml file with schxslt compiled xsl file with SaxonCS. In the output of svrl report, failed location looks like this.

<svrl:failed-assert location="/Q{http://www.edefter.gov.tr}defter[1]/Q{http://www.xbrl.org/2003/instance}xbrl[1]/Q{http://www.xbrl.org/int/gl/cor/2006-10-25}accountingEntries[1]/Q{http://www.xbrl.org/int/gl/cor/2006-10-25}entryHeader[298]"
                       test="some-test">
      <svrl:text>some-message</svrl:text>
   </svrl:failed-assert>

Is there any possible way to retrieve xml elements with namespaces

<svrl:failed-assert location="/edefter:defter[1]/xbrli:xbrl[1]/gl-cor:accountingEntries[1]/gl-cor:entryHeader[298]"
                       test="some-test">
      <svrl:text>some-message</svrl:text>
   </svrl:failed-assert>

like this.

I tried to find a way to supply namespaces or import schemas but could not found a way.

Edit:

here is the namespaces of the svrl file before compile

<xsl:transform version="2.0"
           xmlns="http://www.w3.org/1999/XSL/TransformAlias"
           xmlns:sch="http://purl.oclc.org/dsdl/schematron"
           xmlns:error="https://doi.org/10.5281/zenodo.1495494#error"
           xmlns:schxslt="https://doi.org/10.5281/zenodo.1495494"
           xmlns:schxslt-api="https://doi.org/10.5281/zenodo.1495494#api"
           xmlns:svrl="http://purl.oclc.org/dsdl/svrl"
           xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

and here is the the namespaces of the compiled svrl report

<svrl:schematron-output xmlns:defterek="http://www.edefter.gov.tr/ek"
                        xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
                        xmlns:edefter="http://www.edefter.gov.tr"
                        xmlns:error="https://doi.org/10.5281/zenodo.1495494#error"
                        xmlns:gl-bus="http://www.xbrl.org/int/gl/bus/2006-10-25"
                        xmlns:gl-cor="http://www.xbrl.org/int/gl/cor/2006-10-25"
                        xmlns:gl-muc="http://www.xbrl.org/int/gl/muc/2006-10-25"
                        xmlns:gl-plt="http://www.xbrl.org/int/gl/plt/2010-04-16"
                        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
                        xmlns:sch="http://purl.oclc.org/dsdl/schematron"
                        xmlns:schxslt="https://doi.org/10.5281/zenodo.1495494"
                        xmlns:schxslt-api="https://doi.org/10.5281/zenodo.1495494#api"
                        xmlns:svrl="http://purl.oclc.org/dsdl/svrl"
                        xmlns:xades="http://uri.etsi.org/01903/v1.3.2#"
                        xmlns:xbrli="http://www.xbrl.org/2003/instance"
                        xmlns:xs="http://www.w3.org/2001/XMLSchema"
                        title="Yevmiye defteri dokumanlarını kontrol etmek için gerekli olan schematron kuralları">


 <svrl:ns-prefix-in-attribute-values prefix="gl-plt" uri="http://www.xbrl.org/int/gl/plt/2010-04-16"/>
   <svrl:ns-prefix-in-attribute-values prefix="gl-cor" uri="http://www.xbrl.org/int/gl/cor/2006-10-25"/>
   <svrl:ns-prefix-in-attribute-values prefix="gl-bus" uri="http://www.xbrl.org/int/gl/bus/2006-10-25"/>
   <svrl:ns-prefix-in-attribute-values prefix="gl-muc" uri="http://www.xbrl.org/int/gl/muc/2006-10-25"/>
   <svrl:ns-prefix-in-attribute-values prefix="xbrli" uri="http://www.xbrl.org/2003/instance"/>
   <svrl:ns-prefix-in-attribute-values prefix="ds" uri="http://www.w3.org/2000/09/xmldsig#"/>
   <svrl:ns-prefix-in-attribute-values prefix="xades" uri="http://uri.etsi.org/01903/v1.3.2#"/>
   <svrl:ns-prefix-in-attribute-values prefix="edefter" uri="http://www.edefter.gov.tr"/>
   <svrl:ns-prefix-in-attribute-values prefix="defterek" uri="http://www.edefter.gov.tr/ek"/>

Solution

  • In your Schematron you can provide your own schxslt:location function e.g.

    <schema xmlns="http://purl.oclc.org/dsdl/schematron" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:schxslt="https://doi.org/10.5281/zenodo.1495494" queryBinding="xslt3">
        <xsl:function name="schxslt:location" as="xs:string">
          <xsl:param name="node" as="node()"/>
          <xsl:sequence
            select="string-join($node/ancestor-or-self::*!node-name(), '/')"/>
        </xsl:function>
    

    That example is just to show you how to set up your own function, the function body is not an implementation of the path with positional predicates you want to generate but just generates a path with node-names. But you can adapt that function to your needs, the original Schxslt implementation that however tries to mimic the path function result is at https://github.com/schxslt/schxslt/blob/main/core/src/main/resources/xslt/2.0/compile/compile-2.0.xsl#L185. In that code instead of the Q{ namespace-uri and local name concatenation you seem to want to simply output the node-name() of a an element node plus the positional predicate.

    I have now tried to spell that out as

    <schema xmlns="http://purl.oclc.org/dsdl/schematron" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:schxslt="https://doi.org/10.5281/zenodo.1495494" queryBinding="xslt3">
        
        <xsl:function name="schxslt:location" as="xs:string">
          <xsl:param name="node" as="node()"/>
          <xsl:variable name="segments" as="xs:string*">
                <xsl:for-each select="($node/ancestor-or-self::node())">
                  <xsl:variable name="position">
                    <xsl:number level="single"/>
                  </xsl:variable>
                  <xsl:choose>
                    <xsl:when test=". instance of element()">
                      <xsl:value-of select="concat(node-name(), '[', $position, ']')"/>
                    </xsl:when>
                    <xsl:when test=". instance of attribute()">
                      <xsl:value-of select="concat('@', node-name())"/>
                    </xsl:when>
                    <xsl:when test=". instance of processing-instruction()">
                      <xsl:value-of select="concat('processing-instruction(&quot;', name(.), '&quot;)[', $position, ']')"/>
                    </xsl:when>
                    <xsl:when test=". instance of comment()">
                      <value-of select="concat('comment()[', $position, ']')"/>
                    </xsl:when>
                    <xsl:when test=". instance of text()">
                      <xsl:value-of select="concat('text()[', $position, ']')"/>
                    </xsl:when>
                    <xsl:otherwise/>
                  </xsl:choose>
                </xsl:for-each>
              </xsl:variable>
    
              <xsl:sequence select="concat('/', string-join($segments, '/'))"/>
    
        </xsl:function>
    

    I have put an online fiddle that runs SaxonJS at this link.