XML Schema 1.1断言:如何捕获动态类型错误?

时间:2015-06-21 12:00:28

标签: xml saxon xsd-validation assertion xsd-1.1

我目前正在努力解决XML Schema 1.1中的断言。 XML Schema 1.1建议states如果在执行期间发生错误则违反了断言。这种行为似乎是合理的,但在尝试理解评估结果时可能会引起一些混淆。让我解释一下:

以下示例XSD解释定义了两个元素:str和dec。元素str必须具有值“A”或“B”。元素dec必须是数字。此外,如果str具有值“A”,则dec必须为正。我尝试使用断言来定义最后一个属性:

<?xml version="1.0" encoding="utf-8"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="data">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="str">
          <xs:simpleType>
            <xs:restriction base="xs:string">
              <xs:enumeration value="A"/>
              <xs:enumeration value="B"/>
            </xs:restriction>
          </xs:simpleType>
        </xs:element>
        <xs:element name="dec" type="xs:decimal"/>
      </xs:sequence>
      <xs:assert test="str != 'A' or dec gt 0"/>
    </xs:complexType>
  </xs:element>
</xs:schema>

以下XML文件无效,因为元素str的值为“X”,这是不允许的。

<?xml version="1.0" encoding="utf-8" ?>
<data>
  <str>X</str>
  <dec>5</dec>
</data>

当我现在使用Saxon 9.6.0.6验证XML文件时,我得到以下输出:

Validation error on line 3 column 16 of test.xml:
  XSD: The content "X" of element <str> does not match the required simple type. Value "X"
  contravenes the enumeration facet "A, B" of the type of element str
  Validating /data[1]/str[1]
  See http://www.w3.org/TR/xmlschema11-2/#cvc-datatype-valid clause 1
Warning: on line 1 
  Internal error: value doesn't match its type annotation. Value "X" contravenes the
  enumeration facet "A, B" of the type of element str
Validation error at data on line 5 column 8 of test.xml:
  XSD: Element data does not satisfy assertion str != 'A' or dec gt 0
  Validating /data[1]

正如您所看到的,我只针对一个问题报告了两个错误(元素str的非法值)。我发现这种行为很混乱,因为它使得更难以看到真正的问题(错误的值,而不是失败的断言)。

是否有任何方法可以“捕获”断言中的类型错误,以便断言在此示例中不会失败?

1 个答案:

答案 0 :(得分:2)

有趣。与大多数验证器一样,Saxon将通过在单次运行中捕获尽可能多的验证错误来尝试提供帮助。但这只有在错误彼此独立时才有用。测试已知无效的值的断言并不是非常有用:但当然,断言是盲目地执行的#34;由一个XPath处理器,它不知道已经报告了哪些错误。

Saxon报告了一个内部错误&#34;这是一条线索,它不应该以这种方式工作。我将在此处记录一个错误,看看我们能做些什么。

断言是相当奇怪的,因为它们对已经半验证的数据进行操作:这使得关于它们是对有序值还是无类型值进行操作的规则相当复杂。在这种情况下,我怀疑在更具防御性的情况下编写你的断言可能会对事情有所帮助。但是如果str具有值&#34; A&#34;&#39;那么代码可能是有意义的。更直接的是&#34; if(str =&#39; A&#39;)然后dec> 0,否则为true()&#34;。