任何顺序的 XML 元素,有些是必需的,有些不是

标签 xml xsd

我正在尝试获得一个允许以任何顺序排列的元素列表。有些元素是必需的(最少 1 个,最多 1 个),有些是可选的,最多有一个,有些是可选的,可以有任意数量。这就是我所拥有的并且 XSD 是有效的,但是当我去验证 XML 时,我试图实现的规则并没有被强制执行。例如,id 不是必需的。

<xsd:complexType name="feedType">
        <xsd:annotation>
            <xsd:documentation>
                The Atom feed construct is defined in section 4.1.1 of the format spec.
            </xsd:documentation>
        </xsd:annotation>
        <xsd:choice minOccurs="3" maxOccurs="unbounded">
            <xsd:element name="author" type="atom:personType" minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="category" type="atom:categoryType" minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="contributor" type="atom:personType" minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="generator" type="atom:generatorType" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="icon" type="atom:iconType" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="id" type="atom:idType" minOccurs="1" maxOccurs="1"/>
            <xsd:element name="link" type="atom:linkType" minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="logo" type="atom:logoType" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="rights" type="atom:textType" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="subtitle" type="atom:textType" minOccurs="0" maxOccurs="1"/>
            <xsd:element name="title" type="atom:textType" minOccurs="1" maxOccurs="1"/>
            <xsd:element name="updated" type="atom:dateTimeType" minOccurs="1" maxOccurs="1"/>
            <xsd:element name="entry" type="atom:entryType" minOccurs="0" maxOccurs="unbounded"/>
            <xsd:any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
        </xsd:choice>
        <xsd:attributeGroup ref="atom:commonAttributes"/>
    </xsd:complexType>

最佳答案

我刚刚遇到了同样的问题并查看了他们在 XHTML XSD 中做了什么. head 中的情况相同:title 是必需的,base 是可选的,然后是任意数量的 scriptstylemetalinkobject 元素。

这是他们所做的:首先,他们将可能出现不止一次的可选元素分组:

  <xs:group name="head.misc">
    <xs:sequence>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="script"/>
        <xs:element ref="style"/>
        <xs:element ref="meta"/>
        <xs:element ref="link"/>
        <xs:element ref="object"/>
      </xs:choice>
    </xs:sequence>
  </xs:group>

然后他们在实际的 head 定义中引用了这个组:

  <xs:sequence>
    <xs:group ref="head.misc"/>
    <xs:choice>
      <xs:sequence>
        <xs:element ref="title"/>
        <xs:group ref="head.misc"/>
        <xs:sequence minOccurs="0">
          <xs:element ref="base"/>
          <xs:group ref="head.misc"/>
        </xs:sequence>
      </xs:sequence>
      <xs:sequence>
        <xs:element ref="base"/>
        <xs:group ref="head.misc"/>
        <xs:element ref="title"/>
        <xs:group ref="head.misc"/>
      </xs:sequence>
    </xs:choice>
  </xs:sequence>

这有点棘手。写成类似正则表达式的伪代码,上面看起来像这样:

misc=(script|style|meta|link|object)*
head=${misc}(title${misc}(base${misc})?|base${misc}title${misc})

所以,从技术上讲它是可行的。

但是,这需要将强制元素和可选元素的所有可能排列(以及介于两者之间的杂项)放入 choice 中。对于 n 元素,这是 n! 子节点。因此,对于 n=2 的 XHTML,它们以 n!=2 结束。在您使用 n=8 的情况下,它将是 n!=40320

FWIW,这是生成 XSD 的算法:

result = '<xs:group name="misc"><xs:sequence><xs:choice minOccurs="0" maxOccurs="unbounded">'
forall(optionalArbitraryCountElements as element)
    result += '<xs:element ref="' + element.name + '"/>'
result += '</xs:choice></xs:sequence></xs:group>'

result += '<xs:complexType name="feedType"><xs:sequence><xs:group ref="misc"/><xs:choice>'
permutations = getAllPermutations(mandatoryElements + optionalOnceElements)
foreach (permutations as p)
    result += '<xs:sequence>'
    foreach (p as element)
        if (element.isOptional)
            result += '<xs:sequence minOccurs="0">'
        result += '<xs:element ref="' + element.name + '"/><xs:group ref="misc"/>'
        if (element.isOptional)
            result += '</xs:sequence>'
    result += '</xs:sequence>'
result += '</xs:choice></xs:sequence></xs:complexType>'

return result

关于任何顺序的 XML 元素,有些是必需的,有些不是,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10902485/

相关文章:

python - 使用空命名空间解析 xml

java - 在布局和 ScrollView 底部添加按钮

.net - 在 xsd 中使用 key 的正确方法

java - XSD 错误 : cvc-complex-type. 2.4.a:发现以元素开头的无效内容

java - 无法找到 XML 模式命名空间的 Spring NamespaceHandler [http ://jboss. org/xml/ns/javax/validation/configuration]

xml - 删除 XML 元素的 PowerShell 脚本

android - 创建聊天布局?

xml - 有没有在线工具可以获取XML节点的值?

xslt - ID/IDREFS 在 XML Schema 中的使用

.net - XSDObjectGen.exe 与 XSD.exe