Foto av Sofia Jonsson

Versionshantering av XML Scheman

// Sofia Jonsson

Jag har under den senaste veckan återigen ägnat mig åt ett ständigt återkommande problem, nämligen versionshantering av XML Scheman. Denna gång inom ramen för Websphere Message Broker (WMB) och dess meddelandedefinitioner, som är XML Schema-baserade.

Ett vanligt återkommande krav i sammanhanget är vad man skulle kunna kalla “framåtkompatibla” scheman. Det man vill åstadkomma är möjligheten att kunna lägga på ytterligare optional-element utan att de som validerar med en äldre version av schemat för den sakens skull stöter på problem. 

I web service-sammanhang vill man t ex ofta ha möjlighet att utöka sitt interface med extra output-element utan att de klienter som genererats med tidigare versioner av WSDL och XML Schema skall sluta fungera. De klienter som är intresserade av de nya elementen genererar om sin kod, medan övriga klienter förblir lyckligt ovetandes om förändringen. 

De flesta som jobbat med versionshantering av XML Scheman är troligtvis bekanta med användandet av “any”-definitioner för att uppnå detta:

<xsd:sequence>
  <xsd:element name="foo" type="xsd:integer" minOccurs="0"/>
  <xsd:any minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
</xsd:sequence>

Trots att många XML-parsers och -bindningsimplementationer gladeligen sväljer ovanstående (däribland WMB) kan det vara viktigt att påminna sig om att det egentligen inte 100% korrekt. Enligt Unique Particle Attribution får varje element i ett XML dokument endast ha en möjlig tolkning. I fallet ovan skulle ett element, <foo>1</foo>, kunna tolkas både som att det hör till <xsd:element name="foo" .../> och till <xsd:any .../>.

Många parsers (enligt min erfarenhet de flesta) ser “mellan fingrarna” när det gäller just any-konstruktioner men t ex JAXB 1.0 tillåter inte ovanstående. Har man inte full kontroll över vilken bindningsimplementation som ens klienter kommer använda sig av finns det alltså anledning att vara försiktig. Ett sätt att få till en helt korrekt syntax är att låta alla utökningar höra till ett nytt namespace. Korrekt notation i ursprungsschemat blir isåfall: 

<xsd:sequence>
  <xsd:element name="foo" type="xsd:integer" minOccurs="0"/>
  <xsd:any minOccurs="0" maxOccurs="unbounded" processContents="lax"
      namespace="##other"/>
</xsd:sequence>

Alla utökningar måste därmed definieras i ett nytt XML Schema. Den här strategin leder till uppsplittrade scheman som är allmänt svårlästa och jobbiga att underhålla.

Glädjande är att JAXB 2.0, som är standard för Web services i Java EE 5, är betydligt mindre strikt och släpper igenom den översta konstruktionen. Ännu mer glädjande är att i version 1.1 av XML Schema-specen så ser det här problemet äntligen ut att vara helt borta. I den draft som finns ute är det tydligt uttalat att “riktiga” element-definitioner alltid ska gå före any, vilket är precis i linje med hur de flesta “vettiga” parsers och bindningsimplementationer har fungerat hela tiden!

Kommentarer