In IHE and HL7, we've been using the <templateId> element to identify templates. One of the challenges has been that creating a new version of a template changes the requirements of any templates that use that template. Consider the case where an implementation guide has two templates, template A, and template B, and template A says: must contain [n..m] instances of template B. Making a substantive change to the content of template B means that it must have a new identifier. We'll use B' in this case.
So now, template A must say: must contain [n..m] instances of template B'. But this too is a substantive change to template A, and so template A must be given a new identifier (template A'). And so the change propagates upwards through the entire document. This may be desirable in some cases, but in others, it totally sucks.
When we started with template identifiers in HL7, we did something this:
Later, we shifted to this form:
Dropping the extension attribute, and just uniquely identifying the template with the root attribute.
Some have suggested going back to using the extension attribute, but using it to represent the "version" of the template. Originally, I thought this was a bad idea, because it semantically overloads the extension attribute. I've changed my mind somewhat, because this is a useful a convention, or best practice, rather than semantics. What we are doing is saying that: root represents an identifier for the the concept expressed by the template, and extension represents different ways (versions) that this concept can be expressed.
Using versions, we can write templates a bit differently. Consider our template A above. Suppose we had written it instead as template A: must contain [n..m] instances of templates whose root is B.root. Now, when we create a new version of B, B.root will remain the same (because the template expresses the same context), but B.extension will be different. We could also fix to a particular version, as in: A must contain [n..m] instances of template whose root is B.root and whose version is B.extension. Or we could set a lower bound on the version of the template.
Ideally, data types would allow template identifiers to support versioning, just as code systems and value sets can be versioned, but it doesn't. So, we can make a gentleperson's agreement to deal with root and extension in this fashion.
A disadvantage of this scheme is that a system that only knows how to address version 1.0 the content of template B, won't know what to do with version 2.0 when it encounters it. Furthermore, it can no longer just look at the document template to see whether it knows how to deal with all of the templates inside of it. So, you'd need to look at more than just the document template to understand whether you can deal with all of the content.
I've got some thoughts on how to generate a CDA document that uses two different versions of (wire-format incompatible) templates, but I'll save that for tomorrow.