Serialitazió de documents XML
Motivació
Tal i com s'ha explicat en apartats anteriors un dels passos a seguir quan es vol xifrar o signar un document XML és serialitzar-lo. Però per que és necessari fer-ho? Quan enviem un document XML signat a un altre usuari pot passar que la representació física del document hagi variat però no hagi variat la seva representació lògica, per exemple suposem que enviem un document XML a través del protocol SOAP i un dels nodes SOAP pels que passa treu els espais innecessaris:
Imatge
1
: Exemple
El problema apareix quan l'usuari B intenta verificar la firma. És clar que si la representació física ha variat la seva firma també, ja que està basada en el digest d'aquest. Però tal i com es pot observar els dos documents XML segueixen sent lògicament equivalents. Per tant en aquest cas trobem la necessitat de trobar un mecanisme que ens permeti verificar si dos fitxers són lògicament iguals. Això ho podem fer representant el document XML original en forma canònica. Fent servir aquest procediment el problema anterior queda arreglat:
Imatge
2
: Exemple
En aquest cas quan el destinatari verifica la firma sobre el document XML canònic i verifica que la seva estructura lògica no ha estat modificada.
Per altra banda ens podem trobar amb altres tipus de modificacions més complexes, és a dir que no es tracti només d'afegir o treure espais, que fan que un subconjunt d'un document XML segueixi sent lògicament equivalent però físicament diferent.
És a dir, observem el següent document XML:
|
<?xml version="1.0"?>
<arrel>
<node1 xmlns:SpNom1="http://www.guim.net/xml">
<node2 xmlns:SpNom2="http//francesc.guim.net/xml" id="1">
Document XML original, observar
la declaració dels dos espais de noms i de l'id.
</node2>
<node2 xmlns:SpNom2="http//francesc.guim.net/xml" id="2">
Document XML original, observar
la declaració dels dos espais de noms i de l'id.
</node2>
</node1>
</arrel> |
Taula
1
: Ex1DocumentOriginal.xml
Suposem ara que es necessita treballar amb un subconjunt d'aquest document, concretament amb l'element node2 que té l'atribut id amb valor "2" . Per fer-ho apliquem la següent expressió XPath [XPath] al document:
|
/arrel/node1/node2[id="2"] |
El resultat d'aquest és el següent document:
|
<node2 xmlns:SpNom2="http//francesc.guim.net/xml" id="2">
Document XML original, observar
la declaració dels dos espais de noms i de l'id.
</node2> |
Taula
2
: Ex1DocumentDesti1.xml
Però cal tenir present que la declaració de l'espai de noms del seu node pare, node1, també l'afecta. Per tant el següent subdocument XML seria equivalent:
|
<node2 xmlns:SpNom2="http//francesc.guim.net/xml"
xmlns:SpNom1="http://www.guim.net/xml"
id="2">
Document XML original, observar
la declaració dels dos espais de noms i de l'id.
</node2> |
Taula
3
: Ex1DocumentDesti2.xml
D'aquest fet en podem extreure que no només és important saber canonitzar documents XML complets, sinó que també cal establir un mecanisme que ens permeti definir el procés de canonització sobre un possibles transformacions d'un document XML.
Objectiu de la canonització
L'objectiu principal d'aquesta especificació és establir un mètode per a determinar quan dos documents són idèntics, o quan una aplicació no ha modificat un document XML, exceptuant aquelles transformacions permeses a l'especificació de l'XML 1.0 i en l'especificació dels espais de noms d'XML .
Cal remarcar que el que no es pretén amb aquest procés és determinar si dos documents XML són equivalents si i no només si les seves dues formes canòniques són equivalents. Aquest procés sembla inassolible ja que caldria tenir en compte molts altres factors. Per exemple, els dos següents documents XML són equivalents?
|
<?xml version="1.0"?>
<colors>
<color>Blau</color>
<color>Verd</color>
</colors> |
Taula
4
: Ex2XMLColorsCat.xml
|
<?xml version="1.0"?>
<colors>
<color>Blue</color>
<color>Green</color>
</colors> |
Taula
5
: Ex2XMLColorsAng.xml
Probablement hom podria dir que si, però aquest no és l'objectiu de l'estàndard que estem explicant.
Tipus de documents XML
A continuació es mostra els diferents tipus de documents XML canònics que hi ha, en els successius punts se'n descriu el procés de transformació a cada un d'ells:
§
Document XML Canònic.
§
Document XML Canònic sense comentaris.
§
Document XML Canònic Exclusiu.
§
Document XML Canònic Exclusiu sense comentaris.
Els dos primers tipus de documents són els més emprats, no obstant per cert tipus d'aplicacions és útil treballar amb els dos darrers formats.
Documents XML Canònics
En aquest apartat es descriurà el procés de transformació d'un document XML a la seva forma canònica.
La única diferència entre un document XML Canònic i XML Canònic sense comentaris, tal i com indica el seu nom, és que aquest darrer treu tots els comentaris del document XML.
A continuació es mostren els canvis que cal realitzar sobre un document XML per passar-lo a la seva forma canònica:
§
Cal passar el document XML a codificació UTF-8
§
Els salts de línia són normalitzats per #xA abans de realitzar el parsing.
§
Cal resoldre les entitats pel seu valor.
§
Cal substituir les seccions de tipus CDATA pel seu contingut.
§
En el cas que el document XML tingui una declaració de tipus de document [DTD] caldrà posar els atributs d'un element que tinguin valor per defecte. És a dir la DTD ens ajudarà a la creació de la forma canònica.
§
Eliminar la declaració de tipus de document.
§
Eliminar la declaració de document XML.
§
Els espais de dins del node arrel s'han de preservar, la resta s'han de suprimir.
§
En l'estàndard XML no defineix cap ordre en la declaració dels atributs i espais de noms d'un element, cal establir-ne un:
o
Els espais de noms sempre van abans que la declaració dels atributs.
o
Els espais de noms són ordenats de forma lexicogràfica.
o
Els atributs són ordenats de forma lexicogràfica tenint en compte l'espai de noms. En el cas que l'espai de noms sigui buit l'atribut és lexicogràficament l'últim.
§
El text resultant depèn del tipus de node XML que estiguem tractant, a continuació se'n detalla el procés de transformació de cada tipus d'element:
o
Node Arrel s'han de processar tots els seus fills.
o
Node Element el format d'aquest ha de ser obert del caràcter "<", seguit d'un element [QNAME], seguit del resultat de processar els seus espais de noms, seguit del resultat de processar els seus atributs, segut del caràcter ">", seguit del resultat de processar els seus fills, seguit del caràcter "<", seguit d'un element [QNAME], seguit del caràcter "/" i finalment seguit del caràcter ">".
§
Tractament dels espais de noms:
1.
S'hi assigna l'espai de noms per defecte xmlns="" si i només si aquest és el seu espai de noms i el seu element antecessor té un espai de noms per defecte diferent de "", tenir en compte que quan estem tractant un element ja hem processat tots els anteriors, la qual cosa implica que és manté la semàntica del document original (Mirar els exemples). D'aquesta manera ens estalviem ocurrències innecessàries.
2.
Per cada espai de noms declarat el suprimim si i només si ja ha estat declarat anteriorment amb el mateix valor.
3.
Entre cada declaració hi ha un sol espai.
§
Tractament dels atributs: entre cada atribut hi ha una sol espai. La seva declaració comença pel nom d'aquest, seguit del signe "=" i seguit del valor. Aquest darrer ha de començar de " i ser tancats per ", cal modificar el seu contingut de la següent manera:
·
Substituir els "&" per "&"
·
Substituir els "<" per "<"
·
Substituir els símbols de comentari per """
·
Els caràcters d'espai #x9,#xA,#xD per les seves referències (p.e: #x9 per 	)
§
Tractament del contingut text dels: cal realitzar les següents modificacions:
·
Substituir els "<" per "<"
·
Substituir els ">" per ">"
·
Els caràcters #xD per 
o
Node PI (Processing Instruction) : aquest element ha de començar per "<?", seguit del nom del node, seguit d'un espai, , seguit d'una cadena, seguit d'un espai en el cas que la cadena no estigui buida.
o
Node Comentari: en el cas que estiguem treballant amb XML Canònic sense comentaris el suprimim. Altrament l'element ha de començar per "<!--", seguit del comentari i finalment seguit de "<!--".
El procés que s'ha mostrat és el que cal seguir cada vegada que es vol serialitzar un document XML perquè estigui en forma Canònica. No obstant tal i com ja hem dit en punts anteriors d'avegades ens interessa passar a forma normal un subconjunt d'un document XML, en aquest cas no només cal realitzar els diferents passos esmentats sinó que a més a més cal propagar les declaracions dels espais de noms cap al subdocument, és a dir el que cal assegurar és que tot espais de noms que abans estava declarat en el document i que el subdocument n'heretava la definició estigui contingut en el subdocument. En el segon exemple que hem mostrat en la motivació:
|
<?xml version="1.0"?>
<arrel>
<node1 xmlns:SpNom1="http://www.guim.net/xml">
<node2 xmlns:SpNom2="http//francesc.guim.net/xml" id="1">
Document XML original, observar
la declaració dels dos espais de noms i de l'id.
</node2>
<node2 xmlns:SpNom2="http//francesc.guim.net/xml" id="2">
Document XML original, observar
la declaració dels dos espais de noms i de l'id.
</node2>
</node1>
</arrel> |
Al extreure l'element node2, en el seu procés de canonització s'ha de comprovar quins espais de noms hereta dels seus antecessors i no estan declarats en els seus antecessors del subdocument ubicar-los en la seva declaració, per tant tal la seva forma Canònica és:
|
<node2 xmlns:SpNom1="http://www.guim.net/xml"
xmlns:SpNom2="http//francesc.guim.net/xml"
id="2">
Document XML original, observar
la declaració dels dos espais de noms i de l'id.
</node2> |
Exemples de pas a document XML Canònic
En aquest apartat es veuran un conjunt d'exemples que serveixen per il·lustrar el procés explicat en el darrer punt.
Exemple 1: el document XML de partida de l'exemple és el següent:
|
<?xml version="1.0"?>
<?xml-stylesheet href="doc.xsl"
type="text/xsl" ?>
<!DOCTYPE doc SYSTEM "doc.dtd">
<!-- Comment 2 -->
<!-- Comment 3 -->
<doc>Primera canonització !!!<!-- Comentari --></doc>
<?PI-Buida ?> |
Taula
6
: Ex1FormaNoCanonica.xml
Mirem quina és la seva forma Canònica:
|
<?xml-stylesheet href="doc.xsl"
type="text/xsl" ?>
<!-- Primer comentari -->
<!-- Segon comentari -->
<doc>Primera canonització !!!<!-- Comentari --></doc>
<?PI-Buida?> |
Taula
7
: Ex1FormaCanonica.xml
Remarcar que s'han perdut els salts de línia que estaven fora del node arrel, s'ha perdut la declaració de document XML, s'ha perdut la declaració del tipus de document, s'han perdut els espais de l'element PI-Buida ja que no té cap cadena, i s'han mantingut els espais dins les dades de la primera PI xml-stylesheet.
Mirem ara quina és la seva forma Canònica sense comentaris:
|
<?xml-stylesheet href="doc.xsl"
type="text/xsl" ?>
<!DOCTYPE doc SYSTEM "doc.dtd">
<doc>Primera canonització !!!</doc>
<?PI-Buida?> |
Taula
8
: Ex1FormaCanonicaOutCom.xml
Les modificacions que s'han dut a terme han estat les mateixes que en la forma anterior, però a més a més s'han tret els parèntesis.
Exemple 2: el document XML de partida és el següent
|
<arrel>
<fill1> </fill1>
<fill2> Segon fill </fill2>
<fill3>
<Net1> </Net1>
<Net2></Net2>
<Net3> Tercer Net</Net3>
</fill3>
</arrel> |
Taula
9
: Taula
10
: Ex1FormaCanonica.xml
Aquest document ja es troba en forma canònica, cal remarcar que els espais i salts de línia es mantenen perquè es troben ubicats dins els node arrel.
Exemple 3: el document de partida és el següent:
|
<?xml version="1.0"?>
<!DOCTYPE doc [<!ATTLIST e9 attr CDATA "default">]>
<Arrel>
<elem1 />
<elem2 ></elem2>
<elem3 name = "elem3" id="elem3" />
<elem4 name="elem4" id="elem4" ></elem4>
<elem5 a:attr="out" b:attr="sorted" attr2="all" attr="I'm"
xmlns:b="http://www.ietf.org"
xmlns:a="http://www.w3.org"
xmlns="http://example.org"/>
<elem6 xmlns="" xmlns:a="http://www.w3.org">
<elem7 xmlns="http://www.ietf.org">
<elem8 xmlns="" xmlns:a="http://www.w3.org">
<elem9 xmlns="" xmlns:a="http://www.ietf.org"/>
</elem8>
</elem7>
</elem6>
</Arrel> |
Taula
11
: Ex3FormaNoCanonica.xml
En la següent pàgina es pot observar el resultat de passar a forma Canònica aquest document. En aquest cas com que no hi ha comentaris, la seva forma Canònica amb o sense comentaris és la mateixa.
|
<Arrel>
<elem1></elem1> (1)
<elem2></elem2>
<elem3 id="elem3"(3) name="elem3" (2)></elem3>
<elem4 id="elem4" name="elem4"></elem4>
<elem5 (4) xmlns="http://example.org" xmlns:a="http://www.w3.org" xmlns:b="http://www.ietf.org" attr="I'm" attr2="all" b:attr="sorted" a:attr="out"></elem5>
<elem6 xmlns:a="http://www.w3.org">
<elem7 xmlns="http://www.ietf.org">
<elem8 xmlns="">
<elem9 xmlns:a="http://www.ietf.org" attr="default" (1) ></elem9>
</elem8>
</elem7>
</elem6>
</Arrel> |
Taula
12
: Ex3FormaCanonica.xml
Cal remarcar que els elements que eren de la forma "<nom/>" han passat a ser de la forma "<nom></nom>" (1), els espais entre els atributs s'ha normalitzat (2), és a dir només n'hi ha un entre cada atribut, els atributs també s'han normalitzat i s'hi ha tret els espais (3), s'han ordenat els espais de noms i atributs segons l'ordre explicat en el darrer punt (4), s'han eliminat els espais de noms redundants, s'han afegit els atributs definits per defecte a la DTD (5).
Exemple 4: el document de partida és el següent:
|
<!DOCTYPE doc [
<!ATTLIST Id id ID #IMPLIED>
<!ATTLIST Names attr NMTOKENS #IMPLIED>
]>
<Arrel>
<text>Primera Linia
 Segona Linia</text>
<valor>2</valor>
<calcul><![CDATA[value>"0" && value<"10" ?"valid":"error"]]></calcul>
<calcul expr='value>"0" && value<"10" ?"valid":"error"'>valid</calcul>
<norm attr=' '   
	 ' '/>
<Names attr=' A   
	 B '/>
<Id id=' '   
	 ' '/>
</Arrel> |
Taula
13
: Ex4FormaNoCanonica.xml
El resultat de passar a forma Canònica el document anterior és el següent:
|
<Arrel>
<text>Primera Linia
Segona Linia</text>
<valor>2</valor>
<calcul>value>"0" && value<"10" ?"valid":"error"</calcul>
<compute expr="value>"0" && value<"10" ?"valid":"error"">valid</calcul>
<norm attr=" ' 
	 ' "></norm>
<Names attr="A 
	 B"></Names>
<Id id="' 
	 '"></Id>
</Arrel> |
Taula
14
: Ex4FormaCanonica.xml
Cal remarcar que tots els caràcters del tipus "#x." han estat substituïts per la seva referència, per exemple el caràcter #xD s'ha substituït per 
. Per altra banda els valors d'atributs introduïts per cometes dobles han passat a ser introduïts per cometes simples, s'ha normalitzat el valors dels atributs, s'ha substituït l'element CDATA pel seu contingut, s'han substituït els caràcters especials per les seves referències tant en els atributs com en el text, per exemple & per & .
Exemple 5: el document de partida és el següent
|
<!DOCTYPE doc [
<!ATTLIST doc attrExtEnt ENTITY #IMPLIED>
<!ENTITY ent1 "Hola">
<!ENTITY ent2 SYSTEM "mon.txt">
<!ENTITY entExt SYSTEM "earth.gif" NDATA gif>
<!NOTATION gif SYSTEM "viewgif.exe">
]>
<Arrel attrExtEnt="entExt">
&ent1;, &ent2;!
</Arrel> |
Taula
15
: Ex5FormaNoCanonica.xml
(El fitxer mon.txt conté la cadena "mon".)
El resultat de passar a forma Canònica el document és la següent:
|
<doc attrExtEnt="entExt">
Hola, mon!
</doc> |
Taula
16
: Ex5FormaCanonica.xml
Cal remarcar que s'han tret totes les definicions de tipus de documents i s'han substituït totes les referències a entitats pel seu valor. Fins i tot amb el contingut del fitxer mon.txt.
Exemple 6: el document de partida és el següent:
|
<?xml version="1.0"?>
<Arrel>
<nivell1 xmlns="http://www.guim.net"
xmlns:a="http://www.guim.net/xml">
<llibres id="1" xmlns:b="http://www.guim.net/llibre">
<llibre>XML</llibre>
<llibre>XSL</llibre>
<llibre>XSLFO</llibre>
</llibres>
<llibres id="2"/>
</nivell1>
<nivell2 xmlns="http://www.guim.net"
xmlns:a="http://www.guim.net/rdf">
<llibres id="1"/>
  |