如何强制 XML 文件中存在某个元素?
How to enforce the presence of a certain element in the XML file?
我想强制 <a-special/>
元素在我的文档中 至少出现一次 。对于这样的语法,这样的文档将是有效的(因为 <a-special/>
出现):
<my-container>
text <a id="1" type="B"/> text text <a-special/>
text text <a id="5" type="B"/> text <a id="24" type="B"/>
text <a id="5" type="C"/>
</my-container>
而这将被视为无效(因为 <a-special/>
不会 发生):
<my-container>
<a id="1" type="B"/> text text
text <a id="5" type="B"/> text <a id="24" type="B"/>
text <a id="5" type="C"/>
</my-container>
我已经用下面的语法尝试了不同的东西,但我似乎无法让它按照我需要的方式工作。
<!ELEMENT my-container ( #PCDATA | a | a-special | b )*>
<!ELEMENT a-special EMPTY>
<!ELEMENT a EMPTY>
<!ATTLIST a id CDATA #REQUIRED>
<!ATTLIST a type CDATA #REQUIRED>
<!ELEMENT b EMPTY>
<!ATTLIST b id CDATA #REQUIRED>
<!ATTLIST a type CDATA #REQUIRED>
我知道这是错误的,但我在想这样的事情:
<!ELEMENT my-container
a-special+ ( #PCDATA | a | b | a-special )*
| ( #PCDATA | a | b )+ a-special+ ( #PCDATA | a | b | a-special )*
>
第一部分将解析任何以 a-special
开头的内容,第二部分将解析任何需要 a-special
介于两者之间或末尾的内容。这可以用 DTD 语法来完成吗?
您要强制执行的约束不能用 XML DTD 声明。
如果您的最外层元素真的只是一系列字符数据和空子元素,您提到的类似内容模型的表达式将(在提供缺少的逗号之后)准确地捕获约束:
((#PCDATA | a | b)*, a-special, (#PCDATA | a | b | a-special)*)
这在 SGML 中是合法的(我认为是这样,但我还没有检查过)。但是 XML DTD 中混合内容唯一允许的形式是
(#PCDATA)
(#PCDATA | x | y | ... |z)*
(#PCDATA)*
所描述的约束可以在 XSD 或 Relax NG 中表达。
如果允许文档元素以外的任何元素为非空,则约束不能用我所知道的任何模式语言的内容模型表达:内容模型作为一种上下文无关语法,并且文档中 某处 有一个 a-special
元素的要求需要一种上下文敏感的形式。
正如@potame 在评论中观察到的那样,Schematron 可以制定约束; XSD 1.1 中的断言也可以附加到文档元素的声明中。
一种可能的解决方法:以不同的方式标记元素的特殊性,例如通过指向文档中的某些 a
个元素:
<!ELEMENT my-container (#PCDATA|a|b)* >
<!ATTLIST my-container specials IDREFS #REQUIRED >
<!ELEMENT a EMPTY >
<!ATTLIST a id ID #IMPLIED>
<!ELEMENT b EMPTY>
由于my-container/@specials
是必需的,它必须至少命名文档中的一个元素。由于为其定义 ID 的唯一元素类型是 a
,因此由 specials
命名的元素保证是 a
个元素。
如果您使用 XSD 而不是 DTD,您可以只在元素中使用 minOccurs 属性。
我想强制 <a-special/>
元素在我的文档中 至少出现一次 。对于这样的语法,这样的文档将是有效的(因为 <a-special/>
出现):
<my-container>
text <a id="1" type="B"/> text text <a-special/>
text text <a id="5" type="B"/> text <a id="24" type="B"/>
text <a id="5" type="C"/>
</my-container>
而这将被视为无效(因为 <a-special/>
不会 发生):
<my-container>
<a id="1" type="B"/> text text
text <a id="5" type="B"/> text <a id="24" type="B"/>
text <a id="5" type="C"/>
</my-container>
我已经用下面的语法尝试了不同的东西,但我似乎无法让它按照我需要的方式工作。
<!ELEMENT my-container ( #PCDATA | a | a-special | b )*>
<!ELEMENT a-special EMPTY>
<!ELEMENT a EMPTY>
<!ATTLIST a id CDATA #REQUIRED>
<!ATTLIST a type CDATA #REQUIRED>
<!ELEMENT b EMPTY>
<!ATTLIST b id CDATA #REQUIRED>
<!ATTLIST a type CDATA #REQUIRED>
我知道这是错误的,但我在想这样的事情:
<!ELEMENT my-container
a-special+ ( #PCDATA | a | b | a-special )*
| ( #PCDATA | a | b )+ a-special+ ( #PCDATA | a | b | a-special )*
>
第一部分将解析任何以 a-special
开头的内容,第二部分将解析任何需要 a-special
介于两者之间或末尾的内容。这可以用 DTD 语法来完成吗?
您要强制执行的约束不能用 XML DTD 声明。
如果您的最外层元素真的只是一系列字符数据和空子元素,您提到的类似内容模型的表达式将(在提供缺少的逗号之后)准确地捕获约束:
((#PCDATA | a | b)*, a-special, (#PCDATA | a | b | a-special)*)
这在 SGML 中是合法的(我认为是这样,但我还没有检查过)。但是 XML DTD 中混合内容唯一允许的形式是
(#PCDATA)
(#PCDATA | x | y | ... |z)*
(#PCDATA)*
所描述的约束可以在 XSD 或 Relax NG 中表达。
如果允许文档元素以外的任何元素为非空,则约束不能用我所知道的任何模式语言的内容模型表达:内容模型作为一种上下文无关语法,并且文档中 某处 有一个 a-special
元素的要求需要一种上下文敏感的形式。
正如@potame 在评论中观察到的那样,Schematron 可以制定约束; XSD 1.1 中的断言也可以附加到文档元素的声明中。
一种可能的解决方法:以不同的方式标记元素的特殊性,例如通过指向文档中的某些 a
个元素:
<!ELEMENT my-container (#PCDATA|a|b)* >
<!ATTLIST my-container specials IDREFS #REQUIRED >
<!ELEMENT a EMPTY >
<!ATTLIST a id ID #IMPLIED>
<!ELEMENT b EMPTY>
由于my-container/@specials
是必需的,它必须至少命名文档中的一个元素。由于为其定义 ID 的唯一元素类型是 a
,因此由 specials
命名的元素保证是 a
个元素。
如果您使用 XSD 而不是 DTD,您可以只在元素中使用 minOccurs 属性。