Saxon 9EE 为单个元素抛出多个错误

Saxon9EE throws mutliple error for single element

我正在使用 Saxon9EE.jar 来验证 XML。

我有一个简单类型的断言,用于我的元素来验证年份中的日期是否在 1900 年之后,这非常有效。但是对于所有使用元素名称进行验证的断言,它都会出错。

我的XSD:

<?xml version="1.0" encoding="ISO-8859-1"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saxon="http://saxon.sf.net/">
    <xs:element name="Root">
        <xs:annotation>
            <xs:appinfo>
                <XSDVersion>1</XSDVersion>
                <fieldSeparator>|</fieldSeparator>
                <recordSeparator>\n</recordSeparator>
                <allowDiscontinousOrder>true</allowDiscontinousOrder>
                <allowIgnoreCase>false</allowIgnoreCase>
                <allowLessFields>true</allowLessFields>
                <removeInvalidChar>false</removeInvalidChar>
                <enclosedChar/>
            </xs:appinfo>
        </xs:annotation>
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Record" minOccurs="1" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="LoanOpenDate" nillable="false" minOccurs="0" maxOccurs="1">
                                <xs:annotation>
                                    <xs:appinfo>
                                        <format>AAAAAAA</format>
                                        <originalName><![CDATA[LoanOpenDate]]></originalName>
                                        <parent> </parent>
                                    </xs:appinfo>
                                </xs:annotation>
                                <xs:simpleType>
                                    <xs:restriction base="CMGDateFormat">
                                        <xs:assertion test="if(string-length($value) != 0) then true() else false()" saxon:message="LoanOpenDate, should have a valid input"/>
                                        <xs:assertion test="if(string-length($value) != 0 and string-length($value) = 10 ) then (xs:integer(substring($value,7,4)) > 1900) else true()" saxon:message="LoanOpenDate, should have a valid input, Year should be after 1900"/>

                                    </xs:restriction>
                                </xs:simpleType>
                            </xs:element>



                            <xs:element name="LoanClosedDate" minOccurs="0" maxOccurs="1">
                                <xs:annotation>
                                    <xs:appinfo>
                                        <format>AAAAAAA</format>
                                        <originalName><![CDATA[LoanClosedDate]]></originalName>
                                        <parent> </parent>
                                    </xs:appinfo>
                                </xs:annotation>
                                <xs:simpleType>
                                    <xs:restriction base="CMGDateFormat">
                                        <xs:assertion test="if(string-length($value) != 0 and string-length($value) = 10 ) then (xs:integer(substring($value,7,4)) > 1900) else true()" saxon:message="LoanOpenDate, should have a valid input, Year should be after 1900"/>
                                    </xs:restriction>
                                </xs:simpleType>
                            </xs:element>


                        </xs:sequence>
                        <xs:attribute name="recordNumber" type="xs:string" use="required"/>
                        <xs:assert test="if(xs:integer(substring(LoanClosedDate,7,4)) > 1900 and  xs:integer(substring(LoanOpenDate,7,4)) > 1900 and  string-length(LoanClosedDate) != 0) then string-length(LoanOpenDate) != 0 else true()" saxon:message="LoanOpenDate, cannot be null if a LoanClosedDate exists"/>
                        <xs:assert test="if(string-length(LoanOpenDate) != 0  and string-length(LoanClosedDate) != 0 and xs:integer(substring(LoanClosedDate,7,4)) > 1900 and  xs:integer(substring(LoanOpenDate,7,4)) > 1900 and xs:long(concat(substring(LoanClosedDate,7,4),substring(LoanClosedDate,1,2),substring(LoanClosedDate,4,2))) != xs:long(concat(substring(LoanOpenDate,7,4),substring(LoanOpenDate1,2), substring(LoanOpenDate,4,2))))
                                                then 
                                                (xs:date(concat(substring( LoanOpenDate,7 ,4 ) ,'-',substring(LoanOpenDate,1,2 ),'-', substring(LoanOpenDate,4,2))) &lt; (xs:date(concat(substring(LoanClosedDate,7,4),'-',substring(LoanClosedDate,1,2),'-',substring(LoanClosedDate,4,2))))) 
                                                else true()" saxon:message="LoanOpenDate, cannot be a date after LoanClosedDate, cannot be null if a LoanClosedDate exists, cannot be equal to LoanClosedDate"/>


                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:simpleType name="CMGDateFormat">
        <xs:annotation>
            <xs:documentation>This type is used for dates requested in mm/dd/yyyy format.</xs:documentation>
        </xs:annotation>
        <xs:restriction base="xs:string">
            <xs:pattern value="((((0[1-9]|1[012])[/](0[1-9]|1[0-9]|2[0-8]))|((0[13578]|1[02])[/](29|30|31))|((0[4,6,9]|11)[/](29|30)))[/](19|[2-9][0-9])\d\d)|(02[/]29[/](19|[2-9][0-9])(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96))|\s*"/>
        </xs:restriction>
    </xs:simpleType>
</xs:schema>

这是我要验证的 XML:

<?xml version="1.0" encoding="ISO-8859-1"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Record  recordNumber = "1" >

 <LoanOpenDate><![CDATA[08/06/2008]]></LoanOpenDate>

 <LoanClosedDate><![CDATA[10/10/1900]]></LoanClosedDate>
 </Record>

 </Root>

我希望撒克逊人不应该为记录级别的断言抛出错误。应该在元素级别生成一个错误。但事实并非如此

<?xml version="1.0" encoding="UTF-8"?>
    <validation-report xmlns="http://saxon.sf.net/ns/validation"
                       system-id="file:/K:/redir/My%20Documents/MyJabberFiles/gsa4970@cmutual.com/SaxonStandalone/Loantest.xml">
       <error line="7"
              column="18"
              path="/Q{}Root[1]/Q{}Record[1]/Q{}LoanClosedDate[1]"
              xsd-part="2"
              constraint="cvc-datatype-valid.1">The content "10/10/1900" of element &lt;LoanClosedDate&gt; does not match the required simple type. Value "10/10/1900" contravenes the assertion facet "if(string-length($value) != 0 ..." of the type of element LoanClosedDate. LoanOpenDate, should have a valid input, Year should be after 1900</error>
       <error line="3"
              column="30"
              path="/Q{}Root[1]/Q{}Record[1]"
              xsd-part="1"
              constraint="sec-cvc-assertion.0">Element Record does not satisfy assertion. LoanOpenDate, cannot be a date after LoanClosedDate, cannot be null if a LoanClosedDate exists, cannot be equal to LoanClosedDate</error>
       <error line="3"
              column="30"
              path="/Q{}Root[1]/Q{}Record[1]"
              xsd-part="1"
              constraint="sec-cvc-assertion.0">Element Record does not satisfy assertion. LoanOpenDate, cannot be null if a LoanClosedDate exists</error>
       <meta-data>
          <validator name="SAXON-EE" version="9.8.0.4"/>
          <results errors="3" warnings="0"/>
          <schema file="Loan1.xsd" xsd-version="1.1"/>
          <run at="2018-01-30T10:50:42.45-06:00"/>
       </meta-data>
    </validation-report>

你能告诉我是否有解决方法或者撒克逊语是否存在错误。

就像编译 Java 这样的语言一样,要报告多少错误是一个艰难的决定。您不想在第一个错误之后停止报告,因为人们希望在再次尝试验证之前更正所有错误,但您不想仅仅因为规则中有多个不同的方式就以几种不同的方式报告相同的错误违反了语言规范(或在本例中为模式)。

当然可以说"don't evaluate assertions on a parent element if any of the child elements has been found to be invalid"。但是,如果断言由于与子元素中的错误无关的原因而为假,则您的实例文档中将出现两个错误,并且只会报告其中一个。

理想的解决方案可能是 "don't evaluate assertions on a parent element if it needs access to children that have been found to be invalid"。但这真的很难实现。

在这种情况下,您的实例文档中有一段无效数据导致架构中的三个规则失败,而 Saxon 报告了所有三个规则。恐怕这就是它的工作方式。

有些人喜欢分多个阶段组织验证,因此您首先检查结构规则,然后再检查 "business" 规则。这涉及多个模式的管道。这是可能的,但需要大量工作。

您也可以尝试变得聪明并使用 XSLT 过滤验证报告,查看与各个错误关联的路径并将它们分组。我们引入 XML 验证报告的主要原因是允许这种定制。