xsd里面的elementFormDefault属性的用法

XML的schema文件当中,一个常用的属性叫做elementFormDefault。下面是一个sample:

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

上面的xsd文件可以命名为try.xsd。下面是对应的XML文件,命名为try.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>

使用xmllint命令来进行验证:

$ xmllint --schema try.xsd try.xml --noout
try.xml:4: element assignment: Schemas validity error : Element '{http://www.levijackson.net/web340/ns}assignment': This element is not expected. Expected is ( assignment ).
try.xml fails to validate

可以看到这个xml文件没有通过这个xsd的语法验证。但是看起来xml文件的内容并没有什么问题啊?原因是xsd解析的一个一开始的设计bug:也就是说xsd里面的nested elements,并没有namespace的scope继承关系。为了fix这个问题,xsd的schema里面提供一个elementFormDefault属性,可以这样设置:

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

如上所示,加上elementFormDefault="qualified"的属性,这样nested elements之间的namespaces就约定好了继承关系。重新使用xmllint命令来检查:

$ xmllint --schema try.xsd try.xml --noout
try.xml validates

如上所示,这个验证就可以通过了。

参考资料: