Podstawy#
Przestrzenie nazw#
Pojęcie przestrzeni nazw (namespace) przewija się nieustannie w specyfikacji XML, DOM, różnych modułach CSS, i oczywiście HTML5. Sam termin związany jest nie tylko z językami znacznikowymi, ale dotyczy także dowolnego innego języka (naturalnego, technicznego, programowania itd.).
Miałem napisać krótki wywód na temat deklarowania i używania przestrzeni nazw w XML-u, ale specyfikacja "Namespaces in XML 1.1" ("Przestrzenie nazw w XML 1.1") okazała się niewielka i dość przystępna, to też przetłumaczyłem jej najważniejsze kwestie.
Pisząc "specyfikacja" lub "specyfikacja W3C" mam na myśli przytoczoną wersję. Całość uzupełniona została uwagami i przykładami z innych źródeł.
W pigułce#
Z przestrzeniami nazw XML związanych jest wiele określeń. Żeby nie zmuszać czytelników do ciągłego przeszukiwania treści (zakładając że lekturę mają już za sobą), zamieszczam na początku jeden przykład z tabelkowym objaśnieniem dla każdego terminu.
<?xml version="1.1""?>
<root xmlns="http://www.w3.org" xmlns:n1="http://www.w3.org/N1">
<AAA>...</AAA>
<n1:BBB CCC>...</n1:BBB>
</root>
Termin | Wartość dla elementu AAA | Wartość dla elementu n1:BBB | Wartość dla atrybutu CCC w elemencie n1:BBB |
---|---|---|---|
qualified name | AAA | n1:BBB | CCC |
local name | AAA | BBB | CCC |
namespace prefix | brak | n1 | brak |
namespace name | http://www.w3.org | http://www.w3.org/N1 | brak |
expanded name | (http://www.w3.org, AAA) | (http://www.w3.org/N1, BBB) | (brak, CCC) |
Główne pojęcia#
XML jako metajęzyk jest doskonałym rozwiązaniem, jednak istnieje pewien problem związany z rozpoznaniem znaczenia elementu w danym kontekście. Na przykład załóżmy, że mamy element <kod>
, który może oznaczać:
- fragment kodu źródłowego w artykułach informatycznych (aplikacja XML opracowana przez Bronka)
- kod pocztowy w książce adresowej (aplikacja XML opracowana przez Zenka)
Dopóki kod źródłowy i kod pocztowy występują zawsze w różnych dokumentach, nie stanowi to problemu, ale jeśli Bronek i Zenek zechcą połączyć swoje dokumenty (np. dodać metadane o autorze do artykułu), pojawi się problem z interpretacją znaczenia tych elementów. Oznaczałoby to, że języki te nie mogą być łączone, ani nie mogą ze sobą współpracować. Był to największy problem, któremu język XML musiał stawić czoło i z tego powodu utworzono mechanizm obsługi przestrzeni nazw, czyli rozwiązanie spełniające podobne zadania, jakie pojawia się w innych językach programowania.
Przestrzenie nazw w XML są rozwiązaniem dedykowanym dla języka XML, standaryzowanym przez W3C, obecnie występują dwie osobne specyfikacje dla każdej wersji XML:
Przestrzeń nazw XML (XML namespace) jest identyfikowana przez referencję IRI (Internationalized Resource Identifie). Nazwy elementów i atrybutów mogą być umieszczone w przestrzeni nazw XML, używającej mechanizmów opisanych w specyfikacji W3C.
Nazwa rozszerzona # (expanded name) to para składająca się z nazwy przestrzeni nazw # i nazwy lokalnej #.
Dla nazwy N
w przestrzeni nazw zidentyfikowanej przez IRI I
, nazwą przestrzeni nazw (namespace name) jest I
. Dla nazwy N
nie będącej w przestrzeni nazw nazwa przestrzeni nazw nie ma wartości. W każdym przypadku nazwą lokalną (local name) jest N
. To ta kombinacja uniwersalnie zarządzanych przestrzeni nazw IRI ze słownikowymi nazwami lokalnymi jest efektywna przy unikaniu konfliktów nazw.
Odwołania IRI mogą zawierać znaki niedozwolone w nazwach, często są także niewygodnie długie, więc rozszerzone nazwy nie są używane bezpośrednio dla nazw elementów i atrybutów w dokumentach XML. W zamian są używane nazwy kwalifikowane.
Nazwa kwalifikowana # (qualified name) to nazwany temat do interpretacji przestrzeni nazw. W dokumentach zgodnych ze specyfikacją, nazwy elementów i atrybutów pojawiają się jako nazwy kwalifikowane. Syntaktycznie są to nazwy z prefiksem (prefixed names) lub nazwy bez prefiksu (unprefixed names). Specjalna składnia deklaracji bazująca na atrybutach jest dostarczona do łączenia prefiksów z nazwami przestrzeni nazw i do łączenia domyślnych przestrzeni nazw, które stosuje się do nazw elementów bez prefiksów. Deklaracje te oddziałują na elementy, na których się pojawiają, tak żeby różne łączenia mogły być stosowane w różnych częściach dokumentu. Parsery zgodne ze specyfikacją muszą rozpoznawać i reagować na te deklaracje i prefiksy.
IRI jako nazwy przestrzeni nazw#
IRI jest standardem internetowym uwzględniającym internacjonalizację i umożliwiającym łatwą identyfikację zasobów w Internecie.
IRI jest zazwyczaj krótkim łańcuchem znaków, zapisanym zgodnie ze składnią określoną w standardzie. Łańcuch ten określa nazwę lub adres zasobu. Identyfikator IRI jest podobny do URI, jednak różni się tym, że uwzględnia potrzeby języków mających inny alfabet niż łaciński (angielski). Standard IRI opisany jest w dokumencie RFC 3987.
Pusty łańcuch znakowy, chociaż jest legalnym odwołaniem IRI, nie może być używany jako nazwa przestrzeni nazw.
Stosowanie relatywnych odnośników IRI, łącznie z odwołaniami dla tego samego dokumentu, jest niezalecane - przestarzałe (deprecated) - w deklaracjach przestrzeni nazw. Takie stanowisko zostało ustalone przez W3C na plenarnym głosowaniu. Określono w nim także, że późniejsze specyfikacje, takie jak DOM, XPath, itd. nie będą definiować żadnych interpretacji dla nich.
Odwołania IRI identyfikujące przestrzenie nazw są porównywane podczas określania, czy nazwa należy do danej przestrzeni nazw, i czy dwie nazwy należą do tej samej przestrzeni nazw. Dwa IRI są traktowane jak łańcuchy znakowe i są identyczne # (identical) tylko wtedy, kiedy łańcuchy są identyczne, tj. jeśli mają takie same sekwencje znaków. Przy porównaniu uwzględniana jest wielkość znaków, ponadto żadne procentowe kodowanie nie jest przetwarzane (wykonywane).
Konsekwencją tego jest to, że odnośniki IRI, które nie są identyczne w kontekście przestrzeni nazw, mogą odnosić się do tego samego miejsca w Internecie. Oto kilka przykładów odwołań IRI, które wskazują na różne przestrzenie nazw:
// Różnica w wielkości znaków
http://www.example.org/wine
http://www.Example.org/wine
http://www.example.org/Wine
// Różnica w zapisie znaków (kodowanie procentowe)
http://www.example.org/rosé
http://www.example.org/ros%c3%a9
http://www.example.org/ros%c3%A9
http://www.example.org/ros%C3%a9
http://www.example.org/ros%C3%A9
// To samo co oba powyższe przypadki
http://www.example.org/~wilbur
http://www.example.org/%7ewilbur
http://www.example.org/%7Ewilbur
W deklaracji przestrzeni nazw, odnośnik IRI to znormalizowana wartość atrybutu, więc zamiana odwołań do znaków i encji XML zostanie wykonana przed jakimkolwiek porównaniem. Oto kilka przykładów odwołań URI, które wskazują na tę samą przestrzeń nazw:
<p:foo xmlns:p="http://example.org/rosé">
<p:foo xmlns:p="http://example.org/ros&#xe9;">
<p:foo xmlns:p="http://example.org/ros&#xE9;">
<p:foo xmlns:p="http://example.org/ros&#233;">
<p:foo xmlns:p="http://example.org/ros&eacute;">
Czyli jedyny proces jaki zachodzi przed porównywaniem przestrzeni nazw to zamiana encji na odpowiadające im znaki. Ze względu na duże ryzyko pomylenia kilku IRI używających kodowania procentowego w nazwach przestrzeni nazw, zaleca się unikania takiego zapisu w ogóle.
Deklarowanie przestrzeni nazw#
Przestrzeń nazw (lub bardziej precyzyjnie, łączenie przestrzeni nazw) jest deklarowana (declared) poprzez użycie rodziny zarezerwowanych atrybutów. Nazwa takich atrybutów musi być postaci xmlns lub zaczynać się od xmlns:. Te atrybuty, podobnie jak inne atrybuty XML, mogą być wprowadzone bezpośrednio lub domyślnie (default).
Wymagania stawiane nazwom atrybutów dla deklaracji przestrzeni nazw są następujące:
NSAttName ::= PrefixedAttName
| DefaultAttName
PrefixedAttName ::= 'xmlns:' NCName [NSC: Reserved Prefixes and Namespace Names]
DefaultAttName ::= 'xmlns'
NCName ::= NCNameStartChar NCNameChar* /* An XML Name, minus the ":" */
NCNameChar ::= NameChar - ':'
NCNameStartChar ::= NameStartChar - ':'
Znormalizowana wartość atrybutu musi być odwołaniem URI - nazwą przestrzeni nazw identyfikującą przestrzeń nazw - lub pustym łańcuchem znakowym. Nazwa przestrzeni nazw, aby służyć swojemu zamierzonemu celowi, powinna mieć charakter jednoznaczności i trwałości. Jej celem nie jest bezpośrednie wskazanie gotowego do użycia schematu XML (jeśli jakiś istnieje). URN (Uniform Resource Names) jest przykładem składni, która spełnia wymagania stawiane przez specyfikację. Jednak powinno się zauważyć, że zwykłe URL-e mogą zapewnić podobną funkcjonalność.
Jeśli nazwa atrybutu pasuje do PrefixedAttName
, wtedy NCName
określa prefiks przestrzeni nazw # (namespace prefix), używany do łączenia nazw elementu i atrybutu z nazwą przestrzeni nazw ustawioną w wartości atrybutu w zakresie danego elementu, do którego deklaracja jest dołączona.
Jeśli nazwa atrybutu pasuje do DefaultAttName
, wtedy nazwa przestrzeni nazw w wartości atrybutu jest domyślną przestrzenią nazw # (default namespace) w zakresie danego elementu, do którego deklaracja jest dołączona.
W uproszczeniu całość można wyrazić za pomocą następującego zapisu znacznikowego:
<element xmlns="IRI">...</element> <element xmlns:prefix="IRI">...</element>
Prefiks nie może zawierać znaku dwukropka ":"
, gdyż jest on stosowany do rozdzielania nazwy atrybutu xmlns
od nazwy prefiksu.
W poniższym przykładzie stosujemy deklarację przestrzeni nazw, która łączy prefiks "edi"
z nazwą przestrzeni nazw "http://ecommerce.example.org/schema"
:
<x xmlns:edi="http://ecommerce.example.org/schema">
<!-- Prefix "edi" jest wiązany z http://ecommerce.example.org/schema
w elemencie "x" i dotyczy jego zawartości -->
</x>
Przykład jest ciekawy ponieważ element x
, na którym odbywa się połączenie prefiksu "edi"
z przestrzenią nazw "http://ecommerce.example.org/schema"
, nie należy do tej przestrzeni nazw, ale szczegóły tego zachowania będą wyjaśnione dalej.
Zarezerwowane prefiksy i nazwy przestrzeni nazw#
Prefiks xml jest z definicji łączony z nazwą przestrzeni nazw http://www.w3.org/XML/1998/namespace
. Może być deklarowany, ale nie jest to konieczne. Nie można jednak usunąć lub łączyć tego prefiksu z żadną inną nazwą przestrzeni nazw. Inne prefiksy nie mogą być łączone z tą nazwą przestrzeni nazw, a ona sama nie może być zadeklarowana jako domyślna przestrzeń nazw.
Prefiks xmlns jest używany tylko do deklaracji łączenia z przestrzenią nazw, i z definicji jest połączony z nazwą przestrzeni nazw http://www.w3.org/2000/xmlns/
. Nie może być deklarowany lub usuwany. Inne prefiksy nie mogą być łączone z tą nazwą przestrzeni nazw, a ona sama nie może być zadeklarowana jako domyślna przestrzeń nazw. Nazwy elementów nie mogą zawierać prefiksu xmlns
.
Wszystkie inne prefiksy rozpoczynające się od trzyliterowej sekwencji x, m, l
, w jakiejkolwiek kombinacji wielkości znaków, są zarezerwowane. To znaczy, że:
- nie powinny być stosowane przez użytkowników, z wyjątkiem definicji pochodzących z późniejszych specyfikacji
- nie mogą być traktowane przez parsery jako błędy krytyczne
Chociaż same nie są zastrzeżone, nie poleca się stosowania nazw prefiksowych, których LocalPart
rozpoczyna się literami x, m, l
, w dowolnej kombinacji, tak jakby te nazwy były zarezerwowane przy zastosowaniu bez prefiksu.
Nazwy kwalifikowane#
W dokumentach XML zgodnych ze specyfikacją, niektóre nazwy (konstrukcje odpowiadające nieterminalnej Name
) muszą być podane jako nazwy kwalifikowane (qualified names), według następujących reguł:
QName ::= PrefixedName | UnprefixedName PrefixedName # ::= Prefix ':' LocalPart UnprefixedName # ::= LocalPart Prefix ::= NCName LocalPart ::= NCName
Prefix #
określa prefiks przestrzeni nazw, który stanowi część nazwy kwalifikowanej. Prefiks musi zostać połączony z referencją IRI przestrzeni nazw umieszczoną w deklaracji przestrzeni nazw.
LocalPart
określa część lokalną # (local part) nazwy kwalifikowanej.
Należy zauważyć, że funkcje prefiksu służą tylko jako zastępniki dla nazwy przestrzeni nazw. Aplikacje powinny stosować nazwę przestrzeni nazw, nie prefiks, w konstruowaniu nazw, których zasięg wykracza poza obejmujący dokument.
W uproszczeniu całość można wyrazić za pomocą następującego zapisu:
nazwa prefix:nazwa
gdzie nazwa
odpowiada nazwie elementu bądź atrybutu, prefix
zaś odpowiada prefiksowi przypisanemu do konkretnej przestrzeni nazw (w deklaracji przestrzeni nazw).
Stosowanie nazw kwalifikowanych#
W dokumentach XML zgodnych ze specyfikacją, nazwy elementów są wyrażane w postaci nazw kwalifikowanych, według następujących reguł:
Nazwy elementów
STag ::= '<' QName (S Attribute)* S? '>' [NSC: Prefix Declared]
ETag ::= '</' QName S? '>' [NSC: Prefix Declared]
EmptyElemTag ::= '<' QName (S Attribute)* S? '/>' [NSC: Prefix Declared]
W poniższym przykładzie stosujemy nazwę kwalifikowaną edi:price
jako nazwę dla elementu price
:
<!-- Element 'price' znajduje się w przestrzeni nazw http://ecommerce.example.org/schema -->
<edi:price xmlns:edi='http://ecommerce.example.org/schema' units='Euro'>32.18</edi:price>
Zwracam uwagę na fakt, że w przypadku elementów niepustych należy koniecznie umieszczać nazwę kwalifikowaną zarówno w znaczniku otwierającym, jaki i zamykającym.
Atrybuty
Attribute ::= NSAttName Eq AttValue
| QName Eq AttValue [NSC: Prefix Declared]
Atrybuty mogą być deklaracjami przestrzeni nazw lub ich nazwy są wyrażane w postaci nazw kwalifikowanych.
W poniższym przykładzie stosujemy nazwę kwalifikowaną edi:taxClass
jako nazwę dla atrybutu taxClass
:
<x xmlns:edi='http://ecommerce.example.org/schema'>
<!-- Atrybut 'taxClass' znajduje się w przestrzeni nazw http://ecommerce.example.org/schema -->
<lineItem edi:taxClass="exempt">Baby food</lineItem>
</x>
Ograniczenia przy deklarowaniu prefiksu
Przy deklarowaniu prefiksów występują pewne ograniczenia. Prefiks przestrzeni nazw, z wykluczeniem xml
lub xmlns
, musi być zadeklarowany za pomocą atrybutowej deklaracji przestrzeni nazw w znaczniku początkowym elementu, gdzie prefiks jest używany, lub w elemencie przodka (tj. elemencie, którego zawartość content jest oznaczona przez znacznik prefiksowy). Co więcej, wartość atrybutu dla najgłębszej takiej deklaracji nie może być pustym łańcuchem znakowym.
Powyższe ograniczenie może powodować operacyjne trudności w przypadku, gdzie atrybutowa deklaracja przestrzeni nazw jest zapewniana nie bezpośrednio w jednostce dokumentu (document entity), ale przez domyślny atrybut deklaracyjny w zewnętrznej jednostce. Takie deklaracje mogą nie być odczytywane przez programy, które bazują na parserze XML bez walidacji. Wielu aplikacjom XML, włączając w to te przypuszczalnie obsługujące przestrzenie nazw, nie udaje się przejść wymaganej walidacji. Jeśli prawidłowe działanie takich aplikacji jest wymagane, to deklaracje przestrzeni nazw muszą być zapewnione bezpośrednio lub za pośrednictwem domyślnych deklaracji atrybutów w wewnętrznym podzbiorze DTD (internal subset of the DTD).
Deklaracja DTD
doctypedecl ::= '<!DOCTYPE' S QName (S ExternalID)? S? ('[' (markupdecl | PEReference | S)* ']' S?)? '>' elementdecl ::= '<!ELEMENT' S QName S contentspec S? '>' cp ::= (QName | choice | seq) ('?' | '*' | '+')? Mixed ::= '(' S? '#PCDATA' (S? '|' S? QName)* S? ')*' | '(' S? '#PCDATA' S? ')' AttlistDecl ::= '<!ATTLIST' S QName AttDef* S? '>' AttDef ::= S (QName | NSAttName) S AttType S DefaultDecl
Nazwy elementów oraz nazwy atrybutów również są wyrażane za pomocą nazw kwalifikowanych, kiedy pojawiają się w deklaracjach wewnątrz DTD.
Stosowanie przestrzeni nazw w elementach i atrybutach#
Zasięg przestrzeni nazw#
Zasięg (scope) deklaracji przestrzeni nazw ustalającej prefiks rozciąga się od znacznika otwierającego (w którym się pojawia), aż do końca odpowiadającego znacznika zamykającego, włączając w to wszystkie zawarte elementy między tymi znacznikami, ale z wykluczeniem zasięgu jakichkolwiek innych wewnętrznych deklaracji z taką samą częścią NSAttName
(które mogą ją nadpisać). W przypadku elementu pustego zakresem jest sam element.
Taka deklaracja przestrzeni nazw odnosi się do wszystkich nazw elementów i atrybutów wewnątrz jej zasięgu, których prefiks pasuje do tego określonego w deklaracji. To jest bardzo ważna informacja, element w którym następuje prefiksowa deklaracja przestrzeni nazw nie należy do tej przestrzeni, dopóki nie zostanie dopisany prefiks przed nazwą tego elementu.
Nazwa rozszerzona odpowiadająca prefiksowej nazwie elementu lub atrybutu posiada IRI, który jest połączony za pomocą prefiksu z nazwą przestrzeni nazw, a część lokalna stanowi nazwę lokalną.
Prosty przykład:
<?xml version="1.1"?>
<html:html xmlns:html='http://www.w3.org/1999/xhtml'>
<html:head>
<html:title>Frobnostication</html:title>
</html:head>
<html:body>
<html:p>Moved to <html:a href='http://frob.example.com'>here.</html:a></html:p>
</html:body>
</html:html>
Wielokrotne prefiksowe przestrzenie nazw można zadeklarować jako atrybuty pojedynczego elementu, jak pokazano na przykładzie:
<?xml version="1.1"?>
<!-- Obydwa prefiksy przestrzeni nazw są dostępne -->
<bk:book xmlns:bk='urn:loc.gov:books' xmlns:isbn='urn:ISBN:0-395-36341-6'>
<bk:title>Cheaper by the Dozen</bk:title>
<isbn:number>1568491379</isbn:number>
</bk:book>
Wartość atrybutu dla prefiksowej deklaracji przestrzeni nazw może być pusta. W obrębie zasięgu deklaracji ma to taki efekt, że usuwa jakiekolwiek połączenia prefiksu z nazwą przestrzeni nazw. Dalsze deklaracje mogą przedeklarować prefiks ponownie:
<?xml version="1.1"?>
<x xmlns:n1="http://www.w3.org">
<n1:a /> <!-- Dozwolone - prefiks n1 jest łączony z http://www.w3.org -->
<x xmlns:n1="">
<n1:a /> <!-- Zabronione - prefiks n1 nie ma połączenia w tym miejscu -->
<x xmlns:n1="http://www.w3.org">
<n1:a /> <!-- Dozwolone - prefiks n1 jest łączony ponownie -->
</x>
</x>
</x>
Domyślna przestrzeń nazw#
Zasięg (scope) deklaracji domyślnej przestrzeni nazw rozciąga się od znacznika otwierającego (w którym się pojawia), aż do końca odpowiadającego znacznika zamykającego, włączając w to wszystkie zawarte elementy między tymi znacznikami, ale z wykluczeniem zasięgu jakichkolwiek innych wewnętrznych deklaracji domyślnych przestrzeni nazw. W przypadku elementu pustego zakresem jest sam element.
Deklaracja domyślnej przestrzeni nazw odnosi się do wszystkich bezprefiksowych nazw elementów wewnątrz jej zasięgu. Deklaracje domyślnej przestrzeni nazw nie dotyczą bezpośrednio nazw atrybutów. Interpretacja bezprefiksowych atrybutów jest uzależniana od elementów, w których się pojawiają.
Jeśli w zasięgu istnieje deklaracja domyślnej przestrzeni nazw, to nazwa rozszerzona odpowiada nieprefiksowej nazwie elementu, którego IRI z domyślnej przestrzeni nazw jest nazwą przestrzeni nazw. Jeśli w zasięgu nie istnieje deklaracja domyślnej przestrzeni nazw, to nazwa przestrzeni nazw nie ma wartości. Nazwa przestrzeni nazw dla nieprefiksowych nazw atrybutów nigdy nie ma wartości. We wszystkich przypadkach nazwą lokalną jest część lokalna (identyczna z nieprefiksową nazwą).
Prosty przykład:
<?xml version="1.1"?>
<!-- Elementy należą do domyślnej przestrzeni nazw HTML -->
<html xmlns='http://www.w3.org/1999/xhtml'>
<head>
<title>Frobnostication</title>
</head>
<body>
<p>Moved to <a href='http://frob.example.com'>here</a>.</p>
</body>
</html>
Kolejny przykład
<?xml version="1.1"?>
<!-- Nieprefiksowe elementy pochodzą z "urn:loc.gov:books" -->
<book xmlns='urn:loc.gov:books' xmlns:isbn='urn:ISBN:0-395-36341-6'>
<title>Cheaper by the Dozen</title>
<isbn:number>1568491379</isbn:number>
</book>
Jeszcze jeden przykład:
<?xml version="1.1"?>
<!-- Początkowo domyślną przestrzenią nazw jest "urn:loc.gov:books" -->
<book xmlns='urn:loc.gov:books' xmlns:isbn='urn:ISBN:0-395-36341-6'>
<title>Cheaper by the Dozen</title>
<isbn:number>1568491379</isbn:number>
<notes>
<!-- Uczyń HTML domyślną przestrzenią nazw dla niektórych komentarzy -->
<p xmlns='urn:w3-org-ns:HTML'>
This is a <i>funny</i> book!
</p>
</notes>
</book>
Wartość atrybutu w deklaracji domyślnej przestrzeni nazw może być pusta. W obrębie zasięgu deklaracji ma to taki efekt, że nie ma domyślnej przestrzeni nazw:
<?xml version="1.1"?>
<Beers>
<!-- Od tej pory domyślną przestrzenią nazw jest HTML -->
<table xmlns='http://www.w3.org/TR/REC-html40'>
<th>
<td>Name</td>
<td>Origin</td>
<td>Description</td>
</th>
<tr>
<!-- Brak domyślnej przestrzeni nazw wewnątrz komórek tabeli -->
<td>
<brandName xmlns="">Huntsman</brandName>
</td>
<td>
<origin xmlns="">Bath, UK</origin>
</td>
<td>
<details xmlns="">
<class>Bitter</class>
<hop>Fuggles</hop>
<pro>Wonderful hop, light alcohol, good summer beer</pro>
<con>Fragile; excessive variance pub to pub</con>
</details>
</td>
</tr>
</table>
</Beers>
Unikalność atrybutów#
W dokumentach zgodnych ze specyfikacją żaden tag nie może zawierać dwóch atrybutów, które:
- posiadają identyczne nazwy, lub
- posiadają kwalifikowane nazwy z tą samą częścią lokalną i z prefiksami, które połączono z identycznymi nazwami przestrzeni nazw.
To ograniczenie jest równoważne z wymogiem mówiącym, że element nie może mieć dwóch atrybutów z tą samą nazwą rozszerzoną.
W poniższym przykładzie każdy z elementów pustych bad
jest niedozwolony:
<!-- http://www.w3.org jest łączona z n1 i n2 -->
<x xmlns:n1="http://www.w3.org" xmlns:n2="http://www.w3.org">
<bad a="1" a="2" />
<bad n1:a="1" n2:a="2" />
</x>
Jednakże, każdy z następujących wariantów jest dozwolony, ten drugi ponieważ domyślna przestrzeń nazw nie stosuje się do nazw atrybutów:
<!-- http://www.w3.org jest łączona z n1 i jest domyślna -->
<x xmlns:n1="http://www.w3.org" xmlns="http://www.w3.org">
<good a="1" b="2" />
<good a="1" n1:a="2" />
</x>
Możliwe jest także użycie dwóch różnych prefiksów dla tej samej przestrzeni nazw, będą wtedy traktowane równorzędnie:
<!-- http://www.w3.org jest łączona z n1 i n2 -->
<x xmlns:n1="http://www.w3.org" xmlns:n2="http://www.w3.org">
<n1:good />
<n2:good />
<good n1:a="1" n2:b="2" />
</x>
W przedstawionym przykładzie element good
z prefiksem n1
to dokładnie ten sam element, co element good
z prefiksem n2
.
Przestrzenie nazw DOM4#
W specyfikacji DOM4 pojawiają się następujące przestrzenie nazw:
- przestrzeń nazw HTML # (HTML namespace):
http://www.w3.org/1999/xhtml
- przestrzeń nazw SVG # (SVG namespace):
http://www.w3.org/2000/svg
- przestrzeń nazw XML # (XML namespace):
http://www.w3.org/XML/1998/namespace
- przestrzeń nazw XMLNS # (XMLNS namespace):
http://www.w3.org/2000/xmlns/
Oczywiście DOM4 współpracuje z dowolnymi przestrzeniami nazw XML, aczkolwiek tylko te trzy będą się przewijały w całej dokumentacji DOM4.
Warto przeczytać podrozdział "XML Namespaces" ze specyfikacji DOM3, gdzie wyjaśniono kilka kluczowych zachowań związanych z przestrzeniami nazw dla węzłów, atrybutów, właściwości i metod.
Przestrzenie nazw HTML5#
W specyfikacji HTML5 dozwolone są następujące przestrzenie nazw:
- przestrzeń nazw HTML # (HTML namespace):
http://www.w3.org/1999/xhtml
- przestrzeń nazw MathML # (MathML namespace):
http://www.w3.org/1998/Math/MathML
- przestrzeń nazw SVG # (SVG namespace):
http://www.w3.org/2000/svg
- przestrzeń nazw XLink # (XLink namespace):
http://www.w3.org/1999/xlink
- przestrzeń nazw XML # (XML namespace):
http://www.w3.org/XML/1998/namespace
- przestrzeń nazw XMLNS # (XMLNS namespace):
http://www.w3.org/2000/xmlns/
Dla łatwiejszej migracji z HTML do XHTML aplikacje klienckie zgodne ze specyfikacją HTML5 powinny umieszczać elementy HTML w przestrzeni nazw http://www.w3.org/1999/xhtml
. Termin "elementy HTML" odnosi się do wszystkich elementów zawartych w tej przestrzeni nazw, a więc odnosi się zarówno do elementów HTML jak i XHTML.
Narzędzia przetwarzające dane oraz inne aplikacje klienckie, które wykonują operacje na zawartości bez uruchamiania skryptów, rozwijania wyrażeń CSS oraz XPath, lub w inny sposób prezentujących wynikowy DOM dla bezwzględnej zawartości, mogą "obsługiwać przestrzenie nazw" po prostu stwierdzając, że ich węzły DOM przynależą do pewnych przestrzeni nazw, bez konieczności rzeczywistego eksponowania powyższych łańcuchów znakowych.
W składni HTML5 prefiksy przestrzeni nazw oraz deklaracje przestrzeni nazw nie mają takiego samego efektu jak w przypadku XML. Dla przykładu, dwukropek nie ma specjalnego znaczenia w nazwach elementów HTML5. Przeglądarki internetowe automatycznie umieszczają elementy i atrybuty dokumentów HTML w odpowiednich przestrzeniach nazw (choćby dla DOM i CSS).
Powyższa uwaga będzie dotyczyła także osadzonego SVG lub MathML bezpośrednio w plikach HTML. Deklaracja przestrzeni nazw dla tych elementów jest zbędna.
HTML5 dopuszcza pewne atrybuty z prefiksami dla elementów foreign, pozwala także na specyficzne literalne użycie xml:lang
, ale tylko po to, aby umożliwić tworzenie dwujęzycznych dokumentów HTML5 i XHTML5 (tzw. polyglot). Jeśli dokument będzie parsowany jako HTML, atrybut taki nie będzie miał żadnego znaczenia przy przetwarzaniu języka.
Przestrzenie nazw CSS#
W przypadku kaskadowych arkuszy stylów obsługę przestrzeni nazw opisałem bezpośrednio w kursie CSS.
Dodatkowe przykłady#
W pierwszym przykładzie pozagnieżdzano wiele deklaracji przestrzeni nazw. Każdy element oraz atrybut został dokładnie opisany, do jakiej przestrzeni nazw przynależy:
<a xmlns:b="urn:b"> <!-- 'a' nie należy do żadnej przestrzeni nazw -->
<c xmlns="urn:x"> <!-- 'c' należy do urn:x -->
<!-- 'e' należy do urn:d -->
<!-- 'f' należy do urn:b -->
<d:e xmlns="urn:y" xmlns:d="urn:d" b:f="g">
<!-- 'i' należy do urn:y -->
<j b:k="l" /> <!-- 'j' należy do urn:y --> <!-- 'k' należy do urn:b2 -->
</i>
</d:e>
<m n="o" /> <!-- 'm' należy do urn:x --> <!-- 'n' nie należy do żadnej przestrzeni nazw! -->
</c>
<p /> <!-- 'p' nie należy do żadnej przestrzeni nazw! -->
</a>
W drugim przykładzie stosujemy deklarację przestrzeni nazw do połączenia naszego dokumentu XML ze schematem XML umieszczonym w pliku SimpleAddress.xsd
(językiem schematu jest XML Schema):
<?xml version="1.0" encoding="utf-8"?>
<Address xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="SimpleAddress.xsd">
<Recipient>Mr. Walter C. Brown</Recipient>
<House>49</House>
<Street>Featherstone Street</Street>
<Town>LONDON</Town>
<PostCode>EC1Y 8SY</PostCode>
<Country>UK</Country>
</Address>
Trzeci przykład prezentuje plik arkusza stylów XSLT, który w swoich definicjach również wykorzystuje mechanizm przestrzeni nazw:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr>
<th align="left">Title</th>
<th align="left">Artist</th>
</tr>
<xsl:for-each select="catalog/cd">
<tr>
<td><xsl:value-of select="title" /></td>
<td><xsl:value-of select="artist" /></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Warto przeanalizować 14 przykładów z poradnika Tutorial: przestrzenie nazw XML (Namespace).