2012-01-13 21 views
45

El siguiente post pregunta como para indicar que un elemento es el elemento raíz en un esquema XML:esquema XML: elemento raíz

Is it possible to define a root element in an XML Document using Schema?

He seguido las w3schools tutorial sobre esquemas XML, pero todavía le queda algo no es claro. Considere el esquema de ejemplo 2 desde http://www.w3schools.com/schema/schema_example.asp (se reproduce a continuación para mayor comodidad). ¿Cómo indica este código que <shiporder> es el elemento raíz? ¿No es el ejemplo que dice que todos los elementos son válidos como elementos raíz?

------------------ instancia --------------------------- -------

<?xml version="1.0" encoding="ISO-8859-1"?> 

<shiporder orderid="889923" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:noNamespaceSchemaLocation="shiporder.xsd"> 
    <orderperson>John Smith</orderperson> 
    <shipto> 
    <name>Ola Nordmann</name> 
    <address>Langgt 23</address> 
    <city>4000 Stavanger</city> 
    <country>Norway</country> 
    </shipto> 
    <item> 
    <title>Empire Burlesque</title> 
    <note>Special Edition</note> 
    <quantity>1</quantity> 
    <price>10.90</price> 
    </item> 
    <item> 
    <title>Hide your heart</title> 
    <quantity>1</xample saying that all elements are valid as root elements?quantity> 
    <price>9.90</price> 
    </item> 
</shiporder> 

----------------------- schema ------------ ------------

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

<!-- definition of simple elements --> 
<xs:element name="orderperson" type="xs:string"/> 
<xs:element name="name" type="xs:string"/> 
<xs:element name="address" type="xs:string"/> 
<xs:element name="city" type="xs:string"/> 
<xs:element name="country" type="xs:string"/> 
<xs:element name="title" type="xs:string"/> 
<xs:element name="note" type="xs:string"/> 
<xs:element name="quantity" type="xs:positiveInteger"/> 
<xs:element name="price" type="xs:decimal"/> 

<!-- definition of attributes --> 
<xs:attribute name="orderid" type="xs:string"/> 

<!-- definition of complex elements --> 
<xs:element name="shipto"> 
    <xs:complexType> 
    <xs:sequence> 
     <xs:element ref="name"/> 
     <xs:element ref="address"/> 
     <xs:element ref="city"/> 
     <xs:element ref="country"/> 
    </xs:sequence> 
    </xs:complexType> 
</xs:element> 

<xs:element name="item"> 
    <xs:complexType> 
    <xs:sequence> 
     <xs:element ref="title"/> 
     <xs:element ref="note" minOccurs="0"/> 
     <xs:element ref="quantity"/> 
     <xs:element ref="price"/> 
    </xs:sequence> 
    </xs:complexType> 
</xs:element> 

<xs:element name="shiporder"> 
    <xs:complexType> 
    <xs:sequence> 
     <xs:element ref="orderperson"/> 
     <xs:element ref="shipto"/> 
     <xs:element ref="item" maxOccurs="unbounded"/> 
    </xs:sequence> 
    <xs:attribute ref="orderid" use="required"/> 
    </xs:complexType> 
</xs:element> 

</xs:schema> 

Desde mi punto de vista un esquema XML debe hacer dos cosas:

  1. def ine lo que puede ocurrir dentro de cada nodo
  2. definen donde cada nodo puede ser colocado

Y parece que el ejemplo falla en el # 2. ¿Alguna sugerencia?

+0

Estaba siguiendo los consejos del enlace. ¿Tendría razón al afirmar que con el Esquema XML anterior cualquiera de los elementos definidos puede ocurrir como el elemento raíz del documento? Gracias. – johngoche9999

+0

Gracias, Brian Driscoll, por su explicación detallada de exactamente lo que el interlocutor está haciendo mal y cómo puede solucionarlo. – fool4jesus

Respuesta

43

Por lo que sé, cualquier globalmente elemento definido se puede utilizar como elemento raíz, y XML Schema no tiene una noción para especificar qué elemento raíz se supone que debe ser.

Sin embargo, puede solucionar esto diseñando bien su Esquema XML, de modo que solo haya un elemento definido globalmente, entonces solo este elemento es válido como elemento raíz.

Un ejemplo de esto se puede encontrar en W3Schools (partida Uso de tipos con nombre) Este ejemplo sólo tiene un elemento definido a nivel mundial, y por lo tanto sólo un posible elemento raíz.

+0

Gracias, creo que el ejemplo 3 del sitio w3schools es, de hecho, quizás la mejor manera de abordar el problema, es decir, definir primero todos los tipos simples y complejos y luego desginar un solo elemento raíz al tener un único elemento definido globalmente. – johngoche9999

+2

El enlace está muerto. – Xenos

+0

La Máquina WayBack lo tiene: https://web.archive.org/web/20140201170920/http://www.w3schools.com/schema/schema_example.asp –

14

sí, tienes razón. xsd debería ser:

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

<!-- definition of attributes --> 
<xs:attribute name="orderid" type="xs:string"/> 

<!-- definition of complex elements --> 
<xs:complexType name="shiptoType"> 
    <xs:sequence> 
    <xs:element name="name" type="xs:string" /> 
    <xs:element name="address" type="xs:string" /> 
    <xs:element name="city" type="xs:string" /> 
    <xs:element name="country" type="xs:string" /> 
    </xs:sequence> 
</xs:complexType> 

<xs:complexType name="itemType"> 
    <xs:sequence> 
    <xs:element name="title" type="xs:string" /> 
    <xs:element name="note" minOccurs="0" type="xs:string" /> 
    <xs:element name="quantity" type="xs:string" /> 
    <xs:element name="price" type="xs:string" /> 
    </xs:sequence> 
</xs:complexType> 

<xs:element name="shiporder"> 
    <xs:complexType> 
    <xs:sequence> 
     <xs:element name="orderperson" type="xs:string" /> 
     <xs:element name="shipto" type="shiptoType"/> 
     <xs:element name="item" maxOccurs="unbounded" type="itemType"/> 
    </xs:sequence> 
    <xs:attribute ref="orderid" use="required"/> 
    </xs:complexType> 
</xs:element> 

</xs:schema> 

como ves, ahora sólo hay un xs:element, y que es el único que puede ser un elemento raíz válida :)

0

¿Cómo este código indica que es el elemento raíz?

John, Ese esquema acaba de definir todos los elementos y cualquiera de ellos se puede elegir como un elemento raíz. Si intenta generar un xml de muestra desde cualquier herramienta como Altova XML Spy o su tipo, podrá elegir un elemento para ser el elemento raíz.

De modo que cualquiera de esos elementos puede ser la raíz.

Para evitar la ambigüedad, utilice un elemento definido globalmente.

19

No todos están de acuerdo, pero el hecho de que XML Schema no pueda especificar un elemento raíz es por diseño. La idea es que si un <invoice> es válido cuando es lo único en un documento, entonces es igualmente válido si está contenido en otra cosa. La idea es que el contenido sea reutilizable y no se le debe permitir evitar que alguien use contenido válido como parte de algo más grande.

(El hecho de que ID y IDREF están en el ámbito de un documento en vez va en contra de esta política;. Pero entonces el lenguaje fue diseñado por un comité bastante grande)

+5

Y ID e IDREF fueron diseñados por un comité completamente diferente, en una organización diferente, veinte años antes. –

+0

@Michael Así que la idea aquí sería generar todos los elementos en un esquema, y ​​si es vital permitir que solo uno de ellos sea elemento raíz, para crear otro esquema, incluya el que define los elementos, y tenga ese ¿nuevo define solo uno de ellos como el elemento raíz, que contiene otros como la restricción se ajusta? – starturtle

+0

No, eso es una inferencia incorrecta. Si tiene alguna pregunta, publique una nueva pregunta, no un comentario en una publicación anterior. –

1

La desventaja de una gran cantidad de elementos globales es que todos pudieran ser utilizado como elementos raíz para documentos. La ventaja es entonces que puede usar el elemento cuando defina nuevos tipos que garantizarán que el espacio de nombres de los elementos secundarios coincidan con los del tipo padre.

He cambiado de pensar que solo debería haber un elemento global para que todos los tipos complejos tengan un elemento global.

0

Según el ejemplo que proporcionó, es posible encontrar el único elemento raíz.

Puede obtener una lista de elementos globales, luego obtener una lista de elementos anidados que hace referencia en complexType bajo el nodo xs: secuencia, por lo tanto, el elemento raíz es el de la lista de elementos globales pero no de elementos anidados.

He hecho esto usando la clase XmlSchemaSet en .NET. no

static IEnumerable<XmlSchemaElement> GetNestedTypes(this XmlSchemaGroupBase xmlSchemaGroupBase) 
{ 
    if (xmlSchemaGroupBase != null) 
    { 
     foreach (var xmlSchemaObject in xmlSchemaGroupBase.Items) 
     { 
      var element = xmlSchemaObject as XmlSchemaElement; 
      if (element != null) 
       yield return element; 
      else 
      { 
       var group = xmlSchemaObject as XmlSchemaGroupBase; 
       if (group != null) 
        foreach (var item in group.GetNestedTypes()) 
         yield return item; 
      } 
     } 
    } 
} 

pero todavía tiene problemas para el xsd general, cuando se utiliza este enfoque: Aquí está el fragmento de código:

var localSchema = schemaSet.Schemas().OfType<XmlSchema>().Where(x => !x.SourceUri.StartsWith("http")).ToList(); 

var globalComplexTypes = localSchema 
.SelectMany(x => x.Elements.Values.OfType<XmlSchemaElement>()) 
.Where(x => x.ElementSchemaType is XmlSchemaComplexType) 
.ToList(); 

var nestedTypes = globalComplexTypes.Select(x => x.ElementSchemaType) 
.OfType<XmlSchemaComplexType>() 
.Select(x => x.ContentTypeParticle) 
.OfType<XmlSchemaGroupBase>() 
.SelectMany(x => x.GetNestedTypes()) 
.ToList(); 

var rootElement= globalComplexTypes.Single(x => !nestedTypes.Select(y => y.ElementSchemaType.QualifiedName).Contains(x.SchemaTypeName)); 

Los GetNestedTypes método de extensión. Por ejemplo, en DotNetConfig.xsd que el uso de Visual Studio para el archivo de configuración, el elemento raíz es definir de la siguiente manera:

<xs:element name="configuration"> 
    <xs:complexType> 
     <xs:choice minOccurs="0" maxOccurs="unbounded"> 
     <xs:any namespace="##any" processContents="lax" /> 
     </xs:choice> 
     <xs:anyAttribute namespace="http://schemas.microsoft.com/XML-Document-Transform" processContents="strict"/> 
    </xs:complexType> 
    </xs:element> 

que no te has encontrado una solución completa para hacer frente a todo tipo de esquemas todavía. Continuaré por eso.

Cuestiones relacionadas