logo
XML-->XML
Velkommen > Eksempler > Olympiade >XML-->XML
../../common/gfx/prev.gif ../../common/gfx/home.gif ../../common/gfx/next.gif

Transformasjon fra XML til XML

Hva:
Demonstrerer noen enkle XML -> XML transformasjoner

I denne modulen skal vi lage to forskjellige transformasjoner med utgangspunkt i våre olympiske data. Vi skal ekstrahere 100m resultatene og vi skal lage en restruktureing av fila til en flatere struktur.

.

Bare 100m

Vi ønsker å ekstrahere 100m resultatene og lage en ny xml-fil som er organisert på en litt annen måte. En skisse:

  <Sprint-100m>
   <OlympicGame place="Atlanta -  1996">
      ... athlets som før men bare fra 100m...
   </OlympicGame>
   <OlympicGame place="Barcelona -  1992">
      ... athlets som før men bare fra 100m ...
   </OlympicGame>
  </Sprint-100m>
  

Vi ønsker altså:

  • Introdusere en ny dokumenttype: Sprint-100m
  • Endre, forenkle, attributtliste til elementet:OlympicGame
  • Ekstrahere bare 100m resultatene

Dokumenttypen vil vi ha slik:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!ELEMENT OlympicGame (athlet+)>
<!ATTLIST OlympicGame
    place CDATA #REQUIRED
>
<!ELEMENT Sprint-100m (OlympicGame+)>
<!ELEMENT athlet (name, nation, result)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT nation (#PCDATA)>
<!ELEMENT result (#PCDATA)>

Skjematisk gjør vi følgende:
ol2xml/xmlxml.gif

Selve transformasjonsjobben, T, utføres i et program. For dette eksperimentet kan vi bruke XMLSpy, eller vi kan bruke en nettleser som transformaerer direkte.

Vi skriver en enkel transformasjonsfil, en olymp3.xsl, som beskriver denne transformasjonen:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet  version="1.0"  
                 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml"  
              doctype-system="olymp100.dtd" 
              encoding="ISO-8859-1" />

<xsl:template match="/">
<Sprint-100m>
<xsl:for-each select="IOC/OlympicGame">
   <OlympicGame>
      <xsl:attribute name="place">
       <xsl:value-of select="@place"/>
      <xsl:text> -  </xsl:text>
       <xsl:value-of select="@year"/>
      </xsl:attribute>
      <xsl:for-each select="event">
            <xsl:if test="@track[.='100m']"> 
         <xsl:for-each select="athlet">
            <xsl:copy-of select="."/>
         </xsl:for-each>
         </xsl:if>
      </xsl:for-each>
   </OlympicGame>
</xsl:for-each>
</Sprint-100m>
</xsl:template>
</xsl:stylesheet>

Det er mange måter å gjøre dette på. Her er valgt en eksplisitt form som ligner det resonnementet vi ville bruke i et tradisjonelt språk.

La oss først se litt på linjene i headingen:

  1 <?xml version="1.0" encoding="ISO-8859-1"?>
  2 <xsl:stylesheet  version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  3 <xsl:output method="xml" omit-xml-declaration="no"
    doctype-system="olymp100.dtd"/>
  

Linje 1 forteller oss at xsl-fila faktisk er en xml-fil ! Linje 2 forteller at vi skal lage et stilsett med versjon 1 av xsl og vi definerer et namespace. Linje 3 sier at vi skal produsere xml (alternativene er html eller text), at vi vil ha xml-angivelse i resultatet, og endelig at det vi produserer skal være et dokument av typen olymp100.dtd. Vi skal altså kunne validere resultatet av transformasjonen mot en dtd-fil som er annerledes enn utgngspunktet.

Så ser vi på innmaten av transformasjonen, templaten:

4 <xsl:template match="/">
5 <Sprint-100m>
6 <xsl:for-each select="IOC/OlympicGame">
7  <OlympicGame>
8     <xsl:attribute name="place">
9      <xsl:value-of select="@place"/>
10    <xsl:text> -  </xsl:text>
11     <xsl:value-of select="@year"/>
12    </xsl:attribute>
13    <xsl:for-each select="event">
14          <xsl:if test="@track[.='100m']">
15       <xsl:for-each select="athlet">
16          <xsl:copy-of select="."/>
17       </xsl:for-each>
18       </xsl:if>
19    </xsl:for-each>
20 </OlympicGame>
21 </xsl:for-each>
22 </Sprint-100m>
23 </xsl:template>

Linje 4 - 23 beskriver en template som skal ta fatt i ytterste element i kildedokumnetet, match="/">. Linjene 5 og 22 produserer start og slutt tag for rotelmentet i det dokumentet vi skal produsere. Linjene 6 og 21 avgrenser en løkke over alle olympiske leker og linje 7 og 20 produserer tager for hver olympiade.

Linje 8 tar fatt i attributten place til elementet og linjene 9 - 12 produserer den nye attributten på grunnlag av de to gamle, place og year. I linje 13 starter en løkke over alle øverlser, events, og for de som tilsvarer den geneskapen at deres track-attributt er lik 100m kopierer vi alle løperne, athlets.

Vi kopler xsl-fila til xml-fila ved følgende linje i toppen på xml-fila, all_results3.xml:

  <?xml version="1.0" encoding="ISO-8859-1"?>
  <!DOCTYPE IOC SYSTEM "olymp.dtd" >
  <?xml-stylesheet type="text/xsl" href="olymp3.xsl"?>
  <IOC>
  ...

  

Vi oppnår nøyaktig samme resultat med transformasjonen nendenfor. Denne er skrevet med 3 templates og er et bedre alternativ.

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"  
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml"  
              doctype-system="olymp100.dtd" 
              encoding="ISO-8859-1" 
              indent="yes"/>

<xsl:template match="/">
    <Sprint-100m>
    <xsl:apply-templates select="IOC/OlympicGame"/>    
    </Sprint-100m>
</xsl:template>

<xsl:template match="//OlympicGame">
 <OlympicGame>
      <xsl:attribute name="place">
       <xsl:value-of select="@place"/>
      <xsl:text> -  </xsl:text>
       <xsl:value-of select="@year"/>
      </xsl:attribute>
      <xsl:apply-templates select="event[@track='100m']"/>
   </OlympicGame>
</xsl:template>

<xsl:template match="//athlet">
            <xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
.

Reorganisering

her tar vi for oss materialet og reorganiserer den slik:

olymp-reorg

Det betyr at vi skal gå fra:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!ELEMENT IOC (OlympicGame+)>
<!ELEMENT OlympicGame (event+)>
<!ATTLIST OlympicGame
    place CDATA #REQUIRED
    year CDATA #REQUIRED
>
<!ELEMENT athlet (name, nation, result)>
<!ELEMENT event (athlet+)>
<!ATTLIST event
    track (100m | 200m | 400m) #REQUIRED
>
<!ELEMENT name (#PCDATA)>
<!ELEMENT nation (#PCDATA)>
<!ELEMENT result (#PCDATA)>

til

<?xml version="1.0" encoding="ISO-8859-1"?>
<!ELEMENT IOC (event+)>
<!ELEMENT athlet (name, nation, result)>
<!ELEMENT event (athlet+)>
<!ATTLIST event
    track (100m | 200m | 400m) #REQUIRED
    place (Atlanta | Barcelona | Sidney | Athens) #REQUIRED
    year (1992 | 1996 | 2000 | 2004) #REQUIRED
>
<!ELEMENT name (#PCDATA)>
<!ELEMENT nation (#PCDATA)>
<!ELEMENT result (#PCDATA)>

Transformasjonsfila er i sin helhet slik:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet  version="1.0"  
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" 
    doctype-system="olympreorg.dtd" encoding="ISO-8859-1"/>

<xsl:template match="/">
<IOC>
   <xsl:apply-templates select="/IOC/OlympicGame/event"/>
</IOC>
</xsl:template>

<xsl:template match="event">
    <xsl:element name="event">
      <xsl:attribute name="track">
         <xsl:value-of select="@track"/>
      </xsl:attribute>
      <xsl:attribute name="place">
         <xsl:value-of select="ancestor::OlympicGame/@place"/>
      </xsl:attribute>
      <xsl:attribute name="year">
         <xsl:value-of select="ancestor::OlympicGame/@year"/>
      </xsl:attribute>
      <xsl:apply-templates select="athlet"/>
   </xsl:element>
</xsl:template>

<xsl:template match="athlet">
 <xsl:copy-of select="."/>
</xsl:template>

</xsl:stylesheet>

Referanser og eksempler:

Aktuelle filer i eksempelet er siterte i teksten:

Produksjon, kontroll og vedlikehold:
Børre Stenseth, mai 2006

Markup og web fra Høgskolen i Østfold: http://www.ia.hiof.no/~borres/ml/

../../common/gfx/prev.gif ../../common/gfx/home.gif ../../common/gfx/next.gif
skjema popup

Valid XHTML 1.0 Strict
popup card
Bygget med WXT