1

为什么这是不确定的以及如何解决它?

 <xs:element name="activeyears">
        <xs:complexType>
            <xs:sequence minOccurs="0" maxOccurs="1">
                <xs:sequence minOccurs="0" maxOccurs="unbounded">
                    <xs:element ref="from" minOccurs="1" maxOccurs="1"/>
                    <xs:element ref="till" minOccurs="1" maxOccurs="1"/>
                </xs:sequence>
                <xs:element ref="from" minOccurs="0" maxOccurs="1"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

这应该意味着它<activeyears>要么是空的,要么包含以任何<from><till>一个开头<from>但可以以任何一个结尾的序列。

4

2 回答 2

7

当有两个以相同元素开头的分支时,模式是不确定的 - 因此,如果不向前看该元素,就无法判断要采用哪个分支。一个简单的例子是ab|ac- 当你看到一个 时a,你不知道该选择哪个分支。对于循环,“分支”是重复循环还是继续循环。这方面的一个例子是a*a- 一旦你进入循环,并且你阅读了一个a,你不知道是重复循环还是继续。

查看您的示例模式,想象它刚刚解析了 a <till>,现在它需要解析 a <from>。您可以使用<from><till>循环final解析它<from>。您无法仅通过查看来判断使用哪个分支<from>。你只能通过进一步的展望来判断。


坏消息:我认为您的示例模式非常罕见,无法确定地表达!

以下是您要接受的 XML 文档(我对每个元素使用一个字母,其中a=<from>...</from>b= <to>...</to>

*empty*
a
ab
aba
abab
ababa
ababab
...

...你明白了。问题是任何字母都可以是序列中的最后一个字母,可以是循环的一部分。没有办法知道它会是哪一个,除非提前看下面的信。由于“确定性”意味着您不提前(根据定义)执行此操作,因此您想要的语言无法确定性地表达。

为了简化您的架构,它尝试了一种类似于(ab)*a?- 但两个分支都以a. 另一种方法是a(ba)*b?- 现在两个分支都以b. 我们赢不了!

从技术上讲,模式将接受的所有文档的集合称为该模式的语言。如果不存在可以表达一种语言的确定性模式,则该语言称为“单歧义”。

有关理论讨论,请参阅 Bruggemann-Klein 的系列论文(例如Deterministic Regular LanguagesOne-Unambiguous Regular Languages)。她包括一个明确的语言的正式测试。

于 2009-12-24T01:51:43.297 回答
0

这是对代码的简单编辑;我没试过:

 <xs:element name="activeyears">
        <xs:complexType>
            <xs:sequence minOccurs="0" maxOccurs="1">
                <xs:element ref="from" minOccurs="1" maxOccurs="1"/>
                <xs:sequence minOccurs="0" maxOccurs="unbounded">
                    <xs:element ref="till" minOccurs="1" maxOccurs="1"/>
                    <xs:element ref="from" minOccurs="0" maxOccurs="1"/>
                </xs:sequence>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

一些背景知识:XML 模式是一种非常简单的语法,模式处理器是一个解析器,它试图将这种语法的规则应用于输入文件。然而,与传统编译器使用的解析器不同,XML 模式没有前瞻。因此,您不能有两个共享相同初始标记集(元素名称)的规则。

因此,我所做的具体更改:

  • 我没有改变你的外表sequence;它控制“空的或有特定内容”的要求。
  • 如果有内容,必须以“from”开头;所以我将其element设为序列中的第一个,并带有明确的出现次数
  • 由于我使用“from”作为显式元素,因此我不得不颠倒子序列的顺序。
  • 除非您要指定每个“直到”必须后跟一个“从”,否则您需要放宽minOccurs子序列中的 the 。
  • 子序列还处理单个从/到的情况——正如评论者所指出的,我的第二次编辑minOccurs='0'允许两个“直到”的终止序列。
于 2009-12-23T14:20:37.417 回答