Esquema XML Como Restringir Atributo por Enumeração

86

Eu tenho a seguinte tag XML

<price currency="euros">20000.00</price>

Como posso restringir o atributo de moeda a um dos seguintes:

  • euros
  • libras
  • dólares

E o preço para um duplo?

Acabei de receber um erro quando tento digitar em ambos. Aqui está o que descobri até agora:

<xs:element name="price">
    <xs:complexType>
        <xs:attribute name="currency">
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:enumeration value="pounds" />
                    <xs:enumeration value="euros" />
                    <xs:enumeration value="dollars" />
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
    </xs:complexType>
</xs:element>
Lucas
fonte
1
Se você fizer isso, você precisa remover type = "xs: string" do elemento <xs: attribute> também. Você não pode fornecer o tipo quando simpleType ou complexType está presente.
Sal

Respostas:

117

O valor numérico parece estar faltando em sua definição de preço. Experimente o seguinte:

<xs:simpleType name="curr">
  <xs:restriction base="xs:string">
    <xs:enumeration value="pounds" />
    <xs:enumeration value="euros" />
    <xs:enumeration value="dollars" />
  </xs:restriction>
</xs:simpleType>



<xs:element name="price">
        <xs:complexType>
            <xs:extension base="xs:decimal">
              <xs:attribute name="currency" type="curr"/>
            </xs:extension>
        </xs:complexType>
</xs:element>
usuário998692
fonte
3
Conforme respondido por @kjhughes, o <xs:extensionnão pode ser diretamente filho de, <xs:complexTypemas também deve estar contido por um <xs:complexContentou <xs:simpleContent.
HankCa
22

Nova resposta para a velha pergunta

Nenhuma das respostas existentes para esta velha questão aborda o problema real.

O verdadeiro problema é quexs:complexTypenão é possível terxs:extensionum filhodiretamenteno XSD. A solução é usarxs:simpleContentprimeiro. Detalhes a seguir ...


Seu XML,

<price currency="euros">20000.00</price>

será válido em qualquer um dos seguintes XSDs corrigidos:

Tipo de atributo definido localmente

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="price">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="xs:decimal">
          <xs:attribute name="currency">
            <xs:simpleType>
              <xs:restriction base="xs:string">
                <xs:enumeration value="pounds" />
                <xs:enumeration value="euros" />
                <xs:enumeration value="dollars" />
              </xs:restriction>
            </xs:simpleType>
          </xs:attribute>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
</xs:schema>

Tipo de atributo definido globalmente

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:simpleType name="currencyType">
    <xs:restriction base="xs:string">
      <xs:enumeration value="pounds" />
      <xs:enumeration value="euros" />
      <xs:enumeration value="dollars" />
    </xs:restriction>
  </xs:simpleType>

  <xs:element name="price">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="xs:decimal">
          <xs:attribute name="currency" type="currencyType"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
</xs:schema>

Notas

  • Como comentado por @ Paulo , estes mudam o tipo de conteúdo pricea partir xs:stringdexs:decimal , mas isso não é estritamente necessário e não era o problema real.
  • Conforme respondido por @ user998692 , você poderia separar a definição de moeda e alterar para xs:decimal, mas esse também não era o problema real.

O verdadeiro problema é que xs:complexTypenão podemos ter xs:extensionum filho diretamente no XSD;xs:simpleContenté necessário primeiro.

Um assunto relacionado (que não foi perguntado, mas pode ter confundido outras respostas):

Como poderia priceser restringido dado que tem um atributo?

Neste caso, uma definição global separada de priceType seria necessária; não é possível fazer isso apenas com definições de tipo local.

Como restringir o conteúdo do elemento quando o elemento tem atributo

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:simpleType name="priceType">  
    <xs:restriction base="xs:decimal">  
      <xs:minInclusive value="0.00"/>  
      <xs:maxInclusive value="99999.99"/>  
    </xs:restriction>  
  </xs:simpleType>

  <xs:element name="price">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="priceType">
          <xs:attribute name="currency">
            <xs:simpleType>
              <xs:restriction base="xs:string">
                <xs:enumeration value="pounds" />
                <xs:enumeration value="euros" />
                <xs:enumeration value="dollars" />
              </xs:restriction>
            </xs:simpleType>
          </xs:attribute>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
</xs:schema>
kjhughes
fonte
8

você precisa criar um tipo e tornar o atributo desse tipo:

<xs:simpleType name="curr">
  <xs:restriction base="xs:string">
    <xs:enumeration value="pounds" />
    <xs:enumeration value="euros" />
    <xs:enumeration value="dollars" />
  </xs:restriction>
</xs:simpleType>

então:

<xs:complexType>
    <xs:attribute name="currency" type="curr"/>
</xs:complexType>
ABCade
fonte
Olá, Infelizmente, isso não me permite restringir o tipo de preço para "double" E a enumeração de restrição no atributo "moeda" ao mesmo tempo
Lucas
-2
<xs:element name="price" type="decimal">
<xs:attribute name="currency" type="xs:string" value="(euros|pounds|dollars)" /> 
</element> 

Isso eliminaria a necessidade de enumeração completamente. Você pode alterar o tipo para duplo, se necessário.

Nachiket Kulkarni
fonte
@valuenão pode aparecer xs:attribute. xs:attributenão pode aparecer como filho de xs:element. Os xs:prefixos de namespace necessários são omitidos. Esta resposta é uma bagunça e deveria apenas ser excluída.
kjhughes de