首页 > 解决方案 > 没有重复的可选元素的 DTD

问题描述

我期待 DTD,其中 xml 文件中的每个元素都是可选的,但如果有多个,则必须按正确的顺序排列。并且必须至少有一项没有重复项。

在这种情况下,至少没有一个

<!DOCTYPE mnop [
<!ELEMENT abcd      (#PCDATA)>
<!ELEMENT efgh      (#PCDATA)>
<!ELEMENT ijkl      (#PCDATA)>
<!ELEMENT mnop      (abcd?, efgh?, ijkl?)>
]> 
<mnop> 
</mnop> 

在这种情况下可能有重复

<!DOCTYPE mnop [
<!ELEMENT abcd      (#PCDATA)>
<!ELEMENT efgh      (#PCDATA)>
<!ELEMENT ijkl      (#PCDATA)>
<!ELEMENT mnop      (abcd?, efgh?, ijkl?)+>
]> 
<mnop> 
    <abcd>AAAAAAA</abcd>
    <abcd>AAAAAAA</abcd>
</mnop> 

在这种情况下(我不知道为什么!)但在 xml 中的顺序可能不正确(DTD 有效)

<!DOCTYPE mnop [
<!ELEMENT abcd      (#PCDATA)>
<!ELEMENT efgh      (#PCDATA)>
<!ELEMENT ijkl      (#PCDATA)>
<!ELEMENT mnop      ((abcd, efgh?, ijkl?) | (abcd?, efgh, ijkl?) | (abcd?, efgh?, ijkl))>
]> 
<mnop> 
    <efgh>EEEEE</efgh>
    <abcd>AAAAAAA</abcd>
    <ijkl>AAAAAAA</ijkl>
</mnop> 

例如正确的文件:

<mnop> 
    <abcd>AAAAAAA</abcd>
</mnop> 
<mnop> 
    <efgh>EEEEE</efgh>
    <ijkl>AAAAAAA</ijkl>
</mnop> 
<mnop> 
    <ijkl>AAAAAAA</ijkl>
</mnop> 

并且每个案例都按正确的顺序排列,没有重复。在我的示例中,我说的是 3 个元素,但在我的示例中,我有 12 个元素。

标签: xmldtd

解决方案


很简单

<!ELEMENT mnop      ((a, ((b, c?) | c)?) | (b, c?) | c)? >
                    -----------------------------------^ all optional
                     (----------------)    (-----)  (-) starting with a/b/c
                     recursive

请注意,这需要使用 java 或 python 等编写的生成器工具。当然对于 12 个元素。

从外到内的可选性:(x, (...)?)

替代品甚至会更好。


爪哇:

void p(StringBuilder sb, List<String> tags) {
    if (tags.isEmpty()) {
        throw new IllegalStateException();
    }
    int n = tags.size();
    if (n == 1) {
        sb.append(tags.get(0));
        return;
    }
    sb.append('(');
    for (int starti = 0; starti < n; ++starti) {
        if (starti != 0) {
            sb.append(" | ");
        }
        if (n - starti > 1) {
            sb.append('(');
        }
        sb.append(tags.get(starti));
        if (n - starti > 1) {
            sb.append(", ");
            p(sb, tags.subList(starti + 1, n));
            sb.append("?)");
        }
    }
    sb.append(')');
}

    StringBuilder all = new StringBuilder();
    p(all, Arrays.asList("a", "b", "c"));
    all.append('?');
    System.out.println(all);

((a, ((b, c?) | c)?) | (b, c?) | c)?

(我没有测试它。)


推荐阅读