jQuery: elementi XML generici e namespace XML

Il wrapper $() di jQuery ha la capacità di selezionare gli elementi trasformando l'argomento passato in un'espressione. Questo funziona perfettamente con gli elementi HTML o XHTML noti. Per elemento noto si intende un elemento a cui il browser associa delle proprietà e dei metodi DOM predefiniti basandosi sul namespace di appartenenza o sulla DTD. Quando un elemento non è noto, la selezione jQuery funziona ancora, ma non è possibile utilizzare i suoi metodi sugli elementi selezionati, in quanto questi non posseggono delle caratteristiche associate. Questo è il caso degli elementi XML appartenenti ad un namespace creato da noi. Vediamo un esempio concreto.

Abbiamo questo documento XHTML servito come XML:


<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:p="http://www.ns.com/ns/p">
<head>
<title>Test</title>
<meta http-equiv="Content-Type" content="text/xml; charset=utf-8" />
</head>
<body>
<p:div>Test</p:div>
</body>
</html>

Il namespace viene associato all'URI http://www.ns.com/ns/p ed ha come prefisso p. Possiamo utilizzare il metodo getElementsByTagNameNS() con jQuery:


console.log($(document.getElementsByTagNameNS('http://www.ns.com/ns/p', 'div')));  // [<p:div>​Test​</p:div>​]

All'apparenza funziona perfettamente. Ora proviamo ad operare sulla selezione:


$(document.getElementsByTagNameNS('http://www.ns.com/ns/p', 'div')).each(function() {
	
		console.log(this); //<p:div>​Test​</p:div>​
		this.setAttributeNS('http://www.ns.com/ns/p', 'class', 'test'); // funziona
		$(this).addClass('foo'); // non funziona
	
});

L'elemento è generico ed il browser non può associargli la proprietà className ed è per questo che il metodo addClass() fallisce. Tra l'altro, essendo generico, l'elemento ha bisogno della regola CSS @namespace per poter ricevere gli stili assegnatigli:


@namespace "http://www.ns.com/ns/p";

div[*|class="test"] {
	color: blue;
}
Torna su