2008-10-09 28 views
5

Intento definir un esquema para los documentos XML que recibo.Esquema XML para elementos con el mismo nombre pero con una subestructura diferente según el contexto

Los documentos parecen:

<root> 
    <items> 
     <group name="G-1"> 
      <item name="I-1"/> 
      <item name="I-2"/> 
      <item name="I-3"/> 
      <item name="I-4"/> 
     </group> 
    </items> 
    <data> 
     <group name="G-1" place="here"> 
      <customer name="C-1"> 
       <item name="I-1" count="3"/> 
       <item name="I-2" count="4"/> 
      </customer> 
      <customer name="C-2"> 
       <item name="I-3" count="7"/> 
      </customer> 
     </group> 
    </data> 
</root> 

me trataron XMLSPY y xsd.exe de .NET 2.0. Ambas crearon definiciones de esquema que permiten por debajo de <group> cualquier cantidad de elementos <item> y <customer>. Pero lo que estoy buscando debe restringir <group> por debajo de <items> a <item> elementos y <group> por debajo de <data> por <customer> elementos.

¿Es esto algo el esquema xml no es capaz en absoluto?

Respuesta

3

Sí, XSD puede manejar esto. Me genera este esquema de Visual Studio 2008 (mucho más rápido que hacerlo a mano) y que va a hacer lo que está buscando:

<?xml version="1.0" encoding="utf-8"?> 
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:element name="root"> 
    <xs:complexType> 
     <xs:sequence> 
     <xs:element name="items"> 
      <xs:complexType> 
      <xs:sequence> 
       <xs:element name="group"> 
       <xs:complexType> 
        <xs:sequence> 
        <xs:element maxOccurs="unbounded" name="item"> 
         <xs:complexType> 
         <xs:attribute name="name" type="xs:string" use="required" /> 
         </xs:complexType> 
        </xs:element> 
        </xs:sequence> 
        <xs:attribute name="name" type="xs:string" use="required" /> 
       </xs:complexType> 
       </xs:element> 
      </xs:sequence> 
      </xs:complexType> 
     </xs:element> 
     <xs:element name="data"> 
      <xs:complexType> 
      <xs:sequence> 
       <xs:element name="group"> 
       <xs:complexType> 
        <xs:sequence> 
        <xs:element maxOccurs="unbounded" name="customer"> 
         <xs:complexType> 
         <xs:sequence> 
          <xs:element maxOccurs="unbounded" name="item"> 
          <xs:complexType> 
           <xs:attribute name="name" type="xs:string" use="required" /> 
           <xs:attribute name="count" type="xs:unsignedByte" use="required" /> 
          </xs:complexType> 
          </xs:element> 
         </xs:sequence> 
         <xs:attribute name="name" type="xs:string" use="optional" /> 
         </xs:complexType> 
        </xs:element> 
        </xs:sequence> 
        <xs:attribute name="name" type="xs:string" use="required" /> 
        <xs:attribute name="place" type="xs:string" use="required" /> 
       </xs:complexType> 
       </xs:element> 
      </xs:sequence> 
      </xs:complexType> 
     </xs:element> 
     </xs:sequence> 
    </xs:complexType> 
    </xs:element> 
</xs:schema> 
+0

No hay problema! Encantado de ayudar. –

6

Los puntos clave (véase XML Schema Runtime Polymorphism via xsi:type and Abstract Types para la completa y correcta contexto/colocación/uso) son:

  1. crear un tipo de base con (abstract = "true" para evitar que sea utilizado directamente)

    Nota: el atributo ref sustituye el atributo de nombre para elementos definidos en otra parte

    <xs:complexType name="CustomerType" abstract="true" > 
        <xs:sequence> 
        <xs:element ref="cust:FirstName" /> 
        <xs:element ref="cust:LastName" /> 
        <xs:element ref="cust:PhoneNumber" minOccurs="0"/> 
        </xs:sequence> 
        <xs:attribute name="customerID" type="xs:integer" /> 
    </xs:complexType> 
    
  2. crear dos tipos o más derivados extendiendo o restringiendo el tipo base

    <xs:complexType name="MandatoryPhoneCustomerType" > 
        <xs:complexContent> 
        <xs:restriction base="cust:CustomerType"> 
         <xs:sequence> 
         <xs:element ref="cust:FirstName" /> 
         <xs:element ref="cust:LastName" /> 
         <xs:element ref="cust:PhoneNumber" minOccurs="1" /> 
         </xs:sequence> 
        </xs:restriction> 
        </xs:complexContent> 
    </xs:complexType> 
    

    y

    <xs:complexType name="AddressableCustomerType" > 
        <xs:complexContent> 
        <xs:extension base="cust:CustomerType"> 
         <xs:sequence> 
         <xs:element ref="cust:Address" /> 
         <xs:element ref="cust:City" /> 
         <xs:element ref="cust:State" /> 
         <xs:element ref="cust:Zip" /> 
         </xs:sequence> 
        </xs:extension> 
        </xs:complexContent> 
    </xs:complexType> 
    
  3. de referencia del tipo de base en un elemento

    <xs:element name="Customer" type="cust:CustomerType" /> 
    
  4. En su documento XML instancia, especi fy el tipo específico derivado como un atributo xsi: type

    <cust:Customer customerID="12345" xsi:type="cust:MandatoryPhoneCustomerType" > 
        <cust:FirstName>Dare</cust:FirstName> 
        <cust:LastName>Obasanjo</cust:LastName> 
        <cust:PhoneNumber>425-555-1234</cust:PhoneNumber> 
    </cust:Customer> 
    

    o:

    <cust:Customer customerID="67890" xsi:type="cust:AddressableCustomerType" > 
        <cust:FirstName>John</cust:FirstName> 
        <cust:LastName>Smith</cust:LastName> 
        <cust:Address>2001</cust:Address> 
        <cust:City>Redmond</cust:City> 
        <cust:State>WA</cust:State> 
        <cust:Zip>98052</cust:Zip> 
    </cust:Customer> 
    
Cuestiones relacionadas