2012-01-13 16 views
45

Il seguente post chiede come per indicare che un elemento è l'elemento radice in uno schema XML:XML Schema: elemento radice

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

Ho seguito le w3schools tutorial su XML Schema, ma qualcosa è ancora non chiaro. Considerare lo schema 2 di esempio da http://www.w3schools.com/schema/schema_example.asp (riprodotto di seguito per comodità). In che modo questo codice indica che <shiporder> è l'elemento radice? L'esempio non dice che tutti gli elementi sono validi come elementi radice?

------------------ istanza --------------------------- -------

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

Dal mio punto di vista uno schema XML dovrebbe fare due cose:

  1. def ine ciò che può avvenire all'interno di ciascun nodo
  2. definiscono dove ogni nodo può essere collocato

E sembra l'esempio non riesce a # 2. Qualche suggerimento?

+0

Stavo seguendo il consiglio dal collegamento. Sarei corretto affermando che con lo schema XML sopra qualsiasi elemento definito può verificarsi come elemento principale del documento? Grazie. – johngoche9999

+0

Grazie, Brian Driscoll, per la tua spiegazione approfondita di esattamente ciò che l'interrogante sta facendo male e come può risolverlo. – fool4jesus

risposta

43

Per quanto ne so, qualsiasi elemento definito a livello globale può essere utilizzato come elemento radice e lo schema XML non ha una nozione per specificare cosa si suppone che l'elemento radice sia.

È tuttavia possibile aggirare il problema progettando bene lo schema XML, in modo che vi sia un solo elemento definito globalmente, quindi solo questo elemento è valido come elemento radice.

Un esempio di questo può essere trovato a W3Schools (voce Uso denominati Tipi) Questo esempio ha un solo elemento globalmente definita, e quindi solo un elemento radice possibile.

+0

Grazie, penso che l'esempio 3 del sito w3schools sia in effetti il ​​modo migliore per affrontare il problema, cioè definire prima tutti i tipi semplici e complessi e quindi desginare un singolo elemento radice avendo un singolo elemento globalmente definito. – johngoche9999

+2

Il link è morto. – Xenos

+0

La macchina WayBack ce l'ha: https://web.archive.org/web/20140201170920/http://www.w3schools.com/schema/schema_example.asp –

14

sì, hai ragione. il xsd dovrebbe essere:

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

come si vede, ora c'è solo una xs:element, e che è l'unico che può essere un elemento radice valida :)

0

Come funziona questo codice indica che è l'elemento principale?

John, Questo schema ha appena definito tutti gli elementi e ognuno di questi può essere scelto come elemento radice. Se provi a generare un xml di esempio da qualsiasi strumento come Altova XML Spy o il suo tipo, potrai scegliere un elemento come elemento radice.

Quindi uno di questi elementi può essere la radice.

Per evitare ambiguità, utilizzare un elemento definito globalmente.

19

Non tutti sono d'accordo, ma il fatto che XML Schema non possa specificare un elemento radice è di progettazione. Il pensiero è che se uno <invoice> è valido quando è l'unica cosa in un documento, allora è ugualmente valido se è contenuto in qualcos'altro. L'idea è che il contenuto debba essere riusabile e non si dovrebbe impedire a qualcuno che utilizza contenuti validi come parte di qualcosa di più grande.

(Il fatto che ID e IDREF sono scope a un documento piuttosto va contro questa politica,. Ma poi la lingua creata da una piuttosto grande comitato)

+5

E ID e IDREF sono stati progettati da un comitato completamente diverso, in un'organizzazione diversa, vent'anni prima. –

+0

@ Michael Quindi l'idea sarebbe quella di generare tutti gli elementi in uno schema, e se è di vitale importanza che solo uno di essi sia l'elemento radice, per creare un altro schema, includere quello che definisce gli elementi, e avere quello quello nuovo definisce solo uno di essi come elemento radice, contenendo gli altri come la restrizione si adatta? – starturtle

+0

No, è un'inferenza errata. Se hai una domanda, per favore pubblica una nuova domanda, non un commento su un vecchio post. –

1

Lo svantaggio di un sacco di elementi globali è che potevano tutto essere usato come elementi di root per i documenti. Il vantaggio è quindi che è possibile utilizzare l'elemento quando si definiscono nuovi tipi che assicureranno che lo spazio dei nomi degli elementi figlio corrisponda a quelli del tipo genitore.

Sono cambiato dal pensare che ci dovrebbe essere solo un elemento globale a cui tutti i tipi complessi dovrebbero avere un elemento globale.

0

In base all'esempio fornito, è possibile trovare l'unico elemento radice.

È possibile ottenere un elenco di elementi globali, quindi ottenere un elenco di elementi nidificati che fanno riferimento a complexType sotto il nodo xs: sequence, quindi l'elemento root è quello nell'elenco di elementi globali ma non nell'elenco di elementi nidificati.

Ho eseguito questa operazione utilizzando la classe XmlSchemaSet in .NET. Ecco il frammento di codice:

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

l'estensione del metodo GetNestedTypes:

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

Ma ci ha ancora problemi per l'XSD generale quando si utilizza questo approccio. Per esempio, in DotNetConfig.xsd che utilizzare Visual Studio per file di configurazione, l'elemento radice è definisco come di seguito:

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

ho Havn't trovato una soluzione completa per affrontare tutti i tipi di schemi ancora. Continuerà per questo.