我有以下XSD文件:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="list">
<xsd:complexType>
<xsd:sequence><!--arbitrary number of log entries-->
<xsd:element name="vocable" minOccurs="0" maxOccurs="unbounded"><!--a log entry is a complex type-->
<xsd:complexType>
<xsd:sequence>
<xsd:element name="firstLanguageTranslations" type="xsd:string" minOccurs="1" maxOccurs="1" />
<xsd:element name="firstLanguagePhoneticScripts" type="xsd:string" minOccurs="1" maxOccurs="1" />
<xsd:element name="secondLanguageTranslations" type="xsd:string" minOccurs="1" maxOccurs="1" />
<xsd:element name="secondLanguagePhoneticScripts" type="xsd:string" minOccurs="1" maxOccurs="1" />
<xsd:element name="topics" type="xsd:string" minOccurs="1" maxOccurs="1" />
<xsd:element name="chapters" type="xsd:string" minOccurs="1" maxOccurs="1" />
<xsd:element name="description" type="xsd:string" minOccurs="1" maxOccurs="1" />
<xsd:element name="learnLevel" type="xsd:string" minOccurs="1" maxOccurs="1" />
<xsd:element name="relevanceLevel" type="xsd:string" minOccurs="1" maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
现在我想改变它,所以在最内层的序列中,有<key>attribute name</key>
和<value>value</value>
的元素对,所以在我的程序中,我可以简单地添加新的属性。但是,我希望每个vocable元素的这些属性都相同。我如何确保在XSD文件中?
我将列出XSD文件的要求,使其更加清晰:
<key>attribute name</key>
和<value>attribute value</value>
如果使用键和值元素不是最好的方法,我愿意接受其他建议。
修改#1 : 为了更清楚,我将添加两个例子: 应该有效:
<?xml version="1.0" encoding="utf-8" ?>
<list>
<vocable>
<key>firstLanguageTranslation</key>
<value>word1</value>
<key>secondLanguageTranslation</key>
<value>word2</value>
</vocable>
<vocable>
<key>firstLanguageTranslation</key>
<value>word1</value>
<key>secondLanguageTranslation</key>
<value>word2</value>
</vocable>
</list>
同样有效,因为vocable具有相同的属性:
<?xml version="1.0" encoding="utf-8" ?>
<list>
<vocable>
<key>firstLanguageTranslation</key>
<value>word1</value>
<key>secondLanguageTranslation</key>
<value>word2</value>
<key>something</key>
<value>word4</value>
</vocable>
<vocable>
<key>firstLanguageTranslation</key>
<value>word1</value>
<key>secondLanguageTranslation</key>
<value>word2</value>
<key>something</key>
<value>word3</value>
</vocable>
</list>
无效,因为vocables没有相同的属性:
<?xml version="1.0" encoding="utf-8" ?>
<list>
<vocable>
<key>firstLanguageTranslation</key>
<value>word1</value>
<key>secondLanguageTranslation</key>
<value>word2</value>
</vocable>
<vocable>
<key>firstLanguageTranslation</key>
<value>word1</value>
<key>secondLanguageTranslation</key>
<value>word2</value>
<key>something else</key>
<value>word3</value>
</vocable>
</list>
修改#2 :
为什么这对我很重要:
我希望用户能够在他们认为合适的程序中向vocable添加(或删除)属性,因为不同的人对于应该在vocable中保存的内容有不同的期望和意见。我希望这样做,而无需每次用户添加属性时编写代码来手动更改XSD文件。 同时,我希望能够让用户选择,vocable的哪些属性将显示在vocables表中。如果我知道,每个vocable都有一个特定的属性,这就容易多了。
答案 0 :(得分:1)
架构设计
关于您的XML设计,除key
和value
元素外,一切看起来都很好。例如,想象一下,有人想要从这样的文档中选择 secondLanguageTranslation
的值。在XPath中,他们必须按照
/list/vocable/key[. = 'secondLanguageTranslation']/following-sibling::value[1]
这是一个很长的声明!现在,让我们假设该文件如下:
<list>
<vocable>
<firstLanguageTranslation>word1</firstLanguageTranslation>
<secondLanguageTranslation>word2</secondLanguageTranslation>
</vocable>
</list>
鉴于这个新文档,可以使用更简单的XPath表达式检索相同的信息:
/list/vocable/secondLanguageTranslation
哪个更容易阅读,即使元素名称有点长(非常主观)。为了使我的观点更加普遍:在XML中,元素不仅包含信息,而且是信息,因为元素的名称本身信息。要清晰,在像
这样的结构中<key>secondLanguage</key>
key
元素只不过是名称的容器,而在
<secondLanguage>word1</secondLanguage>
元素名称具有明确的语义,与key
元素不同,后者包含任何名称。或者,键和值很容易表示为属性:
<vocable secondLanguageTranslation="word1"/>
特别是如果键和值的内容只是单个单词。
确保所有元素都具有相同的任意元素集
那就是说,我想我理解你为什么要介绍key
和value
- 因为那时,对文档的更改不需要你更改架构文档。但是,这意味着您失去了对文档内容的控制 - 您只知道有效文档包含key
和value
元素。控制文档的结构和内容正是XML Schema的用途。如果您的文档不断发展,也许没有任何XML Schema可用。
仍然认真对待key
和value
结构,确保所有元素实例具有相同的内容可以使用断言完成。确保所有vocable
元素具有相同数量的key
元素的断言可能如下:
<xsd:assert test="every $x in vocable satisfies (if ($x/following-sibling::vocable) then count($x/key) = count($x/following-sibling::vocable[1]/key) else true())"/>
以及比较所有vocable
元素的键的规则:
<xsd:assert test="every $x in vocable satisfies (if ($x/following-sibling::vocable) then (every $y in $x/key satisfies $y = $x/following-sibling::vocable[1]/key) else true())"/>
嵌入到完整的架构中:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="list">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="vocable" minOccurs="0" maxOccurs="unbounded" type="vocableType"/>
</xsd:sequence>
<xsd:assert test="every $x in vocable satisfies (if ($x/following-sibling::vocable) then count($x/key) = count($x/following-sibling::vocable[1]/key) else true())"/>
<xsd:assert test="every $x in vocable satisfies (if ($x/following-sibling::vocable) then (every $y in $x/key satisfies $y = $x/following-sibling::vocable[1]/key) else true())"/>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="vocableType">
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="key" type="xsd:string"/>
<xsd:element name="value" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
断言必须在list
的定义中进行,因为单个vocable
元素内的断言只能访问以自己为根的子树。断言只能在XSD 1.1中使用,而这种规则在XSD 1.0中是完全不可能的。
正如您所看到的,这种表达方式难以阅读 - 您能否澄清为什么您确实需要确保所有vocable
元素具有相同的内容?特别是因为你似乎非常满足于不知道文档中会出现哪些密钥。