XSD 任意但固定数量的元素

XSD arbitrary but fix number of elements

我有以下 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>

现在我想改一下,让最里面的sequence里面有<key>attribute name</key><value>value</value>的元素对,这样在我的程序中,我可以简单地添加新的属性。但是,我希望每个可调用元素的这些属性都相同。我如何确保在 XSD 文件中?

我将列出 XSD 文件的要求以使其更清楚:

  1. XML 文件可以包含任意数量的词汇
  2. 一个词汇可以包含任意数量的属性
  3. 一个vocable的属性对所有vocables都是一样的(相同的数量,相同的键)
  4. 属性使用 <key>attribute name</key><value>attribute value</value>
  5. 表示

如果使用键和值元素不是执行此操作的最佳方法,我愿意接受其他建议。

编辑#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>

同样有效,因为词汇具有相同的属性:

<?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>

无效,因为词汇不具有相同的属性:

<?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的哪些属性将显示在table个vocables中。当我知道每个 vocable 都有一个特定的属性时,这就容易多了。

架构设计

关于您的 XML 设计,除了 keyvalue 元素外,一切看起来都很好。想象一下,例如,有人想从这样的文档中 select 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 中,元素不仅 包含 信息,它们 信息,在某种意义上元素的名称本身就是信息。 crystal-清晰,在

这样的结构中
<key>secondLanguage</key>

key 元素只不过是名称的容器,而在

<secondLanguage>word1</secondLanguage>

元素名称具有明确的语义,这与包含任何名称的 key 元素不同。或者,键和值很容易表示为属性:

<vocable secondLanguageTranslation="word1"/>

尤其是当键和值的内容永远都是单个单词时。

确保所有元素具有相同的任意元素集

话虽如此,我想我明白您为什么要引入 keyvalue - 因为那样的话,对文档的更改将不需要您更改架构文档。而且,这也意味着您无法控制文档内容 - 您所知道的是有效文档包含 keyvalue 元素。控制文档的结构和内容正是 XML Schema 的用途。如果您的文档在不断发展,也许 XML 架构没有多大用处。

不过,认真对待 keyvalue 结构,确保元素的所有实例都具有相同的内容可以使用 assertions 来完成。确保所有 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 元素具有相同的内容?特别是因为您似乎很满足于不知道文档中会出现哪些键。