BilgiTeknoloji.net    
b i l g i   t e k n o l o j i   y a z ı l ı m

Ana Sayfa

Marjinal XML Access Pratik Uygulamalar Projeler Ekonometri Dilimiz Çetrefil İletişim
 

Şemalarda Öğe ve Tip Tanımlamaları

Şemaları oluşturan en temel bileşenler öğeler ve tip tanımlarıdır. Karmaşık bir şema, genel tip tanımları oluşturularak anlaşılır bir yapıya dönüştürülebilir. Bu ayki dersimizde şemalarda öğelerin, tiplerin genel olarak nasıl tanımlandığını ve değerleri kısıtlama yöntemlerini inceliyoruz.

  • Genel bakış
  • Öğeleri tanımlamak
  • Yerleşik tipler
  • Yeni bir tip tanımlamak
  • Değerleri kısıtlamak
  • Zorunlu seçim listeleri, karakter şablonları, uzunluk ve değer aralığı sınırları oluşturmak

Bir şema belgesi temel olarak öğe tanımlarından oluşur. Her öğe için mutlaka bir tip tanımlaması mevcuttur. Bunlar şemalara özgü yerleşik tipler olabileceği gibi, yerleşik tiplerden türetebileceğimiz yeni tipler de olabilir. Sonrasında öğelerin tip bilgisini ifade yerlere yerleşik tip adı yerine türetilmiş yeni tip adları yazılarak belge düzenlenebilir.

Türetilmiş tipler şema yazınında gerçekte 'özel tip' olarak ifade edilirler ve bir özel tip üst seviyede tanımlanıp adlandırıldığında bunu farklı yerlerde kullanmak mümkün olur. Bir tip tanımlamasını adlandırmanın amacı, şablonun farklı yerlerinde geçen benzer tipler için türetme yaparak ya da doğrudan, aynı tanımlamayı birçok yerde kullanmayı sağlamaktır.

Adlandırılmış tipler bu yönleriyle türetilmiş olarak kabul edilebilirler. Bununla birlikte adlandırılmış tiplerden de türetmeler yapılarak yeni tipler üretilebilir.

Bir şema belgesi en basit şekliyle sadece öğe tanımlamalarının açıkça yazılması ile oluşabilir. Belgenin yapısal, kısa, korumalı ve hatta akıllı olmasını sağlayacak belirtimler ise belgeyi açık yazımdan uzaklaştıracak olanlardır.
 

GENEL BAKIŞ

Şemalar tam anlamıyla xml belgeleridir. Hatırlayacağınız gibi bu, Schema'nın DTD'ye göre üstünlüklerindendir.

Şemalarda kök öğe 'xsd:schema'dır (aslında sadece 'schema'). Bütün tanımlamalar kök öğe içinde yer alır. Gerekli sözlük alanları da yine kök öğeye eklenen öznitelikler yoluyla bildirilir.

Birbirine bağlı xml ve şema (xsd) belgelerinin aşağıdakine benzer şekilde olması gerektiğini kursumuzun önceki derslerinden hatırlayın.

Bir şema ile xml belgesini bağlamak için her iki belgenin başlangıcında birtakım eklemeler yapmak gerekir. XML belgesinde kök öğeye xmlns:xsi ve xsi:noNamespaceSchemaLocation özniteliklerini eklemek yeterlidir. Şema belgesinde ise kök öğe olan xsd:schema'ya xmlns:xsd ve elementFormDefault özniteliklerini eklemek lazım gelir.

[dosya.xml]

<?xml version="1.0"?>
<kök_öğe
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="dosya.xsd">
  ...
</kök_öğe>

 

[dosya.xsd]

<?xml version="1.0" encoding="ISO-8859-9"?>
<xsd:schema
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    elementFormDefault="qualified" >
  ...
</xsd:schema>

Şimdilik xml belgesindeki xsi:noNamespaceLocation ve şemadaki xmlns:xsd dışındaki belirtimleri önemsemeyin. XML belgesinde xsi:noNamespaceLocation ile şema dosyasının yolu bildirilir. Sözlük alanını bildiren xmlns şema belgesi için xsd isimli bir yerel ad alanı açmaktadır. Bu, 'xsd' ile başlayan bütün sözcüklerin, belirtilen sözlük alanına ait olduğunu (yani sözcüklerin bu sözlükte bulunduğunu) işaret eder.

Kimi yayınlarda buradaki xsd yerine xs kullanılabilmektedir. Gerçekte burası herhangi bir belirteç olabilir. Şemadaki öğelerin xsd, xs ya da başka bir şey ile başlaması, xmlns'den sonra getirilen ada bağlıdır. Belgedeki ilgili öğeler burada belirtilen ad ile başlamak zorundadır.

Sözlük alanlarında bildirilen adresler aslında gerçek internet adresleri değildir. Bu, ilgili sözlüğü geliştiren tarafından -ki 'schema'yı geliştiren W3C birliğidir- yalnızca dünyada benzersiz olması amacıyla verilmiş bir addır. Bir gelenek olarak ve de şema hakkında bilgi alınabilecek yer konusunda ipucu olabilmesi dolayısıyla sözlük alanları internet adresi olarak ayarlanmaktadır. Bu adları kullanırken büyük/küçük harf ayrımı olduğunu ve her zaman aynı şekilde yazmak gerektiğini bilmelisiniz.


ÖĞELERİ TANIMLAMAK

XML öğeleri şemalarda xsd:element ile temsil edilirler. Bu etiket, öğeleri çeşitli öznitelikler yardımıyla tanımlayabilse de bunlardan name ve type örnek kişi belgemiz için yeterlidir.

[kisi.xml]

<?xml version="1.0"?>

<KISI xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="kisi.xsd">

  <AD>Lale</AD>
  <SOYAD>Yılmaz</SOYAD>
  <MESLEK>Doktor</MESLEK>
  <SEHIR>Istanbul</SEHIR>
  <TELEFON>0216 999 99 99</TELEFON>

</KISI>

Öğeleri temsil edecek etiketleri yazmadan önce öğelerin basit ya da karmaşık olup olmadıklarına bakmak gerekir. Alt öğe içeren öğeler karmaşık öğe sayılır. Sadece değer içerdiğinde öğeyi basit tipte tanımlamak gerekir.

Tip tanımlamaları şemalarda önemli bir yere sahiptir. Herbir öğe ve özniteliğin de mutlaka bir tipi vardır. Bu tipler yerleşik olan basit tiplerden olabileceği gibi türetilmiş basit ya da karmaşık tipler olabilir.

Bir tip tanımlaması adlandırılırdığında tüm öğeler bundan faydalanabilir. Ayrıca adlandırılmış tip tanımlamaları kök öğe ile aynı seviyede bulunur. Adlandırılmamış bir tip tanımlaması ise yalnızca bir öğenin altında (içinde) yer alır ve sadece o öğenin tipini belirtir. Bunun nasıl yapıldığını aşağıda gösteriliyor.

Bu açıdan şemaların aslında öğelerden ve tip tanımlamalarından oluştuğunu söylemek yanlış olmaz.

Bu bilgiler ışığında kişi belgemizdeki kök öğenin karmaşık olduğunu anlamak zor olmayacaktır. Karmaşık öğeler xsd:element'ten sonra genelde xsd:complexType tanımlamasını gerektirir.

[kisi.xsd]

<?xml version="1.0" ?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<xsd:element name="KISI">
 <xsd:complexType>
  <xsd:sequence>
   <xsd:element name="AD" type="xsd:string" />
   <xsd:element name="SOYAD" type="xsd:string" />
   <xsd:element name="MESLEK" type="xsd:string" />
   <xsd:element name="SEHIR" type="xsd:string" />
   <xsd:element name="TELEFON" type="xsd:string" />
  </xsd:sequence>
 </xsd:complexType>
</xsd:element>

</xsd:schema>

Burada olduğu gibi xsd:sequence'yi şimdilik her xsd:complexType sonrasında bulundurunuz.

Yalnızca xsd:element ile belirtilen öğelere ve KISI öğe tanımlaması ile diğerlerinin arasındaki farka dikkat ediniz. AD, SOYAD gibi öğeler yerleşik 'xsd:string' yani basit metin türündedir. KISI öğesi için ise bu şekilde kısa öğe tanımlaması belirtilemiyor. Aslında bu öğenin tipi hemen alttaki xsd:complexType içinde kalan kısımdır.
 

YERLEŞİK TİPLER

Yerleşik olarak xsd:string dışında birkaç tip daha gelmektedir.

W3C tarafından 2.5.2001'de açıklanan önerilerdeki yerleşik tiplerin bazıları aşağıda yer alıyor.

Yerleşik temel veri tipleri:
string, boolean, decimal, float, double, duration, dateTime, time, date, gYearMonth, gYear, gMonthDay, gDay, gMonth.

Yerleşik türemiş veri tipleri:
normalizedString, integer, positiveInteger, nonPositiveInteger, negativeInteger, nonNegativeInteger, long, int, short, byte, unsignedLong, unsignedInt, unsignedShort, unsignedByte, unsignedInteger, token, language.
 

Bir tip tanımlamasının yerleşik (yani W3C'nin yayınladığı şema kurallarında belirtilmiş) olduğunu sözlük alanını belirten 'xsd:' önekinden anlayabiliriz. Bu, aynı önekin yer aldığı sözcüklerin kök öğe tanımlamasında belirtilen 'http://www.w3.org/2001/XMLSchema' ad uzayından geldiğini anlamamızı sağlar. Yerleşik tanımlılık bu ad uzayına (yani sözlük alanına) ait olmak demektir.

 
Yerleşik tipler öğe tanımlamasının type özniteliğinde 'xsd:' öneki ile birlikte yer alırlar.

  <xsd:element name="SEHIR" type="xsd:string" />

  <SEHIR>İstanbul</SEHIR>


  <xsd:element name="TARIH" type="xsd:date" />

  <TARIH>2003-02-31</TARIH>


  <xsd:element name="ADET" type="xsd:integer" />

  <ADET>123</ADET>

 

W3C birliğinin yayınladığı eski önerilerle yenileri arasında bazı farklılıklar vardır. Örneğin daha önce yıl bilgileri xsd:year ile ifade edilirken güncel öneride bu xsd:gYear şeklindedir. Güncel bazı kitaplarda ve çeşitli kaynaklarda eski önerilere ait bilgilerin yer alabildiğini (ve tabii ki buna uygun eski sözlük alanının kullanıldığını) gözönünde bulundurun.

Şemalarda yazım kuralları, özellikle büyük/küçük harflerin yazılışı önemlidir. Tip tanımlamalarındaki isimleri yazarken ilk harflerin her zaman küçük olduğuna dikkat edin. Varsa birleştirilmiş ek kelimelerin baş harfleri büyük yazılarak devam edilir. 'gMonthDay', 'complexType' gibi...

 

YENİ BİR TİP TANIMLAMAK

Şemalarda kendi tip tanımlamalarımızı yapmamız için çeşitli yollar mevcuttur. Basit bir yeni tip tanımlaması öğe tanımlamaları ile aynı seviyede (xsd:schema başlangıcının hemen altında ya da şema bitiş etiketinin hemen öncesinde) yapılır ve öğe ağacında bu yeni tip gerekli yerlerde kullanılır.

Yeni bir tip oluşturmanın benzer türdeki farklı öğeleri tanımlarken işe yaradığını söyleyebiliriz. Bununla birlikte belgenin karmaşıklığını azaltmak için tip tanımlamaları öğe içinde değil, ayrı olarak yapılabilir.

Yukarıdaki kişi belgesi için telefon bilgisini belli bir karakter şablonuna uymaya zorlayabiliriz. Bunun için tip tanımının öncelikle öğe içinde nasıl yerleştirildiğine bakın.

[kisi.xsd]

...

<xsd:element name="KISI">
 <xsd:complexType>
  <xsd:sequence>
   ...
   <xsd:element name="TELEFON">
    <xsd:simpleType>
     <xsd:restriction base="xsd:string">
      <xsd:pattern value="0[0-9][0-9][0-9] [0-9][0-9][0-9] [0-9][0-9] [0-9][0-9]" />
     </xsd:restriction>
    </xsd:simpleType>
   </xsd:element>

  </xsd:sequence>
 </xsd:complexType>
</xsd:element>

...

Yeşil ile yazılmış kısım TELEFON öğesine ait dahili tip tanımlamasıdır. Dahili tip tanımlamaları <xsd:simpleType> ya da benzer türde bir öbek içinde yapılır.

Bir kısıtlama gerektiğinde xsd:restriction kullanılıyor. Bu örnekteki base ile, kısıtlamanın temelinde xsd:string olduğu belirtiliyor. Yani değer öncelikle bu türdedir ve restriction içinde tanımlanan kurallarla da değer kısıtlanır. Burada telefon bilgisinin xsd:pattern'in value özelliğinde belirtilen karakter şablonuna uyması gerektiği ifade ediliyor.

Öğe yalnızca şu türdeki değerleri kabul edecektir: "0212 123 45 67", "0312 987 65 43" gibi. Bunların dışında parantez getirilmesi, boşluk eklenmesi ya da var olan boşlukların değiştirilmesi geçersizdir.

Öğeler genel olarak bir nesneye ait bileşenlerdir. XML veya şema öğeleri ise gerçekte xsd:element ile belirtilen öğelerdir. Bu yazıda kimi yerlerde öğe adı ile, tüm bileşenlerden herhangi biri kastedilse de yazının akışına göre bunun xsd:element öğesi olup olmadığı ayırdedilebilir.

Dahili (yerel) tip tanımlamalarında bilinmesi gereken en önemli husus bu tanımlamanın sadece ilgili öğeye ait olduğudur. Harici tanımlanıp adlandırılan tipler ise belgedeki birçok öğede kullanılabilir.

Kişiler belgemizi aşağıdaki gibi düzenlediğimizde bunun gerekliliği daha iyi anlaşılacaktır.

[kisi.xml]
...
<AD>Lale</AD>
<SOYAD>Yılmaz</SOYAD>
<MESLEK>Doktor</MESLEK>
<SEHIR>Istanbul</SEHIR>
<EVTEL>0212 999 99 99</EVTEL>
<ISTEL>0216 999 99 98</ISTEL>
<CEPTEL>0555 999 99 97</CEPTEL>
...

Bu belge için yerel tip tanımlandığında şema belgesi yeterince uzayacaktır. Adlandırılmış harici tanımlamalar çoğunlukla bu tür durumlarda devreye girer.

[kisi.xsd]

...

<xsd:schema ... >

<xsd:simpleType name="telefon_tip">
 <xsd:restriction base="xsd:string">
  <xsd:pattern value="0[0-9][0-9][0-9] [0-9][0-9][0-9] [0-9][0-9] [0-9][0-9]" />
 </xsd:restriction>
</xsd:simpleType>


<xsd:element name="KISI">
 <xsd:complexType>
  <xsd:sequence>
   ...
   <xsd:element name="EVTEL" type="telefon_tip" />
   <xsd:element name="ISTEL" type="telefon_tip" />
   <xsd:element name="CEPTEL" type="telefon_tip" />

  </xsd:sequence>
 </xsd:complexType>
</xsd:element>

</xsd:schema>

 

DEĞERLERİ KISITLAMAK

xsd:pattern'in value özelliğinde belirtilen karakter şablonları çok çeşitli olabilir. Bu yazıda tümünü belirtemesek de aşağıda açıklaması verilen, value ile kullanılabilecek farklı türdeki örnekleri inceleyebilirsiniz.

[abc] Köşeli parantez içindeki değerlerden yalnızca biri.
(abc){3} Parantez içindeki değerin 3 kez tekrarı. "abcabcabc". Buradaki parantezler adet koşulundan etkilenecek metni sınırlıyor.
abc| xyz "abc" ya da "xyz".
[0-9] 0-9 arası bir rakam.
[A-Z] A-Z arası bir harf.
\d{5} Yanyana 5 rakam. "12345"...
([a-z])* a-z arası, sınırsız sayıda.
(abc)+ Parantez içindeki metnin 1 ya da çok sayıda tekrarı.
(abc)? Parantez içindeki metnin 0 ya da 1 kez yazılması. "" veya "abc".
[A-Z]{2}-\d{3} A-Z arası 2 harf, sonra tire ve 3 rakam. "TR-247", "DK-069"...
YIL (19|20)\d{2} "YIL 1973", "YIL 2023"...

Pattern'in asıl amacı değerleri belli bir kalıba uygun şekilde kısıtlamaktır. Bu tabii ki belgenin daha kontrollü olmasını sağlar. Pattern dışında da çeşitli kısıtlama seçenekleri vardır.

Kısıtlamalar genel olarak xsd:restriction ile belirtilir. Yukarıda yapıldığı gibi kısıtlama koşulları xsd:restriction'un sınırladığı bölgede bulunur.

Kısıtlama koşulu (restriction) ile birlikte bir temel tip belirtmek gerekir. Bu base özelliği ile yapılır. Base ilgili öğenin ya da özniteliğin (sadece öğeler değil, öznitelikler için de bu şekilde kısıtlama belirtilebilir) temel alınacağı tipi belirtir. Yukarıdaki kisi.xsd dosyasında telefon_tip tanımlamasının altındaki xsd:restriction'un base özelliğinin 'xsd:string' olduğuna dikkat edin. Base özelliği xsd:element'in type özelliğinin alabileceği hemen tüm tip tanımlarını içerebilir. Yerleşik tip tanımlamaları veyahut kendi türettiğimiz tipler gibi...

Basit tipler için kısıtlama bölgesinde kullanılabilen kısıtlama türleri aşağıda inceleniyor.
 

Zorunlu Seçim Listesi Oluşturmak

Değerleri kısıtlamanın bir yolu, benzersiz öğelerden oluşmuş bir listeden seçtirmeye zorlamaktır. Bu xsd:restriction içinde iken xsd:enumeration ile yapılır. Öğe, kısıtlama bölgesinde oluşturulan birden çok enumeration ile belirtilen değerlerden yalnızca birini alabilir.

<xsd:element name="CINSIYET">
 <xsd:simpleType>
  <xsd:restriction base="xsd:string">
   <xsd:enumeration value="KADIN" />
   <xsd:enumeration value="ERKEK" />
  </xsd:restriction>
 </xsd:simpleType>
</xsd:element>

Kişi belgemize cinsiyet bilgisi eklediğimizde bunun yalnızca KADIN ya da ERKEK olmasını sağlamak için yukarıdaki gibi zorunlu seçim listesi oluşturabiliriz. Bunun dışında xsd:pattern ile de dolaylı olarak seçimlik değerler listesi oluşturulabiliyor. Kısıtlama bölgesinin içinde xsd:pattern'i aşağıdaki gibi düzenlemek bunun için yeterlidir. Pattern kullanıldığında her seçeneği dik çizgi işareti ( | ) ile ayırarak yazmak gerekir:

  <xsd:pattern value="KADIN|ERKEK" />
 

Metin ve Sayı Uzunluğunu Sınırlamak

Tip tanımlamalarında bilginin uzunluğunu kısıtlamak mümkündür. Bu, değerin uzunluğunu kesin olarak ya da olabilecek en büyük ve en küçük uzunlukları belirterek yapılabilir.

Bir değerin uzunluğunu kesin olarak belirtmek için xsd:length kısıtlama bölgesi içinde aşağıdaki gibi kullanılır.

  <xsd:length value="10" />

Bu tanım bilginin her zaman 10 karakterli olması gerektiği kuralını koyar. Olabilecek en küçük ve en büyük uzunluk ise xsd:minLength ve xsd:maxLength ile belirtilir.

  <xsd:minLength value="5" />
  <xsd:maxLength value="15" />

Öğe bu şekliyle en az 5, en çok 15 karakter uzunluğunda olabilir. Fakat bu ikisini aynı anda kullanmak zorunlu değildir. Yalnızca birinin belirtilmesi, diğeri için sınırlama olmadığı anlamına gelir.

Uzunluk kısıtlaması için xsd:length kullanıldığında xsd:minLength veya xsd:maxLength kullanmak anlamlı değildir.

Sayılardaki hane uzunluklarını sınırlamak için ise xsd:fractionDigits ve xsd:totalDigits kullanılır. FractionDigits bir sayı için ondalık kısımda yer alabilecek en çok rakam adedini belirtir. TotalDigits ise sayıdaki toplam rakam adedini sınırlar (nokta işareti adede dahil edilmez).

<xsd:restriction base="xsd:decimal">
  <xsd:totalDigits value="5" />
  <xsd:fractionDigits value="2" />
</xsd:restriction>

Yukarıdaki kısıtlamalara sahip bir sayının ondalık kısmında en çok 2, bütününde de en çok 5 hane bulunabilir.

  <SAYI>345.67</SAYI>
 

FractionDigits ve TotalDigits yerine W3C'nin daha eski önerilerinde Precision, Scale tanımlamaları yer alıyordu. Bazı kitaplarda da bu şekildedir. Tabii ilgili sözlük alanı belirtildiğinde eski tanımlamaların kullanılması yanlış değildir. Fakat bu yazıda belirtilen yeni ve güncel sözlük alanı için eskilerini kullanmak hata oluşturur. Yerine FractionDigits ve TotalDigits deyimlerini kullanmak gerekir.

Decimal tipi ondalık sayıları belirtmek için kullanılıyor. Tam sayıları belirtmek için ise integer kullanabilirsiniz. Tabii ondalık değerler olmadığında yukarıdaki kısıtlamaların kullanımı değişebilir. Yerleşik sayı tipleri için sonraki dersimizde gerekli bilgiler verilecektir.
 

Sayılarda Değer Aralığını Sınırlamak

Sayılar için öğenin alabileceği en büyük ve en küçük değerleri belirterek kısıtlama getirilebilir. Listedeki dört deyim bunun için kullanılır.

xsd:minInclusive Sayının alabileceği en küçük değer.
xsd:maxInclusive Sayının alabileceği en büyük değer.
xsd:minExclusive Sayının yaklaşabileceği en küçük değer. Belirtilen sınır değerini alamaz.
xsd:maxExclusive Sayının yaklaşabileceği en büyük değer. Belirtilen sınır değerini alamaz.

Aşağıdaki örnekte ilgili değer en çok 100 olabilirken, alabileceği en küçük değer 0'dan büyük olmak zorundadır. Integer tipinde bir tamsayı için bu değer tabii ki 1'dir.

<xsd:restriction base="xsd:integer">
  <xsd:maxInclusive value="100"/>
  <xsd:minExclusive value="0"/>
</xsd:restriction>

Burada dikkat edilmesi gereken şey, minInclusive ile minExclusive'nin, maxInclusive ile maxExclusive'nin bir arada kullanılmasının mantıklı olmadığıdır.
 

Buraya kadar, birçok alt öğe içeren öğelerin nasıl tanımlandığını incelemedik. Zaten şimdiye kadar öğrendiklerimiz ancak çok basit şema belgeleri oluşturmamıza yardımcı olabilir.

XML Şemaları, XML dünyasındaki en önemli ve uzun konulardan biridir. Gelecek ay yine ayrıntılı olarak incelemeye devam edip şemalar konusunu noktalayacağız. O zamana kadar ekteki ozgecmis.xml ve ozgecmis.xsd dosyalarını inceleyebilirsiniz.
 

Dosyalar
kisi.xml
kisi.xsd
ozgecmis.xml
ozgecmis.xsd


Serkan ŞAHİNOĞLU
(Chip Dergisi, Şubat 2003)


http://BilgiTeknoloji.net