xml - 没有重复的可选元素的 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 个元素。
解决方案
很简单
<!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)?
(我没有测试它。)
推荐阅读
- python - 找出目标函数中每一项的值
- sttwitterapi - 如何使用 Twitter API 对推文进行分类
- c++ - Qml没有收到基类成员变量的更新值
- node.js - Socket.io 不适用于 nginx 和 https
- batch-file - 获取所有级别的所有子文件夹名称以及它们的文件名,然后使用它们;忽略批处理文件的名称
- android - 访问 android wear 数据层时出错
- c# - 异步/等待:冒泡异常?
- azure - Azure 服务总线队列 - 已处理的消息与已处理的活动消息
- react-native - 如何在另一个函数中清除 setTimer
- php - 如何从 PHP 中的 API 数组中获取单个数据?