我使用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))) < (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 <LoanClosedDate> 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>
如果有解决方法或是否可能是撒克逊人的错误,您能否告诉我。
答案 0 :(得分:0)
就像编写像Java这样的语言一样,要报告多少错误是一个艰难的决定。您不希望在第一个之后停止报告,因为人们希望在再次尝试验证之前纠正所有错误,但您不希望以几种不同的方式报告相同的错误,因为违反了语言规范(或者在这种情况下,模式)。
如果发现任何子元素无效,那么肯定可以说“不要在父元素上评估断言”。但是,如果由于与子元素中的错误无关的原因而断言是错误的,则实例文档中会出现两个错误,并且只会报告其中一个错误。
理想的解决方案可能是“如果父元素需要访问已被发现无效的子元素,则不要评估父元素的断言”。但这真的很难实现。
在这种情况下,实例文档中有一条无效数据会导致架构中的三条规则失败,而Saxon会报告这三条规则。我担心这只是它的工作方式。
有些人喜欢在多个阶段组织验证,因此您首先检查结构规则,然后检查“业务”规则。这涉及多个模式的管道。这是可能的,但这是很多工作。
您还可以尝试智能并使用XSLT过滤验证报告,查看与各个错误相关联的路径并对其进行分组。我们引入XML验证报告的主要原因是允许这种剪裁。