如何强制XML文件中存在某个元素?

如何强制XML文件中存在某个元素?,xml,dtd,Xml,Dtd,我想强制一个元素在我的文档中至少出现一次。对于这样的语法,这样的文档是有效的(因为出现): 文本文本文本 文本文本文本 正文 鉴于这将被视为无效(因为不会发生): 文本 文本 正文 我用下面的语法尝试了不同的方法,但我似乎不能按照我需要的方式来做 <!ELEMENT my-container ( #PCDATA | a | a-special | b )*> <!ELEMENT a-special EMPTY> <!ELEMENT a EMPTY>

我想强制一个
元素在我的文档中至少出现一次。对于这样的语法,这样的文档是有效的(因为
出现):


文本文本文本
文本文本文本
正文
鉴于这将被视为无效(因为
不会发生):


文本
文本
正文
我用下面的语法尝试了不同的方法,但我似乎不能按照我需要的方式来做

<!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表示

如果允许document元素以外的任何元素为非空,则约束不能用我所知道的任何模式语言的内容模型来表达:内容模型的功能类似于一种上下文无关语法,文档中某处有一个
a-special
元素的要求需要一种上下文敏感性

正如@potame在一篇评论中所观察到的,Schematron可以表述约束;XSD1.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,则可以只使用元素中的属性。

是的,可以将属性定义为
\REQUIRED
。你能给我们看看你已经设置的DTD吗?@potame是的,我知道我可以根据需要设置属性,但这不是我在这里的意思。我不想说该属性是必需的,而是说一个具有某个必需属性值的元素是必需的。想象一下
A
是为苹果准备的,我想强制每个文档在文本中至少提到一个苹果。我目前无法发布DTD,但我会在下班回家后立即添加。乍一看,我会说DTD是不可能的。在某些情况下,可以使用XML模式执行某些操作。我还想到了Schematron,它可能是实现这种验证的一个选项。@potame-Hmm。。是否至少有一种方法可以强制在文本中的某个地方出现元素
?是否需要使用DTD或XSD/XML模式?好的,我明白了,谢谢!关于上一个解决方案:这意味着没有其他元素可以将id作为属性名,对吗?取决于“can”的含义。如果
a
以外的任何元素都可以有ID,则规则“使用
my container
上的
specials
属性仅指向
a
元素”将成为应用程序约定,而不是有效性规则,
specials
的DTD验证将不能保证遵守该约定。但是,它将捕获一些错误并使检查应用程序约定变得相当容易(对于
specials
属性中的每个IDREF标记,找到已标识的元素并验证它是否为
a
元素)。所以很多使用DTD定义的词汇表都使用类似的约定。你能详细介绍一下这个答案吗?我不清楚minOccurs如何单独解决OP的问题,我想知道你的意思。他可以在一个元素上使用minOccurs,1和max为无界。那么该元素至少需要存在一次。它不是很大程度上依赖于上下文吗?如果他将表达式
(#PCDATA | a | a-special | b)*
翻译成XSD作为
(在混合上下文中),这将如何解决问题?
(#PCDATA)
(#PCDATA | x | y | ... |z)*
(#PCDATA)*
<!ELEMENT my-container (#PCDATA|a|b)* >
<!ATTLIST my-container specials IDREFS #REQUIRED >
<!ELEMENT a EMPTY >
<!ATTLIST a id ID #IMPLIED>
<!ELEMENT b EMPTY>