XML

XML (ang. Extensible Markup Language, w wolnym tłumaczeniu Rozszerzalny Język Znaczników) – uniwersalny język formalny, przeznaczony do reprezentowania różnych danych w strukturalizowany sposób.

XML jest niezależny od platformy, co umożliwia łatwą wymianę dokumentów pomiędzy heterogenicznymi (różnymi) systemami i znacząco przyczyniło się do popularności tego języka w dobie Internetu. XML jest standardem rekomendowanym oraz specyfikowanym przez organizację W3C.

Przygodę z językiem XML zacząłem jak wiele innych - podczas moich studiów magisterskich na Akademii Górniczo-Hutniczej w Krakowie.

Diagramy XTT

Pierwszym, "poważnym" projektem związanym z tym językiem było stworzenie graficznej interpretacji diagramów XTT (ang. eXtended Tabular Trees) w ramach przedmiotu Metody Inżynierii Wiedzy na kierunku Automatyka i Robotyka na wydziale elektrycznym.

Zapis diagramu XTT w języku XML wygląda tak:

<?xml version="1.0"?>

<XTT.Diagram>
 <tables>
 <table tableName="today" x="50" y="50">
  <row>
   <condition name="day" type="IN" w="200" ><value>mon</value><value>tue</value>
     <value>wed</value><value>thu</value><value>fri</value></condition>
   <assert name="today" type="EQ" w="75" ><value>work</value></assert>
   <retract name="today" type="ANY" w="50" />
  </row>
  <row>
   <condition name="day" type="IN" w="200" ><value>sat</value><value>sun</value></condition>
   <assert name="today" type="EQ" w="75" ><value>week</value></assert>
   <retract name="today" type="ANY" w="50" />
  </row>
 </table>
 <table tableName="operation" x="500" y="150">
  <row>
   <condition name="today" type="EQ" w="75" ><value>work</value></condition>
   <condition name="time" type="BIN" w="100" ><value>9</value><value>17</value></condition>
   <assert name="oper" type="EQ" w="50" ><value>1</value></assert>
   <retract name="oper" type="ANY" w="50" />
  </row>
  <row>
   <condition name="today" type="EQ" w="75" ><value>work</value></condition>
   <condition name="time" type="LT" w="100" ><value>9</value></condition>
   <assert name="oper" type="EQ" w="50" ><value>0</value></assert>
   <retract name="oper" type="ANY" w="50" />
  </row>
  <row>
   <condition name="today" type="EQ" w="75" ><value>work</value></condition>
   <condition name="time" type="GT" w="100" ><value>17</value></condition>
   <assert name="oper" type="EQ" w="50" ><value>0</value></assert>
   <retract name="oper" type="ANY" w="50" />
  </row>
  <row>
   <condition name="today" type="EQ" w="75" ><value>work</value></condition>
   <condition name="time" type="ANY" w="100" ></condition>
   <assert name="oper" type="EQ" w="50" ><value>0</value></assert>
   <retract name="oper" type="ANY" w="50" />
  </row>
 </table>
 <table tableName="example" x="50" y="300">
  <row>
   <condition name="today" type="EQ" w="75" ><value>work</value></condition>
   <condition name="time" type="LIN" w="150" ><value>9</value><value>17</value></condition>
   <assert name="today" type="EQ" w="100" ><value>1</value></assert>
   <retract name="oper" type="ANY" w="50" />
  </row>
  <row>
   <condition name="today" type="EQ" w="75" ><value>work</value></condition>
   <condition name="time" type="LT" w="150" ><value>9</value></condition>
   <assert name="today" type="EQ" w="100" ><value>0</value></assert>
   <retract name="oper" type="ANY" w="50" />
  </row>
  <row>
   <condition name="today" type="EQ" w="75" ><value>work</value></condition>
   <condition name="time" type="GE" w="150" ><value>17</value></condition>
   <assert name="today" type="PRC" w="100" ><value>doProc</value><value>procedure body</value></assert>
   <retract name="oper" type="ANY" w="50" />
  </row>
  <row>
   <condition name="today" type="NEQ" w="75" ><value>work</value></condition>
   <condition name="time" type="EQV" w="150" ><value>9</value><value>10</value>
     <value>12</value><value>15</value></condition>
   <assert name="today" type="EQ" w="100" ><value>0.0</value></assert>
   <retract name="oper" type="ANY" w="50" />
  </row>
 </table>
 </tables>
 <connections>
  <connection>
   <from tableName="today" rowNr="1" />
   <to tableName="operation" rowNr="1" />
   <breakUp>100</breakUp>
  </connection>
  <connection>
   <from tableName="today" rowNr="2" />
   <to tableName="operation" rowNr="3" />
   <breakUp>70</breakUp>
  </connection>
  <connection>
   <from tableName="example" rowNr="2" />
   <to tableName="operation" rowNr="4" />
   <breakUp>50</breakUp>
  </connection>
 </connections>
</XTT.Diagram>
      

Jego reprezentacja graficzna wygląda tak:

Graficzna reprezentacja diagramu XTT
Graficzna reprezentacja diagramu XTT

Diagramy XTT służą do reprezentacji wiedzy i zależności pomiędzy jej "porcjami", np. z A wynika B. Diagramy te mają zastosowanie w budowie systemów regułowych.

Konwersja do widocznej postaci stworzona była za pomocą styli XSTL, które przetwarzały plik XML do postaci SVG, które również są dokumentem XML.
Dla dokumentu XML przygotowano plik XSD (XML Schema), umożliwiający walidację dokumentu z diagramem XTT.

Kod źródłowy pliku XSD (opisującego schemat XML) wygląda następująco:

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

  <xs:annotation>
   <xs:documentation xml:lang="en">
   XTT Diagrams schema for AGH.
   Copyright 2006 Tomasz Kuter. All rights reserved.
   </xs:documentation>
  </xs:annotation>

  <xs:element name="XTT.Diagram">
   <xs:complexType>
    <xs:sequence>
      <xs:element name="tables" type="tablesType" minOccurs="1" maxOccurs="unbounded" />
      <xs:element name="connections" type="connectionsType" minOccurs="0" maxOccurs="unbounded" />
    </xs:sequence>
   </xs:complexType>
  </xs:element>

  <xs:complexType name="tablesType">
    <xs:sequence>
      <xs:element name="table" type="tableType" minOccurs="1" maxOccurs="unbounded" />
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="tableType">
    <xs:sequence>
      <xs:element name="row" type="rowType" minOccurs="1" maxOccurs="unbounded" />
    </xs:sequence>
    <xs:attribute name="tableName" type="xs:string"  use="required" />
    <xs:attribute name="x" type="xs:positiveInteger"  use="required" />
    <xs:attribute name="y" type="xs:positiveInteger"  use="required" />
  </xs:complexType>

  <xs:complexType name="rowType">
    <xs:sequence>
      <xs:element name="condition" type="columnType" minOccurs="1" maxOccurs="unbounded" />
      <xs:element name="assert" type="columnType" minOccurs="0" maxOccurs="unbounded" />
      <xs:element name="retract" type="columnType" minOccurs="0" maxOccurs="unbounded" />
      <xs:element name="decision" type="columnType" minOccurs="0" maxOccurs="unbounded" />
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="columnType">
    <xs:sequence>
      <xs:element name="value" type="xs:anyType" minOccurs="0" maxOccurs="unbounded" />
    </xs:sequence>
    <xs:attribute name="name" type="xs:string" use="required" />
    <xs:attribute name="type" type="xs:string" use="required" />
    <xs:attribute name="w" type="xs:positiveInteger" use="required" />
  </xs:complexType>

  <xs:complexType name="connectionsType">
    <xs:sequence>
      <xs:element name="connection" type="connectionType" minOccurs="1" maxOccurs="unbounded" />
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="connectionType">
    <xs:sequence>
      <xs:element name="from" type="pointType" />
      <xs:element name="to" type="pointType" />
      <xs:element name="breakUp" type="xs:positiveInteger" />
      <xs:element name="name" type="xyNameType" minOccurs="0" />
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="pointType">
    <xs:attribute name="tableName" type="xs:string" use="required" />
    <xs:attribute name="rowNr" type="xs:positiveInteger" use="required" />
  </xs:complexType>

  <xs:complexType name="xyNameType">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute name="x" type="xs:integer" use="optional" />
        <xs:attribute name="y" type="xs:integer" use="optional" />
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>

 </xs:schema>
      

ZNF - ZeroNotice Framework dla PHP5

Kolejnym projektem mocno związanym z językiem XML był projekt frameworka MVC dla języka PHP o nazwie Zero Notice Framework, którego byłem współautorem. W projekcie tym poza XSD i XSLT wykorzystywano XPath, czyli specjalny język pozwalający przeszukiwać dokument XML - coś w rodzaju języka SQL dla baz danych.

Przykład pliku XML - konfiguracja bazy danych:

<?xml version="1.0" encoding="utf-8"?>
<znf-db-config xmlns="http://www.zeronotice.org/ZNF/znf-db-config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.zeronotice.org/ZNF/znf-db-config http://www.zeronotice.org/ZNF/xsd/znf-db-config.xsd">

  <db
    default="true"
    dbms="mysql"
    username="root"
    password="jia@sA$DA"
    hostname="localhost"
    dbname="didactix1"
    tableprefix="" />

</znf-db-config>
      

I przykład wykorzystywania XPath dla powyższego dokumentu:

$configXml = new DOMDocument('1.0','utf-8');
$configXml->load(ZNF::CONFIG_DIR . '/' . self::CONFIG_FILE);

if (!$configXml->schemaValidate('ZNF/xsd/znf-db-config.xsd')) {
    $translation = new ZNF_Presentation_Translation('ZNF', $_SESSION['znf']['lang']);
    throw new ZNF_Config_DBConfigException($translation->get('errorDbCfgFileNotValid'));
}

// quick hack to make ZNF work as a PEAR package, to be improved
$dirName = dirname(__FILE__);
$schemaPath = substr($dirName, 0, strpos($dirName, 'Config')) . "xsd/znf-db-config.xsd";
if (!$configXml->schemaValidate($schemaPath)) {
    $translation = new ZNF_Presentation_Translation('ZNF', $_SESSION['znf']['lang']);
    throw new ZNF_Config_DBConfigException($translation->get('errorDbCfgFileNotValid'));
}

$xpath = new DOMXPath($configXml);
$xpath->registerNamespace('db', 'http://www.zeronotice.org/ZNF/znf-db-config');
$config = array();
$default = $xpath->query('/db:znf-db-config/db:db[@default="true"]');

if ($default->length == 1) {
    $config['db']['dbms']     = $default->item(0)->getAttribute('dbms');
    $config['db']['username'] = $default->item(0)->getAttribute('username');
    $config['db']['password'] = $default->item(0)->getAttribute('password');
    $config['db']['hostname'] = $default->item(0)->getAttribute('hostname');
    $config['db']['dbname']   = $default->item(0)->getAttribute('dbname');
    $config['db']['tableprefix']   = $default->item(0)->getAttribute('tableprefix');
// check if only one default action is specified
} else {
    /* ... */
}
      

Eve Online API

Na koniec chciałbym przedstawić API udostępniane przez programistów gry Eve Online.
API to pozwala na pobranie listy postaci (w grze można ich mieć maksymalnie 3), szczegółów postaci, listy posiadanych przedmiotów, listy transakcji finansowych przeprowadzonych na portfelu gracza, itd.

Poniżej plik zawierający dane postaci:

<?xml version='1.0' encoding='UTF-8'?>
<eveapi version="2">
  <currentTime>2011-09-19 02:11:01</currentTime>
  <result>
    <characterID>91192975</characterID>
    <name>Gordon Erkkinen</name>
    <DoB>2011-09-04 21:25:00</DoB>
    <race>Caldari</race>
    <bloodLine>Deteis</bloodLine>
    <ancestry>Merchandisers</ancestry>
    <gender>Male</gender>
    <corporationName>State War Academy</corporationName>
    <corporationID>1000167</corporationID>
    <cloneName>Clone Grade Beta</cloneName>
    <cloneSkillPoints>1380000</cloneSkillPoints>
    <balance>440028.79</balance>
    <attributeEnhancers>
      <perceptionBonus>
        <augmentatorName>Limited Ocular Filter</augmentatorName>
        <augmentatorValue>1</augmentatorValue>
      </perceptionBonus>
      <charismaBonus>
        <augmentatorName>Limited Social Adaptation Chip</augmentatorName>
        <augmentatorValue>1</augmentatorValue>
      </charismaBonus>
      <memoryBonus>
        <augmentatorName>Limited Memory Augmentation</augmentatorName>
        <augmentatorValue>1</augmentatorValue>
      </memoryBonus>
    </attributeEnhancers>
    <attributes>
      <intelligence>20</intelligence>
      <memory>20</memory>
      <charisma>19</charisma>
      <perception>20</perception>
      <willpower>20</willpower>
    </attributes>
    <rowset name="skills" key="typeID" columns="typeID,skillpoints,level,published">
      <row typeID="3300" skillpoints="1415" level="2" published="1" />
      <row typeID="3301" skillpoints="8000" level="3" published="1" />
      <row typeID="3327" skillpoints="8000" level="3" published="1" />
      <row typeID="3330" skillpoints="90510" level="4" published="1" />
      <row typeID="3386" skillpoints="8000" level="3" published="1" />
      <row typeID="3392" skillpoints="8000" level="3" published="1" />
      <row typeID="3402" skillpoints="45255" level="4" published="1" />
      <row typeID="3413" skillpoints="8000" level="3" published="1" />
      <row typeID="3426" skillpoints="8000" level="3" published="1" />
      <row typeID="3449" skillpoints="8000" level="3" published="1" />
      <row typeID="3416" skillpoints="8000" level="3" published="1" />
      <row typeID="3551" skillpoints="8000" level="3" published="1" />
      <row typeID="3319" skillpoints="59043" level="4" published="1" />
      <row typeID="3412" skillpoints="4243" level="2" published="1" />
      <row typeID="3380" skillpoints="8000" level="3" published="1" />
      <row typeID="3320" skillpoints="8000" level="3" published="1" />
      <row typeID="3435" skillpoints="750" level="1" published="1" />
      <row typeID="3429" skillpoints="8000" level="3" published="1" />
      <row typeID="3393" skillpoints="8000" level="3" published="1" />
      <row typeID="3394" skillpoints="16000" level="3" published="1" />
      <row typeID="3428" skillpoints="16000" level="3" published="1" />
      <row typeID="3321" skillpoints="90510" level="4" published="1" />
      <row typeID="3323" skillpoints="16000" level="3" published="1" />
      <row typeID="3432" skillpoints="16000" level="3" published="1" />
      <row typeID="3312" skillpoints="2829" level="2" published="1" />
      <row typeID="3355" skillpoints="8000" level="3" published="1" />
      <row typeID="3356" skillpoints="16000" level="3" published="1" />
      <row typeID="3419" skillpoints="4243" level="2" published="1" />
      <row typeID="3411" skillpoints="4243" level="2" published="1" />
      <row typeID="3322" skillpoints="4243" level="2" published="1" />
      <row typeID="12441" skillpoints="16000" level="3" published="1" />
      <row typeID="21071" skillpoints="16000" level="3" published="1" />
      <row typeID="20314" skillpoints="16000" level="3" published="1" />
      <row typeID="3443" skillpoints="8000" level="3" published="1" />
      <row typeID="25863" skillpoints="4243" level="2" published="1" />
      <row typeID="26252" skillpoints="2829" level="2" published="1" />
      <row typeID="3318" skillpoints="500" level="1" published="1" />
      <row typeID="3311" skillpoints="2829" level="2" published="1" />
      <row typeID="3450" skillpoints="8000" level="3" published="1" />
      <row typeID="3422" skillpoints="2829" level="2" published="1" />
      <row typeID="3334" skillpoints="7072" level="2" published="1" />
      <row typeID="3387" skillpoints="2829" level="2" published="1" />
      <row typeID="3444" skillpoints="2829" level="2" published="1" />
      <row typeID="3388" skillpoints="4243" level="2" published="1" />
      <row typeID="21718" skillpoints="4243" level="2" published="1" />
      <row typeID="3436" skillpoints="8000" level="3" published="1" />
      <row typeID="3324" skillpoints="4243" level="2" published="1" />
      <row typeID="3438" skillpoints="16000" level="3" published="1" />
      <row typeID="25719" skillpoints="4243" level="2" published="1" />
      <row typeID="12442" skillpoints="32000" level="3" published="1" />
      <row typeID="3403" skillpoints="8000" level="3" published="1" />
      <row typeID="3454" skillpoints="7072" level="2" published="1" />
      <row typeID="27902" skillpoints="500" level="1" published="1" />
      <row typeID="16069" skillpoints="500" level="1" published="1" />
    </rowset>
    <rowset name="certificates" key="certificateID" columns="certificateID">
      <row certificateID="282" />
      <row certificateID="135" />
      <row certificateID="139" />
      <row certificateID="146" />
    </rowset>
    <rowset name="corporationRoles" key="roleID" columns="roleID,roleName" />
    <rowset name="corporationRolesAtHQ" key="roleID" columns="roleID,roleName" />
    <rowset name="corporationRolesAtBase" key="roleID" columns="roleID,roleName" />
    <rowset name="corporationRolesAtOther" key="roleID" columns="roleID,roleName" />
    <rowset name="corporationTitles" key="titleID" columns="titleID,titleName" />
  </result>
  <cachedUntil>2011-09-19 02:11:51</cachedUntil>
</eveapi>
      

Szczegółowe informacje na temat API gry Eve Online można znaleźć między innymi pod adresem: http://wiki.eveonline.com/en/wiki/Category:API