xsd - vacio - Esquema XML para elementos con el mismo nombre pero con una subestructura diferente segĂșn el contexto
xsd extension (2)
Sí, XSD puede manejar esto. Genere este esquema desde Visual Studio 2008 (mucho más rápido que hacerlo a mano) y hará 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>
Intento definir un esquema para los documentos XML que recibo.
Los documentos se ven así:
<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>
Intenté XmlSpy y xsd.exe desde .NET 2.0. Ambas crearon definiciones de esquema que permiten a continuación <group>
cualquier cantidad de <item>
y <customer>
. Pero lo que estoy buscando debería restringir <group>
below <items>
a <item>
elementos, y <group>
below <data>
a <customer>
elements.
¿Es esto algo que el esquema xml no es capaz en absoluto?
Los puntos clave (consulte Polimorfismo de tiempo de ejecución del esquema XML mediante xsi: tipo y Tipos abstractos para contexto / ubicación / uso completos y correctos) son:
Cree un tipo de base con (abstract = "true" para evitar que se use directamente)
Nota: el atributo ref reemplaza el atributo de nombre para los 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>
Cree dos o más tipos derivados extendiendo o restringiendo el tipo de 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>
Referenciar el tipo de base en un elemento
<xs:element name="Customer" type="cust:CustomerType" />
En el documento XML de instancia, especifique el tipo derivado específico 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>