XSD中的elementFormDefault是什么作用?

109

elementFormDefault是什么,什么时候应该使用它?

我找到了一些关于elementFormDefault值的定义:

qualified - 元素和属性在模式的 targetNamespace中

unqualified - 元素和属性没有命名空间

根据这个定义,如果一个模式被设置为qualified ,那么为什么必须要用命名空间来前缀类型呢?什么情况下会使用unqualified?我尝试过谷歌搜索,但只得到了一些极难理解的W3C页面。

这是我现在正在处理的文件,请问为什么我需要将类型声明为target:TypeAssignments,当我已经将targetNamespace声明为与xmlns:target相同的命名空间?

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:target="http://www.levijackson.net/web340/ns"
        targetNamespace="http://www.levijackson.net/web340/ns" 
        elementFormDefault="qualified">
  <element name="assignments">
    <complexType>
      <sequence>
        <element name="assignments" type="target:TypeAssignments"
                 minOccurs="1" maxOccurs="unbounded"/>
      </sequence>
    </complexType>
  </element>
  <complexType name="TypeAssignments">
    <sequence>
      <element name="assignment" type="target:assignmentInfo"
               minOccurs="0" maxOccurs="unbounded"/>
    </sequence>
  </complexType>
  <complexType name="assignmentInfo">
    <sequence>
      <element name="name" type="string"/>
      <element name="page" type="target:TypePage"/>
      <element name="file" type="target:TypeFile" 
               minOccurs="0" maxOccurs="unbounded"/>
    </sequence>
    <attribute name="id" type="string" use="required"/>
  </complexType>
  <simpleType name="TypePage">
    <restriction base="integer">
      <minInclusive value="50" />
      <maxInclusive value="498" />
    </restriction>
  </simpleType>
  <simpleType name="TypeFile">
    <restriction base="string">
      <enumeration value=".xml" />
      <enumeration value=".dtd" />
      <enumeration value=".xsd" />
    </restriction>
  </simpleType>
</schema>
6个回答

85

ElementFormDefault与模式中类型的命名空间无关,它是关于符合模式的XML文档中元素的命名空间的设置。

这是规范的相关部分:

Element Declaration Schema

Component Property  {target namespace}
Representation      If form is present and its ·actual value· is qualified, 
                    or if form is absent and the ·actual value· of 
                    elementFormDefault on the <schema> ancestor is qualified, 
                    then the ·actual value· of the targetNamespace [attribute]
                    of the parent <schema> element information item, or 
                    ·absent· if there is none, otherwise ·absent·.
这意味着您在模式顶部声明的 targetNamespace 仅适用于元素形式为 "qualified" 或以 form="qualified" 明确声明在模式中的符合 XML 文档中的元素。
例如:如果 elementFormDefault 为 unqualified -
<element name="name" type="string" form="qualified"></element>
<element name="page" type="target:TypePage"></element>

期望"name"元素在目标命名空间中,而"page"元素在null命名空间中。

为了避免在每个元素声明中都使用form="qualified",声明elementFormDefault="qualified"意味着目标命名空间适用于每个元素,除非在元素声明中使用form="unqualified"覆盖它。


尽管此答案涉及规范,但它并没有正确解释。本地定义的元素仍然在目标命名空间中,永远不会在空命名空间中。elementFormDefault只是一个开关,指定是否应在实例中对它们进行命名空间限定。 - Ihe Onwuka
1
@Ihe,那不正确:或者至少会让人感到困惑。如果本地元素声明没有form=qualified,则元素声明模式组件的{目标命名空间}属性为“缺失”,这意味着元素实例的命名空间URI属性也必须是“缺失”。 - Michael Kay
1
它并不是“简单地说”,因为您描述得非常非正式:“将元素放入空名称空间”这一短语并未使用XSD规范的术语;规范更喜欢使用更加谨慎的术语,这往往使阅读变得困难,但最终更加精确。 - Michael Kay
@MichaelKay,我们正在评论的答案中说:“将期望“name”元素在目标命名空间中,“page”元素在null命名空间中”。因此,您所提到的非正式描述源自答案而不是我的评论,这就是我评论所反对的内容。 - Ihe Onwuka
1
就我而言,这个答案是正确的。 - Michael Kay
显示剩余3条评论

72

一道经常被问到的问题有了新的详细答案和解释...

简短回答:如果在 xsd:schema 中不添加 elementFormDefault="qualified",那么默认值 unqualified 表示本地声明的元素没有命名空间

关于 elementFormDefault 的作用,存在很多混淆,但可以通过一个简短的示例来快速澄清...

简化版 XSD:

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        xmlns:target="http://www.levijackson.net/web340/ns"
        targetNamespace="http://www.levijackson.net/web340/ns">
  <element name="assignments">
    <complexType>
      <sequence>
        <element name="assignment" type="target:assignmentInfo" 
                 minOccurs="1" maxOccurs="unbounded"/>
      </sequence>
    </complexType>
  </element>
  <complexType name="assignmentInfo">
    <sequence>
      <element name="name" type="string"/>
    </sequence>
    <attribute name="id" type="string" use="required"/>
  </complexType>
</schema>

要点:

  • assignment 元素在本地定义。
  • XSD 中本地定义的元素默认没有命名空间。
    • 这是因为 elementFormDefault 的默认值为 unqualified
    • 这可能是 XSD 创建者的设计失误之一。
    • 标准做法是始终使用 elementFormDefault="qualified",使得 assignment 位于目标命名空间中,正如人们所期望的那样。
  • form 属性很少用于 xs:element 声明,其中 elementFormDefault 确定默认值。

看似有效的 XML

根据上述 XSD,这个 XML 看起来应该是有效的:

<assignments xmlns="http://www.levijackson.net/web340/ns"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.levijackson.net/web340/ns try.xsd">
  <assignment id="a1">
    <name>John</name>
  </assignment>
</assignments>

注意:

  • assignments 的默认命名空间将 assignments 及其所有子元素放置在默认命名空间 (http://www.levijackson.net/web340/ns) 中。

令人困惑的验证错误

尽管看起来很有效,但上述 XML 产生了以下令人困惑的验证错误:

[Error] try.xml:4:23: cvc-complex-type.2.4.a:找到开始于元素“assignment”的无效内容。应该其中之一:{assignment}。

注:

  • 你不会是第一个咒骂这个诊断工具的开发者,因为它似乎说“内容无效”,因为它期望找到一个“assignment”元素,但实际上找到了一个“assignment”元素。(WTF)
  • 真正的意思是:括在“{}”中的“assignment”意味着验证希望在此处找到不带命名空间的“assignment”。不幸的是,当它说找到了一个“assignment”元素时,它没有提到它在一个与无命名空间不同的默认命名空间中找到了它。

解决方案

  • 绝大多数情况:xsd:schema 元素添加 elementFormDefault="qualified"。这意味着有效的 XML 必须在本地声明在 XSD 中时将元素放置在目标命名空间中;否则,有效的 XML 必须将本地声明的元素放置在无命名空间中。
  • 极少数情况: 更改 XML 以符合 XSD 要求 assignment 不带命名空间。例如,可以通过向 assignment 元素添加 xmlns="" 来实现。

致谢:感谢Michael Kay对此答案提供有用反馈。


2
"{ 该元素的左大括号和右大括号 }"是关键所在,让我在挣扎了一个小时后找到了解决方案!谢谢!" - Cliff

71

请考虑以下由author元素使用的复合类型AuthorType

<xsd:complexType name="AuthorType">
  <!-- compositor goes here -->
  <xsd:sequence>
     <xsd:element name="name" type="xsd:string"/>
     <xsd:element name="phone" type="tns:Phone"/>
  </xsd:sequence>
  <xsd:attribute name="id" type="tns:AuthorId"/>
</xsd:complexType>
<xsd:element name="author" type="tns:AuthorType"/>
如果elementFormDefault="unqualified",那么以下XML实例是有效的。
<x:author xmlns:x="http://example.org/publishing">
   <name>Aaron Skonnard</name>
   <phone>(801)390-4552</phone>
</x:author>

作者的名称属性可以省略命名空间(Qualified)。任何属于<xsd:complexType>的元素都被视为局部元素(Local)。

如果elementFormDefault="qualified"

那么实例必须将局部元素限定(Qualified)。

<x:author xmlns:x="http://example.org/publishing">
   <x:name>Aaron Skonnard</name>
   <x:phone>(801)390-4552</phone>
</x:author>

请参考此链接获取更多详细信息。


嗯...name是一个元素,不是一个属性。 - Suncat2000

15
需要翻译的内容:

需要注意的是,elementFormDefault 仅适用于本地定义的元素,通常是在complexType块内命名的元素,而不是在模式顶层定义的全局元素。使用 elementFormDefault="qualified",您可以使用模式的目标命名空间作为文档的默认命名空间,在 xml 文档中引用模式中的本地元素。

实际上,使用 elementFormDefault="qualified" 可以声明嵌套块中的元素,否则您将不得不在顶层声明所有元素,并在模式中引用这些元素以在嵌套元素中使用 ref 属性,导致模式更加冗长。

XML Schema Primer 中的这一部分讨论了它:http://www.w3.org/TR/xmlschema-0/#NS


对看起来最准确的答案进行轻微澄清。使用elementFormDefault=qualified,您必须在实例中为本地元素添加命名空间限定符。如果将其设置为unqualified,则不得为它们添加命名空间限定符。 - Ihe Onwuka

6

elementFormDefault="qualified" 用于控制 XML 实例文档(.xml 文件)中的命名空间使用,而不是架构文档本身(.xsd 文件)中的命名空间。

通过指定 elementFormDefault="qualified",我们强制要求在使用此架构验证的文档中使用命名空间声明。

通常将此值指定为声明元素应该限定而不是非限定。但是,由于 attributeFormDefault="unqualified" 是默认值,如果不想限定命名空间,则无需在架构文档中指定。


elementFormDefault仅适用于本地定义的元素。全局元素必须进行命名空间限定。 - Ihe Onwuka

0

我注意到XMLSpy(至少2011版本)需要定义targetNameSpace,如果使用elementFormDefault =“qualified”,否则将无法验证。而且也不会生成带有命名空间前缀的xml。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接