XML/Relazioni ricorsive

< XML
Indice del libro

Obiettivi di apprendimento

  • Comprendere il concetto di relazione ricorsiva
  • Creare uno schema per una relazione ricorsiva uno-a-uno
  • Creare uno schema per una relazione ricorsiva uno-a-molti
  • Creare uno schema per una relazione ricorsiva molti-a-molti
  • Definire un identificatore univoco in uno schema
  • Creare una relazione con chiave primaria/chiave esterna

Le relazioni ricorsive sono un concetto interessante e più complesso rispetto alle relazioni che hai visto nei capitoli precedenti. Una relazione ricorsiva si verifica quando esiste una relazione tra un'entità e se stessa. Ad esempio, una relazione ricorsiva uno-a-molti si verifica quando un dipendente è il responsabile di altri dipendenti. L'entità dipendente è correlata a se stessa e vi è una relazione uno-a-molti tra un dipendente (il manager) e molti altri dipendenti (le persone che fanno riferimento al manager). A causa della natura più complessa di queste relazioni, avremo bisogno di metodi leggermente più complessi per mapparli in uno schema e visualizzarli in un foglio di stile.

La relazione uno-a-uno ricorsiva

modifica

Continuando con il modello della guida turistica, svilupperemo uno schema che mostra le città che hanno ospitato le Olimpiadi e la precedente città ospitante. Dal momento che l'host precedente è un'altra città e solo una città può essere l'host precedente questa è una relazione ricorsiva uno a uno.

 

host.xsd (schema XML per un modello ricorsivo uno-a-uno)

modifica
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
attributeFormDefault="unqualified">

<xsd:element name="cities">
  <xsd:complexType>
    <xsd:sequence>
      <xsd:element name="city" type="cityType" maxOccurs="unbounded"/>
    </xsd:sequence>
  </xsd:complexType>
</xsd:element>

<xsd:complexType name="cityType">
  <xsd:sequence>
    <xsd:element name="cityID" type="xsd:ID"/>
     <xsd:element name="cityName" type="xsd:string"/>
     <xsd:element name="cityCountry" type="xsd:string"/>
     <xsd:element name="cityPop" type="xsd:integer"/>
     <xsd:element name="cityHostYr" type="xsd:integer"/>
     <xsd:element name="cityPreviousHost" type="xsd:IDREF" minOccurs="0" maxOccurs="1"/>
  </xsd:sequence>
</xsd:complexType>
</xsd:schema>

host.xml (documento XML per un modello ricorsivo uno-a-uno)

modifica
<?xml version="1.0" encoding="UTF-8"?>
<cities xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation='host.xsd'>
  <city>
    <cityID>c1</cityID>
    <cityName>Atlanta</cityName>
    <cityCountry>USA</cityCountry>
    <cityPop>4000000</cityPop>
    <cityHostYr>1996</cityHostYr>    
  </city>
  <city>
    <cityID>c2</cityID>
    <cityName>Sydney</cityName>
    <cityCountry>Australia</cityCountry>
    <cityPop>4000000</cityPop>
    <cityHostYr>2000</cityHostYr>  
    <cityPreviousHost>c1</cityPreviousHost>   
  </city>
  <city>
    <cityID>c3</cityID>
    <cityName>Atene</cityName>
    <cityCountry>Grecia</cityCountry>
    <cityPop>3500000</cityPop>
    <cityHostYr>2004</cityHostYr>  
    <cityPreviousHost>c2</cityPreviousHost>   
  </city>
</cities>

La relazione ricorsiva uno-a-molti

modifica

Un ipotetico team sportivo è diviso in squadre, ognuna delle quali ha un capitano. Ogni persona della squadra è un giocatore, indipendentemente dal fatto che sia un capitano di squadra. Poiché un capitano di squadra è un giocatore, questa situazione incontra la definizione di una relazione ricorsiva: un capitano di squadra è anche un giocatore e ha una relazione uno-a-molti con gli altri giocatori. Si tratta di una relazione ricorsiva uno-a-molti perché un capitano ha molti giocatori sotto di sé. L'esempio seguente mostra come come modellare la relazione.

team.xsd (schema XML per un modello ricorsivo uno-a-molti)

modifica
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified">
<xsd:element name="team">
  <xsd:complexType>
    <xsd:sequence>
      <xsd:element name="player" type="playerType" maxOccurs="unbounded"/>
    </xsd:sequence>
  </xsd:complexType>
</xsd:element>
  <xsd:complexType name="playerType">
    <xsd:sequence>
      <xsd:element name="playerID" type="xsd:ID"/>
      <xsd:element name="playerName" type="xsd:string"/>
      <xsd:element name="playerCap" type="playerC" minOccurs="0" maxOccurs="unbounded"/>
    </xsd:sequence>
  </xsd:complexType>
  <xsd:complexType name="playerC">
    <xsd:sequence>
      <xsd:element name="memberOf" type="xsd:IDREF"/>
    </xsd:sequence>
  </xsd:complexType>
</xsd:schema>

team.xml (documento XML per un modello ricorsivo uno-a-molti)

modifica
<?xml version="1.0" encoding="UTF-8"?>
<team xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:noNamespaceSchemaLocation='Recursive1toMSchema.xsd'>
<player>
   <playerID>c1</playerID>
   <playerName>Tommy Jones</playerName>
   <playerCap>
      <memberof>c3</memberof>
   </playerCap>
</player>
<player>
   <playerID>c2</playerID>
   <playerName>Eddie Thomas</playerName>
   <playerCap>
      <memberof>c3</memberof>
   </playerCap>
</player>
<player>
   <playerID>c3</playerID>
   <playerName>Sean McCombs</playerName>
</player>
<player>
   <playerID>c4</playerID>
   <playerName>Patrick O’Shea</playerName>
   <playerCap>
      <memberof>c3</memberof>
    </playerCap>
</player>
</team>

Struttura ricorsiva naturale uno-a-molti

modifica

Un approccio più naturale per la maggior parte delle relazioni ricorsive uno-a-molti è quello di utilizzare la natura gerarchica di XML per rappresentare direttamente la gerarchia. Considerare le posizioni:

<?xml version="1.0" encoding="UTF-8"?>
<location type="country">
  <name>USA</name>
  <sub-locations>
    <location type="state">
      <name>Ohio</name>
      <sub-locations>
        <location type="city"><name>Akron</name></location>
        <location type="city"><name>Columbus</name></location>
      </sub-location>
    </location>
  </sub-locations>
</location>

La relazione ricorsiva molti-a-molti

modifica

Ti senti già ferrato sulle relazioni ricorsive? Beh, c'è ancora la terza e ultima relazione da aggiungere al tuo bagaglio di conoscenze: il rapporto ricorsivo molti-a-molti. Un esempio comune di una relazione ricorsiva molti-a-molti è quando un elemento può essere composto da molti elementi dello stesso tipo di dati, e ciascuno di questi sotto-elementi può appartenere ad un altro elemento padre dello stesso tipo di dati. Sembra confuso? Vediamo l'esempio di un prodotto che può consistere di un singolo elemento o di più elementi (ad esempio, un prodotto confezionato). L'esempio che segue descrive i prodotti turistici che possono essere confezionati insieme per creare un nuovo prodotto.

product.xsd (schema XML per un modello ricorsivo molti-a-molti)

modifica
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified">
    <xsd:element name="products">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="product" type="prodType" maxOccurs="unbounded"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
    <xsd:complexType name="prodType">
        <xsd:sequence>
            <xsd:element name="prodID" type="xsd:ID"/>
            <xsd:element name="prodName" type="xsd:string"/>
            <xsd:element name="prodCost" type="xsd:decimal" minOccurs="0"/>
            <xsd:element name="prodPrice" type="xsd:decimal"/>
            <xsd:element name="components" type="componentsType" minOccurs="0" maxOccurs="1"/>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:complexType name="componentsType">
        <xsd:sequence>
            <xsd:element name="component" type="xsd:IDREF"/>
            <xsd:element name="componentqty" type="xsd:integer"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:schema>

product.xml (documento XML per un modello ricorsivo molti-a-molti)

modifica
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="product.xsl"?>
<products xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="product.xsd">
    <product>
        <prodID>p1000</prodID>
        <prodName>Kit per la fotografia di animali</prodName>
        <prodPrice>725</prodPrice>
        <components>
            <component>p101</component>
            <componentqty>1</componentqty>
        </components>
    </product>
    <product>
        <prodID>p101</prodID>
        <prodName>Custodia per fotocamera</prodName>
        <prodCost>150</prodCost>
        <prodPrice>300</prodPrice>
    </product>
</products>