Schematron使用包含失败与不明确的规则匹配

时间:2018-03-08 20:30:34

标签: xslt schematron

我正在运行核心schematron XSLT(从http://schematron.com/front-page/the-schematron-skeleton-implementation/下载),违反了我的带有include语句的schematron规则。当试图通过中间XSL运行要测试的XML实例时,它会失败并且'模糊规则匹配'对于包含的schematron中存在的每个规则。

  

"描述:不明确的规则匹配       /申报:FilingMessage /归档:FilingConnectedDocument [1] / ECF:DocumentAugmentation [1] / ECF:DocumentRendition [1] / NC:附件[1] / NC:BinaryFormatText [1]       匹配两者       " {http://release.niem.gov/niem/niem-core/3.0/} BinaryFormatText"在文件的第192行:/ C:/ _ working / misc / schematron / schematron / trunk / schematron / code / temp.xsl       和       " {http://release.niem.gov/niem/niem-core/3.0/} BinaryFormatText"在文件的第175行:/ C:/ _ working / misc / schematron / schematron / trunk / schematron / code / temp.xsl   网址:http://www.w3.org/TR/xslt20/#err-XTRE0540"。

在检查生成的中间XSL时,包含的schematron文件中包含的规则似乎会被渲染到中间XSL中两次。检查XSL文件iso_schematron_skeleton_for_saxon.xsl,看起来iso:include使用模式节点和规则节点调用规则模板,这会导致数据重复。

我原以为github上的schematron XSLT是schematron规范的权威实现。是不是这种情况或任何人都可以对此发表评论,因为我不觉得我必须调整schematron XSLT才能使其正常工作?

Base Schematron

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://purl.oclc.org/dsdl/schematron" queryBinding="xslt2">
    <title>Test Schematron Illustrating Transform Bug</title>

    <ns prefix="x" uri="http://www.w3.org/TR/REC-html40"/>
    <ns prefix="filing" uri="https://docs.oasis-open.org/legalxml-courtfiling/ns/v5.0/filing"/>
    <ns prefix="nc" uri="http://release.niem.gov/niem/niem-core/3.0/"/>

    <include href="ExternalTestPattern.sch"/>

    <pattern id="ecf">
        <rule context="/filing:FilingMessage">
            <assert test="./nc:DocumentIdentification/nc:IdentificationID">DocumentID must be present.</assert>
        </rule>
    </pattern>

</schema>

ExternalTestPattern.sch Schematron

<?xml version="1.0" encoding="UTF-8"?>
<pattern xmlns="http://purl.oclc.org/dsdl/schematron" id="code-list-rules">
<!-- Required namespace declarations as indicated in this set of rules:
     <ns prefix="nc" uri="http://release.niem.gov/niem/niem-core/3.0/"/> -->

   <rule context="nc:BinaryFormatText">
      <assert test="( false() or ( contains('&#127;application/json&#127;application/msword&#127;application/pdf&#127;application/vnd.oasis.opendocument.text&#127;application/vnd.openxmlformats-officedocument.wordprocessingml.document&#127;application/xml&#127;',concat('&#127;',.,'&#127;')) ) ) ">Invalid binary format code value.</assert>
   </rule>
</pattern>

我忘了提到的另一件事是,如果我只是使用像Oxygen或XML伙伴这样的XML编辑器来使用我的schematron来验证XML实例,那么它可以正常工作。

当我使用Oxygen加载我的Test.sch以及iso_schematron_message_xslt2.xslt时,生成的XSLT如下所示。在中途,您将看到ExternalTestPattern.sch中定义的规则的模板(match =&#34; nc:BinaryFormatText&#34;)是重复的:

<xsl:stylesheet xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saxon="http://saxon.sf.net/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:schold="http://www.ascc.net/xml/schematron" xmlns:iso="http://purl.oclc.org/dsdl/schematron" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:x="http://www.w3.org/TR/REC-html40" xmlns:filing="https://docs.oasis-open.org/legalxml-courtfiling/ns/v5.0/filing" xmlns:nc="http://release.niem.gov/niem/niem-core/3.0/" version="2.0">
<!--Implementers: please note that overriding process-prolog or process-root is the preferred method for meta-stylesheets to use where possible. -->
<xsl:param name="archiveDirParameter"/>
   <xsl:param name="archiveNameParameter"/>
   <xsl:param name="fileNameParameter"/>
   <xsl:param name="fileDirParameter"/>
   <xsl:variable name="document-uri">
      <xsl:value-of select="document-uri(/)"/>
   </xsl:variable>

   <!--PHASES-->


<!--PROLOG-->
<xsl:output method="text"/>

   <!--XSD TYPES FOR XSLT2-->


<!--KEYS AND FUNCTIONS-->


<!--DEFAULT RULES-->


<!--MODE: SCHEMATRON-SELECT-FULL-PATH-->
<!--This mode can be used to generate an ugly though full XPath for locators-->
<xsl:template match="*" mode="schematron-select-full-path">
      <xsl:apply-templates select="." mode="schematron-get-full-path"/>
   </xsl:template>

   <!--MODE: SCHEMATRON-FULL-PATH-->
<!--This mode can be used to generate an ugly though full XPath for locators-->
<xsl:template match="*" mode="schematron-get-full-path">
      <xsl:apply-templates select="parent::*" mode="schematron-get-full-path"/>
      <xsl:text>/</xsl:text>
      <xsl:choose>
         <xsl:when test="namespace-uri()=''">
            <xsl:value-of select="name()"/>
         </xsl:when>
         <xsl:otherwise>
            <xsl:text>*:</xsl:text>
            <xsl:value-of select="local-name()"/>
            <xsl:text>[namespace-uri()='</xsl:text>
            <xsl:value-of select="namespace-uri()"/>
            <xsl:text>']</xsl:text>
         </xsl:otherwise>
      </xsl:choose>
      <xsl:variable name="preceding" select="count(preceding-sibling::*[local-name()=local-name(current()) and namespace-uri() = namespace-uri(current())])"/>
      <xsl:text>[</xsl:text>
      <xsl:value-of select="1+ $preceding"/>
      <xsl:text>]</xsl:text>
   </xsl:template>
   <xsl:template match="@*" mode="schematron-get-full-path">
      <xsl:apply-templates select="parent::*" mode="schematron-get-full-path"/>
      <xsl:text>/</xsl:text>
      <xsl:choose>
         <xsl:when test="namespace-uri()=''">@<xsl:value-of select="name()"/>
         </xsl:when>
         <xsl:otherwise>
            <xsl:text>@*[local-name()='</xsl:text>
            <xsl:value-of select="local-name()"/>
            <xsl:text>' and namespace-uri()='</xsl:text>
            <xsl:value-of select="namespace-uri()"/>
            <xsl:text>']</xsl:text>
         </xsl:otherwise>
      </xsl:choose>
   </xsl:template>

   <!--MODE: SCHEMATRON-FULL-PATH-2-->
<!--This mode can be used to generate prefixed XPath for humans-->
<xsl:template match="node() | @*" mode="schematron-get-full-path-2">
      <xsl:for-each select="ancestor-or-self::*">
         <xsl:text>/</xsl:text>
         <xsl:value-of select="name(.)"/>
         <xsl:if test="preceding-sibling::*[name(.)=name(current())]">
            <xsl:text>[</xsl:text>
            <xsl:value-of select="count(preceding-sibling::*[name(.)=name(current())])+1"/>
            <xsl:text>]</xsl:text>
         </xsl:if>
      </xsl:for-each>
      <xsl:if test="not(self::*)">
         <xsl:text/>/@<xsl:value-of select="name(.)"/>
      </xsl:if>
   </xsl:template>
   <!--MODE: SCHEMATRON-FULL-PATH-3-->
<!--This mode can be used to generate prefixed XPath for humans 
    (Top-level element has index)-->
<xsl:template match="node() | @*" mode="schematron-get-full-path-3">
      <xsl:for-each select="ancestor-or-self::*">
         <xsl:text>/</xsl:text>
         <xsl:value-of select="name(.)"/>
         <xsl:if test="parent::*">
            <xsl:text>[</xsl:text>
            <xsl:value-of select="count(preceding-sibling::*[name(.)=name(current())])+1"/>
            <xsl:text>]</xsl:text>
         </xsl:if>
      </xsl:for-each>
      <xsl:if test="not(self::*)">
         <xsl:text/>/@<xsl:value-of select="name(.)"/>
      </xsl:if>
   </xsl:template>

   <!--MODE: GENERATE-ID-FROM-PATH -->
<xsl:template match="/" mode="generate-id-from-path"/>
   <xsl:template match="text()" mode="generate-id-from-path">
      <xsl:apply-templates select="parent::*" mode="generate-id-from-path"/>
      <xsl:value-of select="concat('.text-', 1+count(preceding-sibling::text()), '-')"/>
   </xsl:template>
   <xsl:template match="comment()" mode="generate-id-from-path">
      <xsl:apply-templates select="parent::*" mode="generate-id-from-path"/>
      <xsl:value-of select="concat('.comment-', 1+count(preceding-sibling::comment()), '-')"/>
   </xsl:template>
   <xsl:template match="processing-instruction()" mode="generate-id-from-path">
      <xsl:apply-templates select="parent::*" mode="generate-id-from-path"/>
      <xsl:value-of select="concat('.processing-instruction-', 1+count(preceding-sibling::processing-instruction()), '-')"/>
   </xsl:template>
   <xsl:template match="@*" mode="generate-id-from-path">
      <xsl:apply-templates select="parent::*" mode="generate-id-from-path"/>
      <xsl:value-of select="concat('.@', name())"/>
   </xsl:template>
   <xsl:template match="*" mode="generate-id-from-path" priority="-0.5">
      <xsl:apply-templates select="parent::*" mode="generate-id-from-path"/>
      <xsl:text>.</xsl:text>
      <xsl:value-of select="concat('.',name(),'-',1+count(preceding-sibling::*[name()=name(current())]),'-')"/>
   </xsl:template>

   <!--MODE: GENERATE-ID-2 -->
<xsl:template match="/" mode="generate-id-2">U</xsl:template>
   <xsl:template match="*" mode="generate-id-2" priority="2">
      <xsl:text>U</xsl:text>
      <xsl:number level="multiple" count="*"/>
   </xsl:template>
   <xsl:template match="node()" mode="generate-id-2">
      <xsl:text>U.</xsl:text>
      <xsl:number level="multiple" count="*"/>
      <xsl:text>n</xsl:text>
      <xsl:number count="node()"/>
   </xsl:template>
   <xsl:template match="@*" mode="generate-id-2">
      <xsl:text>U.</xsl:text>
      <xsl:number level="multiple" count="*"/>
      <xsl:text>_</xsl:text>
      <xsl:value-of select="string-length(local-name(.))"/>
      <xsl:text>_</xsl:text>
      <xsl:value-of select="translate(name(),':','.')"/>
   </xsl:template>
   <!--Strip characters--><xsl:template match="text()" priority="-1"/>

   <!--SCHEMA SETUP-->
<xsl:template match="/">
      <xsl:apply-templates select="/" mode="M0"/>
      <xsl:apply-templates select="/" mode="M5"/>
   </xsl:template>

   <!--SCHEMATRON PATTERNS-->


<!--PATTERN code-list-rules-->


    <!--RULE -->
<xsl:template match="nc:BinaryFormatText" priority="1000" mode="M0">

        <!--ASSERT -->
<xsl:choose>
         <xsl:when test="( false() or ( contains('&#127;application/json&#127;application/msword&#127;application/pdf&#127;application/vnd.oasis.opendocument.text&#127;application/vnd.openxmlformats-officedocument.wordprocessingml.document&#127;application/xml&#127;',concat('&#127;',.,'&#127;')) ) ) "/>
         <xsl:otherwise>
            <xsl:message>Invalid binary format code value. (( false() or ( contains('&#127;application/json&#127;application/msword&#127;application/pdf&#127;application/vnd.oasis.opendocument.text&#127;application/vnd.openxmlformats-officedocument.wordprocessingml.document&#127;application/xml&#127;',concat('&#127;',.,'&#127;')) ) ))</xsl:message>
         </xsl:otherwise>
      </xsl:choose>
      <xsl:apply-templates select="*|comment()|processing-instruction()" mode="M0"/>
   </xsl:template>
   <xsl:template match="text()" priority="-1" mode="M0"/>
   <xsl:template match="@*|node()" priority="-2" mode="M0">
      <xsl:apply-templates select="*|comment()|processing-instruction()" mode="M0"/>
   </xsl:template>

      <!--RULE -->
<xsl:template match="nc:BinaryFormatText" priority="1000" mode="M0">

        <!--ASSERT -->
<xsl:choose>
         <xsl:when test="( false() or ( contains('&#127;application/json&#127;application/msword&#127;application/pdf&#127;application/vnd.oasis.opendocument.text&#127;application/vnd.openxmlformats-officedocument.wordprocessingml.document&#127;application/xml&#127;',concat('&#127;',.,'&#127;')) ) ) "/>
         <xsl:otherwise>
            <xsl:message>Invalid binary format code value. (( false() or ( contains('&#127;application/json&#127;application/msword&#127;application/pdf&#127;application/vnd.oasis.opendocument.text&#127;application/vnd.openxmlformats-officedocument.wordprocessingml.document&#127;application/xml&#127;',concat('&#127;',.,'&#127;')) ) ))</xsl:message>
         </xsl:otherwise>
      </xsl:choose>
      <xsl:apply-templates select="*|comment()|processing-instruction()" mode="M0"/>
   </xsl:template>

   <!--PATTERN ecf-->


    <!--RULE -->
<xsl:template match="/filing:FilingMessage" priority="1000" mode="M5">

        <!--ASSERT -->
    <xsl:choose>
         <xsl:when test="./nc:DocumentIdentification/nc:IdentificationID"/>
         <xsl:otherwise>
            <xsl:message>DocumentID must be present. (./nc:DocumentIdentification/nc:IdentificationID)</xsl:message>
         </xsl:otherwise>
      </xsl:choose>
      <xsl:apply-templates select="*|comment()|processing-instruction()" mode="M5"/>
   </xsl:template>
   <xsl:template match="text()" priority="-1" mode="M5"/>
   <xsl:template match="@*|node()" priority="-2" mode="M5">
      <xsl:apply-templates select="*|comment()|processing-instruction()" mode="M5"/>
   </xsl:template>
</xsl:stylesheet>

任何启示都会非常有用。 感谢

1 个答案:

答案 0 :(得分:0)

确保通过应用readme中概述的转换序列将Schematron编译为XSLT,并使用先前XSLT转换的输出作为下一步的输入:

  

1)首先,使用iso_dsdl_include.xsl预处理Schematron架构。   这是一个宏处理器,用于从各个部分组装模式。   如果您的架构不在单独的部分中,则可以跳过此阶段。这个   stage还会为某些常见的XPath语法生成错误消息   问题。

     

2)其次,预处理阶段 1的输出   iso_abstract_expand.xsl。这是一个要转换的宏处理器   抽象模式到真实模式。如果您的架构不使用   抽象模式,你可以跳过这个阶段。

     

3)第三,将Schematron模式编译为XSLT脚本。这个   通常会使用iso_svrl_for_xslt1.xsliso_svrl_for_xslt2.xsl   (反过来调用iso_schematron_skeleton_for_xslt1.xsl或   iso_schematron_skeleton_for_saxon.xsl)但是,其他   &#34;元样式表&#34;也是常用的;经营原则   是一样的。如果您的架构使用Schematron阶段,请将其作为   命令行/调用此过程的参数。

     

4)第四,针对文档运行阶段3生成的脚本   正在验证。如果您使用的是SVRL脚本,那么输出   验证将是一个XML文档。如果您的架构使用Schematron   参数,将这些作为命令行/调用参数提供给此参数   过程

此外,请确保您正在应用iso_svrl_for_xslt2.xsl(导入iso_schematron_skeleton_for_saxon.xsl)并且未直接使用iso_schematron_skeleton_for_saxon.xsl