O que elementFormDefault faz no XSD?

92

O que elementFormDefaultfaz e quando deve ser usado?

Então, encontrei algumas definições para elementFormDefaultvalores:

qualificado - elementos e atributos estão no targetNamespace do esquema

não qualificado - elementos e atributos não têm um namespace

Portanto, a partir dessa definição, eu pensaria que, se um esquema é definido como qualificado, por que você deve prefixar o tipo com o namespace? E quais são os cenários que você teria definido como não qualificado para esse assunto? Eu tentei pesquisar no Google, mas tudo que consegui foram algumas páginas do W3C que eram extremamente difíceis de entender.

Este é o arquivo com o qual estou trabalhando agora, por que preciso declarar o tipo de target:TypeAssignmentsquando declaro targetNamespaceo mesmo que 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>
Levi
fonte

Respostas:

73

ElementFormDefault não tem nada a ver com o namespace dos tipos no esquema, é sobre os namespaces dos elementos em documentos XML que estão em conformidade com o esquema.

Esta é a seção relevante da especificação:

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·.

Isso significa que o targetNamespace que você declarou no topo do esquema só se aplica a elementos no documento XML compatível com o esquema se elementFormDefault for "qualificado" ou se o elemento for declarado explicitamente no esquema como tendo form = "qualificado" .

Por exemplo: Se elementFormDefault não for qualificado -

<element name="name" type="string" form="qualified"></element>
<element name="page" type="target:TypePage"></element>

esperará que os elementos "name" estejam no namespace targetNamespace e os elementos "page" no namespace nulo.

Para evitar que você tenha de colocar form = "qualificado" em cada declaração de elemento, declarar elementFormDefault = "qualificado" significa que targetNamespace se aplica a cada elemento, a menos que seja substituído colocando form = "unqualified" na declaração do elemento.

Alohci
fonte
Embora esta resposta se refira à especificação, ela não a interpreta corretamente. Os elementos definidos localmente ainda estão no targetNamespace e nunca no namespace nulo. elementFormDefault é apenas uma opção que especifica se você deve ou não qualificá-los em um namespace em uma instância.
Ihe Onwuka,
1
@Ihe, isso não é correto: ou pelo menos, pode confundir as pessoas. Se a declaração de um elemento local não tiver form = qualificado, a propriedade {target namespace} do componente do esquema de declaração do elemento é "ausente", e isso significa que a propriedade URI do namespace da instância do elemento também deve ser "ausente.
Michael Kay
@MichaelKay Para mim isso é ainda mais confuso. A questão é se a página de exemplo está no namespace nulo, porque se for por que a especificação simplesmente não diz set elementFormDefault = unqualified coloca os elementos definidos localmente no namespace nulo. Está dizendo que a página não deve ser qualificada por namespace em uma instância é o mesmo que dizer que a página não está em nenhum namespace porque se é por que a especificação simplesmente não diz isso e por que um esquema com um targetNamespace está validando coisas que não nesse namespace?
Ihe Onwuka
1
Ele não "simplesmente diz isso" porque você o está descrevendo de maneira muito informal: a frase "colocar um elemento no namespace nulo" não está usando a terminologia da especificação XSD; a especificação prefere usar uma terminologia muito mais cuidadosa, o que muitas vezes dificulta a leitura, mas acaba sendo muito mais precisa.
Michael Kay de
1
No que me diz respeito, é uma resposta correta conforme escrita.
Michael Kay de
61

Considere o seguinte ComplexType AuthorTypeusado pelo authorelemento

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

E se elementFormDefault="unqualified"

então a seguinte instância XML é válida

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

o atributo de nome dos autores é permitido sem especificar o namespace (não qualificado). Todos os elementos que fazem parte de <xsd:complexType>são considerados locais para complexType.

E se elementFormDefault="qualified"

então a instância deve ter os elementos locais qualificados

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

por favor consulte este link para mais detalhes

Feminino
fonte
56

Resposta e explicação novas e detalhadas para uma pergunta antiga e frequente ...

Resposta curta : se você não adicionar elementFormDefault="qualified"a xsd:schema, o unqualifiedvalor padrão significa que os elementos declarados localmente não estão em nenhum namespace .

Há muita confusão sobre o que elementFormDefault faz, mas isso pode ser rapidamente esclarecido com um pequeno exemplo ...

Versão simplificada do seu 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>

Pontos chave:

  • O assignmentelemento é definido localmente.
  • Os elementos definidos localmente no XSD não estão em nenhum namespace por padrão.
    • Isso ocorre porque o valor padrão para elementFormDefaulté unqualified.
    • Isso é indiscutivelmente um erro de design dos criadores do XSD.
    • A prática padrão é sempre usar de elementFormDefault="qualified" modo que assignmentesteja no namespace de destino como seria de se esperar.
  • É um formatributo raramente usado em xs:elementdeclarações para as quais elementFormDefaultestabelece valores padrão.

XML aparentemente válido

Este XML parece que deve ser válido de acordo com o XSD acima:

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

Aviso prévio:

  • O namespace padrão em assignmentslocais assignmentse todos os seus descendentes no namespace padrão ( http://www.levijackson.net/web340/ns).

Erro de validação perplexo

Apesar de parecer válido, o XML acima produz o seguinte erro de validação confuso:

[Erro] try.xml: 4: 23: cvc-complex-type.2.4.a: Conteúdo inválido foi encontrado começando com o elemento 'atribuição'. Espera-se um de '{atribuição}'.

Notas:

  • Você não seria o primeiro desenvolvedor a amaldiçoar esse diagnóstico que parece dizer que o conteúdo é inválido porque esperava encontrar um assignmentelemento, mas na verdade encontrou um assignmentelemento. ( WTF )
  • O que isso realmente significa: O {e }ao redor assignmentsignifica que a validação não esperava assignment em nenhum namespace aqui. Infelizmente, quando diz que encontrou um assignmentelemento, não menciona que o encontrou em um namespace padrão que difere de nenhum namespace.

Solução

  • Grande parte do tempo: adicione elementFormDefault="qualified"aoxsd:schema elemento do XSD. Isso significa que um XML válido deve colocar elementos no namespace de destino quando declarado localmente no XSD; caso contrário, o XML válido deve colocar os elementos declarados localmente em nenhum namespace.
  • Pequena minoria do tempo: Altere o XML para estar em conformidade com o requisito do XSD de que assignmentnão haja namespace. Isso pode ser alcançado, por exemplo, adicionando xmlns=""ao assignmentelemento.

Créditos: Obrigado a Michael Kay pelo feedback útil sobre esta resposta.

kjhughes
fonte
12

Importante observar com elementFormDefault é que ele se aplica localmente elementos definidos , normalmente denominados elementos dentro de um bloco complexType, em oposição a elementos globais definidos no nível superior do esquema. Com elementFormDefault = "qualificado", você pode endereçar elementos locais no esquema de dentro do documento xml usando o namespace de destino do esquema como o namespace padrão do documento.

Na prática, use elementFormDefault = "qualificado" para poder declarar elementos em blocos aninhados, caso contrário, você terá que declarar todos os elementos no nível superior e se referir a eles no esquema em elementos aninhados usando o atributo ref, resultando em um esquema muito menos compacto.

Esta parte do XML Schema Primer fala sobre isso: http://www.w3.org/TR/xmlschema-0/#NS

stephan f
fonte
Um pequeno esclarecimento sobre o que parece ser a resposta mais precisa. Com elementFormDefault = relevant, você deve qualificar o namespace dos elementos locais na instância. Com ele definido como unqualified, você não deve qualificá-los com namespace.
Ihe Onwuka,
6

elementFormDefault = "qualificado" é usado para controlar o uso de namespaces em documentos de instância XML (arquivo .xml), em vez de namespaces no próprio documento de esquema (arquivo .xsd).

Ao especificar elementFormDefault = "qualificado", impomos a declaração de namespace a ser usada em documentos validados com este esquema.

É prática comum especificar esse valor para declarar que os elementos devem ser qualificados em vez de não qualificados. No entanto, como attributeFormDefault = "unqualified" é o valor padrão, ele não precisa ser especificado no documento de esquema, se não se quiser qualificar os namespaces.

Feri
fonte
elementFormDefault só se aplica a elementos definidos localmente. Os elementos globais devem ser qualificados com namespace independentemente.
Ihe Onwuka,
0

Percebi que XMLSpy (pelo menos versão 2011) precisa de um targetNameSpace definido se elementFormDefault = "qualificado" for usado. Caso contrário, não validará. E também não vai gerar xmls com prefixos de namespace

Neal
fonte