Ch.medelexis.xchange.feature.feature.group

From Elexis-Wiki
Jump to navigation Jump to search
Medelexis logo klein.jpg
Version: 3
Kategorie: Datenaustausch
Beschreibung:
Author:
Letzte Bearbeitung: 17. Juni 2014
Voraussetzungen: Elexis 3.0
Betriebssystem: Windows, Mac, Linux
Lizenz: Proprietär



xCHange – an XML based technique to exchange data between electronic medical record systems

Copyright notice: This file and all accompanying materials are copyright© 2010 by Medelexis AG, Baden, Switzerland. Copying, using and redistribution are allowed free of charge as long as the contents and this copyright notice remain unchanged.


Background

Exchange of data between medical record programs is quite difficult in Switzerland. Unlike their respectives in other countries, swiss health officials never enforced standardizing of documents held in electronic medical record systems. So, frequently the sender will print documents on paper, send them by mail, and the receiver scans the documents in. Of course, this is not the best way to transfer data that are present in digital form already.

In 2007, SGAM.Informatics created a project called xChange (see http://www.primary-care.ch/pdf/2007/2007-16/2007-16-169.PDF). The goal of this project was, to prove that digitally encrypted exchange of not standardized medical data between swiss EMR systems is possible. xCHange is a continuation and extension of this project.


Objectives

We introduce a concept to exchange and assign data correctly to medical entities without enforcing a standardized document structure and without enforcing a certain programming language or a certain operating system.

Structure

Overview

xCHange consists of a formal structure description and a set of processing instructions. xCHange does not require a certain operating system or a specific programming language or runtime platform. The concepts and structures used are compeletely generic and based on widely adopted standards such as XML and ZIP.

Identifiers

Recognizing data identity is one of the maior challenges in medical data exchange. We can have (and quite often do have) the same object stored in different environments with different identifiers. If we transfer such objects from one system to another, we must decide whether an object belongs to or is an already existing entity. If a patient is transmitted from a primary care physician to a hospital or a specialist, a report will be generated and eventually sent back to the original referrer, or to another specialist or maybe a different family doctor, if the patient decides to change. So how can we make sure, that the report is assigned automatically to the correct patient, given the fact that name and birthdate are not unique and are spelled differently sometimes or even may change during life? How can we make sure, that an imported lab value belongs to a lab item in our system? How can we let the computer recognize, that a document labelled “Thorax” belongs to a document class that is called “chest x-ray” in our system? These identifiers are not standardized at all.

The simple yet frustrating answer to all these questions is: We can’t. At least not always. A computer system can make some educated guess about the identity of an Object and can make an automated decision on how safe this guess might be. The user of the system may define some threshold. If the probability of its guess falls below that threshold, the computer must always ask a skilled human to help. Our goal is, to minimize the need for such human interaction. The following sections explain the xCHange approach.

Linking object identifiers

Objects used in an EMR System frequently do have many identifiers before they first come to our user’s practice. A Patient might be identified by a Social Security Number, by a Health Insurance Card Number, by a Passport Number, an AHV Number and many more. If the patient comes to a physician’s practice, he or she will receive yet another identifier: the Patient-Number of the physician’s file system or database.

To make use of preexisting identifiers and deal with the identification problems while exchanging EMR data, xCHange introduces the concept of a XID (eXternal Identifier). A XID is an identifier that consists of one or more pairs of domain/id values. A Domain is a String describing the classification system. An ID is a String that describes the given object within this classification system uniquely.

XIDs can easily be expressed as XML Elements. The formal description is in the appendix (XID.xsd)
Here we demonstrate some features with an example:

 
 <xChange:xid id="www.xid.ch/ahv/123.45.67">
    <xChange:identity date="2010-04-01" domain="www.xid.ch/ahv" domainID="123.45.67" isGUID="false" quality="regional"/>
    <xChange:identity date="2009-12-23" domain="www.elexis.ch/patientUID" domainID="0345dswe4553212344" isGUID="true" quality="local"/>
 </xChange:xid>

As you can see. this is a XID with two identities: An AHV number (Swiss ssn) and a patient ID from an EMR System. The AHV number has “regional” quality whereas the EMR ID only has a local quality.On the other hand, the EMR ID is a GUID i.e. is a globally unique identifier (The algorithm of GUID generation guarantees that there is only one person in the world with this GUID. The AHV-Nr. is not a GUID since its generation algorithm does not guarantee uniqueness.)

Combining XIDs

Now consider we import a patient admission from a collegue. The data file identifies the patient being

Foo, Barbara, female dob 10/3/1969, living in Xidikon (1)

In our database we have a patient

Foo-Baz, Barbara, female, dob 3.10.1969, living in Xid City (2)

The two records have different addresses but quite similar names and birth dates. Do they denote the same person?

Let’s look at the XIDs.
(1)

 <xChange:xid id="www.xid.ch/ahv/123.45.69.345">
    <xChange:identity date="2008-07-01" domain="www.xid.ch/ahv" domainID="123.45.67" isGUID="false" quality="regional"/>
    <xChange:identity date="2008-12-23" domain="www.elexis.ch/patientUID" domainID="0345dswe4553212344" isGUID="true" quality="local"/>
    <xChange:identity date="2007-10-12" domain="www.xid.ch/kk/SomeInsurance" domainID="22345565" isGUID="false" quality="regional"/>
 </xChange:xid>

(2)

<xChange:xid id="www.xid.ch/ahv/125.66.69.180">
    <xChange:identity date="2010-04-01" domain="www.xid.ch/ahv" domainID="125.66.69.180" isGUID="false" quality="regional"/>
    <xChange:identity date="2009-12-23" domain="www.SomeEMR.ch/patientUID" domainID="778derggf412344" isGUID="true" quality="local"/>
    <xChange:identity date="2009-10-12" domain="www.xid.ch/kk/SomeInsurance" domainID="22345565" isGUID="false" quality="regional"/>
 </xChange:xid>

As we can see, the AHV is different. This does not prove anything, because the AHV used to change with marriage until recently. We have also Patient ID’s from different EMR systems, which don’t help either. But we are lucky: The person has the same insurance and the same insurance number. Thus the Computer can figure out that the two records denote the same person. Knowing this, it will combine the XIDs:

<xChange:xid id="www.xid.ch/ahv/125.66.69.180">
    <xChange:identity date="2010-04-01" domain="www.xid.ch/ahv" domainID="125.66.69.180" isGUID="false" quality="regional"/>
    <xChange:identity date="2009-12-23" domain="www.SomeEMR.ch/patientUID" domainID="778derggf412344" isGUID="true" quality="local"/>
    <xChange:identity date="2009-10-12" domain="www.xid.ch/kk/SomeInsurance" domainID="22345565" isGUID="false" quality="regional"/>
    <xChange:identity date="2008-12-23" domain="www.elexis.ch/patientUID" domainID="0345dswe4553212344" isGUID="true" quality="local"/>
 </xChange:xid>

Doing so it omitted the elder version of the AHV and imported the other identifiers. If the record is to be exported at a later time, it will carry more information. And if it happens to be reimported in SomeEMR where this patient resides already, the system will instantly recognize the record (The PatientUID is a GUID and therefore it is safe to assume that two records having the same PatientUID from the same domain denote the same Person).

The only thing the computer can not resolve is the different birth date. Thus the system will mark it as conflicting to be resoved by a human.

After the XID is resolved and the patient record is matched or created, the payload of the transfer, e.g. lab values, a letter or an x-ray, can be imported correctly. If there had been no matching identity, the importer would have to ask the user. The formal algorithm for merging XID’s is described in the appendix.

Adapting and evolving XID’s

XID’s are not limited to persons. Most objects transferred with xCHange carry a XID with at least one identity. Such XIDs help classifying imported objects of different kinds. This extension to basic XIDs is called ASIMED.

The key idea is: Not all physicians classify all objects identically. A radiologist will probably classify a document as belonging to “ultrasound/abdomen”. A familiy practinioner receiving this document will file it probably just as “ultrasound”. Or even as “external image”. Now he admits the patient to a surgeon. The EMR system of the surgeon has probably no category called “external image” so it does not know how to classify the incoming document.

There have been many approaches to this problem, most of them using more or less elaborate classification systems (like HL7 CDA, SNOMED), LOINC® and others). These approaches, while being sophisticated and well designed, lack on the failure of today’s EMR systems to produce such classifications automatically. These days, the average medical report comes in as Adobe™ pdf or Microsoft™ Word™ document which has of course no classification information at all. This leaves the task to apply the correct classification to the user of the importing system which may be quite tedious given the enormous size of such classifications (SNOMED has more than 80’000 entries). Moreover: Such classification forces a physician to use a standardized classification system, while he or she probably would rather use some filing matching his/her usual workflow. In fact, it does not make much sense, if, say, a dermatologist, uses the same granularity for classification of x-rays, as a radiologist.

Therefore, xCHange uses a quite different approach: If the importing system does not know how to file an incoming or newly created document, it has to ask the user. The user will apply his/her very own classification. On export, however, this classification is sent along with the document as a hint to the next importing system. If some systems apply different classifications to a document, all these classifications are kept. Over time, the classification information becomes more and more accurate and makes it possible to file documents automatically after some such evolutionary steps.

Of course, in real life, most documents will not be exchanged very frequently and thus carry only few classification metadata. But if a document happens to travel enough to become cluttered with lots of incompatible classification metadata, there is an evolutionary process that removes older and less frequently used entries over time.

Let’s see an example. Consider this document:

<?xml version="1.0" encoding="UTF-8"?>
<xChange:xChange authorization="implicit" destination="34567778993c" id="2345456675ugt" origin="3234325fdghhjju" responsible="443546788987rtzr" timestamp="2010-01-31T12:00:00" xmlns:xChange="http://informatics.sgam.ch/xChange" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://informatics.sgam.ch/xChange xchange.xsd ">
  <xChange:header creatorID="ew54r345346erztt6567" creatorName="elexis" creatorVersion="2.1" language="de_CH" protocolVersion="2.0"/>
  <xChange:contacts>
    <xChange:contact birthdate="1967-04-23" firstname="Barbara" lastname="Foo-Baz" sex="f"  type="person">
    <xChange:xid id="www.xid.ch/ahv/125.66.69.180">
    <xChange:identity date="2010-04-01" domain="www.xid.ch/ahv" domainID="125.66.69.180" isGUID="false" quality="regional"/>
    <xChange:identity date="2009-12-23" domain="www.SomeEMR.ch/patientUID" domainID="778derggf412344" isGUID="true" quality="local"/>
    <xChange:identity date="2009-10-12" domain="www.xid.ch/kk/SomeInsurance" domainID="22345565" isGUID="false" quality="regional"/>
    <xChange:identity date="2008-12-23" domain="www.elexis.ch/patientUID" domainID="0345dswe4553212344" isGUID="true" quality="local"/>
 </xChange:xid>
      <xChange:address city="Xidikon" country="CH" description="home" street="xidstreet 25" zip="9999"/>
      <xChange:contactref description="" refID="idvalue0"/>
      <xChange:medical>
        <xChange:documents>
          <xChange:document date="2010-01-30" destination="3234325fdghhjju"  origin="3234325fdghhjju" title="sono-2010-01-30-012">
           <xChange:xid id="35466756ztrz6578">
              <xChange:identity date="2010-01-30" domain="www.SomeHospital.ch/PACS_ID" domainID="21344545656tz6" isGUID="true" quality="local" usage="0"/>
              <xChange:identity date="2010-01-30" domain="www.xid.ch/ASIMED/3234325fdghhjju" domainID="documents/radiology/sonography/room1/abdomen" isGUID="false" quality="local" usage="0"/>
           </xChange:xid>
        <xChange:hint>Ultraschallbefund</xChange:hint>
         <xChange:contents mimetype="application/pdf"  placement="infile">NameOfTheFileInTheContainer.pdf</xChange:contents>
        </xChange:document>
        </xChange:documents>
      </xChange:medical>
    </xChange:contact>
    <xChange:contact firstname="Alfred" lastname="Test"  salutation="Herr"  title="Dr. med." type="person">
      <xChange:xid id="34567778993c">
        <xChange:identity date="2005-11-17" domain="www.SomeEMR.ch/UIDs" domainID="34567778993c" isGUID="true" quality="local" usage="0"/>
      </xChange:xid>
      <xChange:address city="Xidikon"  description="work" street="Doctor's House" zip="9999"/>
    </xChange:contact>
    <xChange:contact  lastname="Xid Care Hospital" type="organization">
      <xChange:xid id="3234325fdghhjju">
        <xChange:identity date="2002-05-22" domain="www.SomeEMR.ch/UIDs" domainID="3234325fdghhjju" isGUID="true" quality="local" usage="0"/>
      </xChange:xid>
      <xChange:address city="Xidikon"  description="work" street="Healthness Boulevard" zip="9999"/>
    </xChange:contact>
  </xChange:contacts>
  /xChange:xChange>

This is a valid xCHange document. As you can see, it is an ultrasound result, sent from the Xid Care Hospital to Dr. Alfred Test.

After the header follows the person information as discussed earlier, to help the importing system to assign the document to the correct patient record. Below follow the document metadata.

On importing such a document for the first time, the importing system does not know how to handle it. It looks for the ASIMED identities and finds none matching its own classification system. So, depending on its system design or user preference, it would place this document into some sort of inbox to be processed later, or it will immediately ask the user to give informations on how to store this document. The user will probably file it in “documents/findings/ultrasound”. Knowing this, the system will add an ASIMED record to the document. The document metadata will then look like this:

 <xChange:document date="2010-01-30" destination="3234325fdghhjju" mimetype="application/pdf" origin="3234325fdghhjju" placement="infile" subject="ultrasound abdomen" title="sono-2010-01-30-012">
  <xChange:xid id="35466756ztrz6578">
    <xChange:identity date="2010-01-30" domain="www.SomeHospital.ch/PACS_ID" domainID="21344545656tz6" isGUID="true" quality="local" usage="0"/>
    <xChange:identity date="2010-01-30" domain="www.xid.ch/ASIMED/3234325fdghhjju" domainID="documents/radiology/sonography/room1/abdomen" isGUID="false" quality="local" usage="0"/>
    <xChange:identity date="2010-01-31" domain="www.xid.ch/ASIMED/34567778993c" domainID="documents/findings/ultrasound" isGUID="false" quality="local" usage="0"/>
  </xChange:xid>
  <xChange:hint>Ultraschallbefund</xChange:hint>
</xChange:document>

If the document is exported later again, both ASIMED identities will be sent along with it, and the next importing system has two hints on how to import t. If an import happens to use a classification that already has an ASIMED record, this record’s usage value will be increased thus promoting this record to a higher priority in the next transfer.

It’s the law

In some cases, a certian classification system is required by law or professional rules. In these cases, the system should prefer the legal classification over individual concepts. This is achieved by introducing an ASIMED/authoritative record. If such a record is found on an object, this record will always have precedence over all other ASIMED records. The user can still override manually, if he or she wishes to do so.

ASIMED profiles

Sometimes one wants to import several data at once. If we want to transfer whole EMR data from one program to another, it would be quite annoying to manually classify every single of some thousand documents. Therefore it is possible to define translations in advance in a so called “ASIMED profile”. For example we can define a profile for converting data between the systems EMRx and EMRy. We might define, that documents/findings/x-ray/chest from EMRx will always be placed in documents/x-ray in EMRy. Such profiles can even learn new assignements: The user must assign the first object of a given type manually and can define that this assignment should be used for all subsequent objects of the same type. A profile is always valid for exactly one pair of Sender/Receiver and is not valid inversely.

container structure

unencrypted container

An unencrypted xchange container is essentially a ZIP file containing an XML document with the name xchange.xml and zero or more accompanying files. It is suggested to use the suffix .xchange for such files but this is not enforced.

The file xchange.xml contains all informations necessary for import. If there are accompanying files in the container, they are always referenced by metadata found in xchange.xml.

The formal definition of xCHange is in the appendix. Here we discuss some features with an example.

General considerations:

The container declares a header, one ore more contacts and zero or more documents. A contact is any person or organization that can be referenced in the file.
Every object is identified by a XID and has an ID attribute to be referenced within the file. Every XID has at least one identity that is a GUID. A GUID is a character sequence that is guaranteed to exist only once in the world.

<?xml version="1.0" encoding="UTF-8"?>
<xChange:xChange authorization="explicit" destination="some-contactref-1" id="Some-GUID-1" origin="Some-contactref-2" responsible="Some-contactref-3" timestamp="2010-04-21T12:00:00" xmlns:xChange="http://informatics.sgam.ch/xChange" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://informatics.sgam.ch/xChange xchange.xsd ">
  <xChange:header creatorID="Some-GUID-4" creatorName="elexis" creatorVersion="2.1" language="de" protocolVersion="2.0"/>

The beginning of the files declares the xml and some basic values.

  • Authorization: The sender of medical informations must declare, that he is authorized to do so. Authorization can be excplicit (patient has been asked), implicit (e.g. admission of the patient to a hospital) or not required (if the document does not contain sensitive data)
  • destination: A reference to a contact within the same file, that is the receiver of this container.
  • id: a GUID defining this container uniquely.
  • origin: A reference to a contact within the same file that is the sender of this container.
  • responsible: A reference to a contact that must be a person which is directly responsible for sending this container (can be the same as in “origin”)
  <xChange:contacts>
    <xChange:contact birthdate="1967-10-11" firstname="Barbara" lastname="Foo-Baz" middlename="Teresa" salutation="Mrs." sex="f" shortname="Barb" title="MD" type="person">
      <xChange:xid id="some-GUID-2">
        <xChange:identity date="2010-04-10" domain="www.elexis.ch/PatientUID" domainID="Some-GUID-2" isGUID="true" quality="local" usage="0"/>
      </xChange:xid>
      <xChange:address city="Xidikon" country="CH" description="home" street="thatstreet" zip="9999"/>
      <xChange:contactref description="orthopedist" refID="some-GUID-3"/>

The contacts-element encloses all contacts defined in the file. A contact can be a person or an organization. A contactref is a reference to a different contact in the same file.

      <xChange:medical>

If a contact has a medical-element, this contact is by definition a patient. The medical element contains all patient-related data, including patient-related documents (in opposite to the top-level-documents in the xchange container)

        <xChange:episodes>
          <xChange:episode beginDate="2000-03-21" endDate="" id="SomeGUID-4" name="Hyperlipidemia">
            <xChange:diagnosis code="F9" codesystem="TI-Code" text="Stoffwechselkrankheit"/>
            <xChange:insurance companyref="Some-contactref-3" dateFrom="2001-01-01" dateUntil="" publicDiagnosis="Stoffwechsel" reason="disease">
              <xChange:contract caseID="23445667" country="CH" name="KVG"/>
            </xChange:insurance>
          </xChange:episode>
        </xChange:episodes>

xCHange organizes the medical record with episodes. An episode is a distinct problem of the patient that has always a begin date and probably an end date.

        <xChange:records>
          <xChange:record author="Some-contactref-5" date="2010-02-28" id="Some-GUID-6" responsible="Some-contactref-6">
                      <xChange:episode ref="Some-episoderef-1"/>
          </xChange:record>
        </xChange:records>

records are the textual descripions of encounters. A record can reference one or more episodes and can contain arbitrary an possible structured entries.

 
        <xChange:findings>
          <xChange:finding  id="Some-GUID-7" name="RBC" normRange="3.5-5.2" type="numeric" unit="G/l">
            <xChange:xid id="idvalue5">
              <xChange:identity date="2001-01-01" domain="www.xid.ch/labvalues/viollier" domainID="RBC" isGUID="false" quality="regional" usage="0"/>
              <xChange:identity date="2010-01-01" domain="www.xid.ch/ASIMED/Some-GUID-1" domainID="findings/labValues/hematology" isGUID="false" quality="local" usage="0"/>
            </xChange:xid>
          </xChange:finding>
        </xChange:findings>

Findings are semantically somewhat overlapping with documents since a document can also describe a finding. A finding sensu strictu is here an value that can be expressed as number or boolean (normal/abnormal) . In some cases, an application can decide to send a result as document whereas an other application would send the same result as a finding. xCHange allows some ambiguity.

        <xChange:documents>
      <xChange:document date="2010-01-30" destination="3234325fdghhjju"  origin="3234325fdghhjju"   title="sono-2010-01-30-012">
           <xChange:xid id="35466756ztrz6578">
              <xChange:identity date="2010-01-30" domain="www.SomeHospital.ch/PACS_ID" domainID="21344545656tz6" isGUID="true" quality="local" usage="0"/>
              <xChange:identity date="2010-01-30" domain="www.xid.ch/ASIMED/3234325fdghhjju" domainID="documents/radiology/sonography/room1/abdomen" isGUID="false" quality="local" usage="0"/>
           </xChange:xid>
        <xChange:hint>Ultraschallbefund</xChange:hint>
        <xChange:contents placement="infile" mimetype="application/pdf">NameOfTheFileInTheContainer.pdf</xChange:contents>
        </xChange:document>

This Element contains all patient-associated documents. A similar Element is on top level for non-patient associated documents. Here we sa an document of type pdf which is stored outside of this xml-file within the same xCHange-Container (placement=“infile”)

        <xChange:medications>

List of all medications

        <xChange:risks>

List of risk factors

      <xChange:financial billedTotal="0.0" dateFrom="2001-01-01" dateUntil="2001-01-01" lostTotal="0.0" paidTotal="0.0">

financial informations

Note that only header and at least one contact element are required. All other elements can be omitted if not necessary.

custom extensions

Sometimes, an EMR system might want to store more information than possible within the limited xCHange structure. This might be some private information that is useful only for other EMR Systems of the same brand and should therefore not bother others. We have two possibilities to achieve this: First, all xCHange elements have an optional Element called “Meta” that can exist zero or more times. It contains arbritrary key/value pairs. Second, it is always possible to store a file with arbitrary content along with the xchange.xml in the xchange-container. Thus, a Meta Element might carry a link to some external file that contains arbitrary data as needed.

encrypted container

An encrypted xchange container is an unencrypted container wrapped into an encryption envelope (see chapter Encprytion). The envelope is defined as follows: (Syntax: RFC 2234: Augmented Backus Naur Form):

<envelope>   = <header><data>
 <header>    = "xCHange*" <version> <enctype>
 <version>   = 2OCTET     ; xCHange Version as major/minor e.g. 0x100 for 1.0 or 0x0f0a for 15.10
 <enctype>   = 4CHAR     ; Encryption method used. At this time always 'XCH1'
 <data>      = *OCTET       ; encrypted container. Contents and interpretation depending on encryption method

Encryption

xCHange by itself does not make any assumptions on encryptions. Encryption of the xCHange container is a separate process that does not logically modify the contents of the container. At the moment beeing, an encryption scheme very similar to other standard applications is used: a PKI is used to exchange public key portions of the key pairs for an asymmetric encryption method.

The encrypting application

  1. creates a hash over the xCHange container
  2. signs this hash with its private key
  3. creates a random session key
  4. uses this session key to encrypt the container and the hash
  5. obtains the public key of the receiver
  6. encrypts the session key with this key
  7. creates a file containing an xCHange-Header followed by the data

The decrypting application

  1. reads the file header and checks for conformity
  2. uses its private key to decrypt the session key
  3. uses this session key to decrypt the data portion
  4. uses the sender’s public key to verify the hash over the container

The XCH1 encryption method

This is at this time the only encryption method defined. It uses RSA/ECB/PKCS1Padding for asymmetric key encryption, SHA512/RSA for signature and Blowfish for symmetric data encryption. The structure of the encrypted container is defined as follows (Syntax: RFC 2234: Augmented Backus Naur Form):

<data>       = %xefde.%x0102.<key>.1*<block>
<key>         = %x0010.<length>.*OCTET  
<block>      = %x0030.<length>.*OCTET 
<length>    = %x00000000-%xffffffff      ; little endian format

Processes

xCHange transfer must deal with the following difficulties:

  • We do not know what kind of application the sender uses.
  • We do not know what kind of application the receiver uses
  • we do not know what kind of documents the sender will send
  • We do not know what kind of documents the receiver can handle

Obviously, we must chose a quite generic approach. The sender might collect personal data from his billing software and an x-Ray DICOM from his PACS. The receiver might have an all-in-one EMR system instead that can handle all kinds of documents (but is not specifically able to handle DICOM images). Thus, our generic approach relies onf the concepts of

  1. a “Collector” instance, i.e. a device or program that asks all registered applications to contribute to a pending export,
  2. a “Transporter” instance, i.e. a device or program that transfers the collected data to a receiver
  3. a “Dispatcher” instance, i.e. a device or program that asks all registered applications for every received data object, how they can handle this kind of data.

xCHange makes absolutely no assumptions on the implementation of such devices. The sample application, however, is an OSGi platform that is extensible by plugins and communicates via OSGi means. It can easily be extended to a Webservice that communicates via SOAP. The basic concepts are explained in the following sections.

Exporting data: The Collector

Every application or plugin that wants to export data via xCHange must register itself with the xCHange-Collector as a sender. If the user selects a data object (say, a document or a lab value or a whole patient record) for export, the Collector asks all registered senders to contibute data to this object. A sender can just skip or can attach its data in a transportable form. After all senders are finished, the Collector shows the user, what can be exported. The user can manually select or deselect some of the proposed entities.

The Collector then packs all data objects into an xCHange container and passes this container over to the Transporter.

Transporting data: The Transporter

The Transporter asks the user for the destination and the path of the transport. Care must be taken, because the container carries sensitive data. So all Transfers must be either encrypted or under full control of the patient him/herself. Following paths are defined:

  • The container is moved to a mobile storage device. In this case, it must be encrypted because the device might get lost. Typically, we will ask the Patient for a password of his/her choice, encrypt the container symmetrically with that password and hand it over to the patient. The receiver asks the patient for the password and is then able to decrypt the container.
  • The container is sent via e-mail through an encrypted tunnel. This is the case with ASAS clients in Switzerland. In this case, sender and receiver are identified via the HIN-ASAS PKI and the mail is sent end-to-end encrypted, if both, sender and receiver, are ASAS users. In this case, The transporter can leave the container unencrypted.
  • The container is sent via normal e-mail. In this case, the Transporter must encrypt the container via asymmetric encryption. It must retrieve the receiver’s public key, and the receiver must be able to retrieve the sender’s public key (to verify the signature). Transport via unsecured e-mail is only allowed if these requirements are met.

Importing data: The Dispatcher

Every application or plugin that wants to receive data from xCHange must register itself with the xCHange-Dispatcher as a receiver.

The xCHange-Dispatcher receives the (possibly enrypted) container, unpacks it and parses the enclosed xchange.xml. For every data object found, it calls each registered receiver if and how it can handle this data. If more than one receiver can handle a given object, a competition takes place, as described below, and the winner will get the object.

A receiver must manage all aspects of XID matching, extending and ASIMED dynamic classification for the objects it handles.

Competition: Finding the Right One

Typically in a real-world-practice environment, there will be more than one receiver, that can handle a cretain data type. Possibly a pracitioner first bought an all-in-one EMR system with a built-in document management system that handles all sorts of documents. Later, the user buys a more sophisticated document management system, and a digital x-ray equipment that comes with a PACS. Now we have (at least) three different applications that register themselves as xCHange importers. They do not necessarily know anything about each other, so each importer “thinks” it is the only one. On importing of, say, an X-Ray, the Dispatcher will ask all importers, whether they can handle it, and all will answer confidently “Yes, I can!”. So we would end up having imported the X-Ray three times. Or imported by an application that in fact is not the best available choice for such images.

As expected, xCHange has a flexible way to come around these problems. First, if the Dispatcher asks, the importers will not answer simply yes or no, but rather with a number indicating how well it can handle the object in question. A Number of 0 will mean “No, I can’t handle this at all”, a Number of 1 says “Ok, if no other stands ready, I’ll take it” while 1000 means “Hey, that’s my job! Trust me!”. In fact, the values can be even higher. Now if there is a clear difference between all applicants, the Dispatcher will chose the best one. If two ore more are similarly rated (e.g. less dan 50 points difference), the Dispatcher will ask the user, which one to take. The importer the user choses for this import will get then a rating bonus of 10 for this kind of data. So, next time, the importer probably can guess the user’s preference without asking.

Alternatively, the user can also decide to define a static association. He or she can declare, that images should always be handled by the image database and so on. In this case, the chosen application will get a bonus of 1000 points for the indicated type of data.

Process instructions

Besides the structural definition, processing instructions are a vital part of the xCHange definition. We need a well defined way to handle and merge XID’s, ASIMED’s and so on. Thus, following the instructions here is mandatory for an xCHange implementation.

XID Matching

Purpose: To decide whether two XIDs denote the same object

The decision is based on a Score that is computed from a prevalent estimate and the identities of the XIDs. A Score of 1000 means that the two objects are identical for sure and a score of 0 means, they are not identical for sure. Usually there will be a threshold declared by the user of the application, that is needed to regard to objects as identical. Let’s say we handle Objects with a matching score of 900 or more as being identical.

Pretest probability

Some times, an application can tell without using XIDs wether two objects are identical. At least with a certain level of confidence. This depends on the nature of the objects involved. If the objects are patient records, identical name and first name would rise the pretest probability to say 300. If also the birth date is same, it might be as high as 700, and if they have the same address we would end up with a pretest probability of 990 and so don’t have to make XID matching at all. This is, of course, only an example with arbitrary values. Calculating pretest probability is a task entirely for the importing application using its own rules.

Test procedure

When comparing two XIDs (XIDa and XIDb), matching involves the following steps:

(1) take pretest probability as score

(2) Repeat for all identities of XIDa except ASIMED identities:

  • Find identity with same domain in XIDb
    • if found: compare ID’s
      • if same:
        • if it is a GUID: add 500 to the score
        • if it has regional assignment: add 300 to the score if both objects originate from the same region
        • if it has global assignet: add 400 to the score
        • if it is of local assignment and is not a GUID, no score

(3) Compare score with predefined threshold. If above: take the two objects as equal

XID merging

If two objects are recognized to be identical, their XIDs must be merged to a single resulting XID. This involves the following steps:

  • for each identity of XIDa (including ASIMED):
    • if an identity with same domain exists in XIDb: retain the newer one and discard the other.
    • if no identity with same domain exists in XIDb: retain this identity

Appendices

xCHange.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://informatics.sgam.ch/xChange"
    elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xChange="http://informatics.sgam.ch/xChange">
    <xs:include schemaLocation="xid.xsd"></xs:include>
    <xs:include schemaLocation="service.xsd"></xs:include>
    <xs:annotation>
        <xs:documentation>xChange Version 2.0.0</xs:documentation>
    </xs:annotation>
    <xs:element name="xChange" type="xChange:xChangeDescriptor" />
    <xs:complexType name="addressType" mixed="true">
        <xs:attribute name="description" type="xs:string">
            <xs:annotation>
                <xs:documentation>
                    a description describing the addresse, e.g "home"
                    or
                    "work". Defaults to "default"
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="street" type="xs:string"></xs:attribute>
        <xs:attribute name="zip" type="xs:string"></xs:attribute>
        <xs:attribute name="city" type="xs:string"></xs:attribute>
        <xs:attribute name="country" type="xs:string"></xs:attribute>
    </xs:complexType>
    <xs:complexType name="xChangeDescriptor">
        <xs:sequence>
            <xs:element name="header" type="xChange:headerType"
                maxOccurs="1" minOccurs="1">
            </xs:element>
            <xs:element name="contacts" type="xChange:contactsListType"
                maxOccurs="1" minOccurs="1">
            </xs:element>
            <xs:element name="documents" type="xChange:documentListType"
                maxOccurs="1" minOccurs="0">
            </xs:element>
        </xs:sequence>
        <xs:attribute name="id" type="xs:ID" use="required"></xs:attribute>
        <xs:attribute name="origin" type="xs:IDREF" use="required"></xs:attribute>
        <xs:attribute name="destination" type="xs:string" use="optional">
        </xs:attribute>
        <xs:attribute name="timestamp" type="xs:dateTime" use="required">
        </xs:attribute>
        <xs:attribute name="responsible" type="xs:IDREF" use="required">
        </xs:attribute>
        <xs:attribute name="authorization" type="xs:string" use="optional">
        </xs:attribute>
    </xs:complexType>
    <xs:complexType name="xChangeContactType">
        <xs:sequence>
            <xs:element name="xid" type="xChange:XIDType" maxOccurs="1"
                minOccurs="1">
            </xs:element>
            <xs:element minOccurs="0" maxOccurs="unbounded" type="xChange:addressType"
                name="address">
            </xs:element>
            <xs:element name="contactref" minOccurs="0" maxOccurs="unbounded"
                type="xChange:contactRefType" />
            <xs:element name="medical" type="xChange:medicalType"
                maxOccurs="1" minOccurs="0">
            </xs:element>
            <xs:element name="meta" type="xChange:metaType" maxOccurs="unbounded"
                minOccurs="0">
            </xs:element>
            <xs:element name="financial" type="xChange:financialType"
                maxOccurs="1" minOccurs="0">
            </xs:element>
        </xs:sequence>
        <xs:attribute name="lastname" type="xs:string" use="required"></xs:attribute>
        <xs:attribute name="middlename" type="xs:string" use="optional">
        </xs:attribute>
        <xs:attribute name="firstname" type="xs:string" use="optional">
        </xs:attribute>
        <xs:attribute name="birthdate" type="xs:date" use="optional"></xs:attribute>
        <xs:attribute name="salutation" type="xs:string" use="optional">
        </xs:attribute>
        <xs:attribute name="sex" type="xs:string" use="optional"></xs:attribute>
        <xs:attribute name="title" type="xs:string" use="optional"></xs:attribute>
        <xs:attribute use="required" name="type">
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:enumeration value="person"></xs:enumeration>
                    <xs:enumeration value="organization"></xs:enumeration>
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
        <xs:attribute name="shortname" type="xs:string" use="optional">
        </xs:attribute>
    </xs:complexType>
    <!--
        xs:complexType name="xChangeEpisode"> <xs:sequence> <xs:element
        minOccurs="0" ref="diagnosis"></xs:element> <xs:element minOccurs="0"
        ref="text"></xs:element> <xs:element name="insurance"
        type="insuranceType"></xs:element> </xs:sequence> <xs:attribute
        name="begin" type="xs:date"></xs:attribute> <xs:attribute
        use="required" name="id" type="xs:string"></xs:attribute>
        <xs:attribute name="active" type="xs:boolean"></xs:attribute>
        <xs:attribute name="title" type="xs:string"></xs:attribute>
        </xs:complexType
    -->
    <xs:complexType name="insuranceType">
        <xs:sequence>
            <xs:element name="contract" type="xChange:tariffType"
                maxOccurs="unbounded" minOccurs="1">
            </xs:element>
        </xs:sequence>
        <xs:attribute name="companyref" type="xs:IDREF"></xs:attribute>
        <xs:attribute name="reason">
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:enumeration value="disease"></xs:enumeration>
                    <xs:enumeration value="accident"></xs:enumeration>
                    <xs:enumeration value="maternity"></xs:enumeration>
                    <xs:enumeration value="prevention"></xs:enumeration>
                    <xs:enumeration value="birthdefect"></xs:enumeration>
                    <xs:enumeration value="other"></xs:enumeration>
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
        <xs:attribute name="publicDiagnosis" type="xs:string"></xs:attribute>
        <xs:attribute name="dateFrom" type="xs:date"></xs:attribute>
        <xs:attribute name="dateUntil" type="xs:string"></xs:attribute>
    </xs:complexType>
    <xs:complexType name="tariffType">
        <xs:attribute name="country">
            <xs:annotation>
                <xs:documentation>
                    ISO Countrycode for the country, that tariff
                    applies
                </xs:documentation>
            </xs:annotation>
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:minLength value="1"></xs:minLength>
                    <xs:maxLength value="3"></xs:maxLength>
                    <xs:whiteSpace value="collapse"></xs:whiteSpace>
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
        <xs:attribute name="name" type="xs:string"></xs:attribute>
        <xs:attribute name="caseID" type="xs:string"></xs:attribute>
    </xs:complexType>
    <xs:complexType name="medicalType">
        <xs:sequence>
            <xs:element name="episodes" type="xChange:episodeListType"
                maxOccurs="1" minOccurs="0" />
            <xs:element type="xChange:recordListType" name="records"
                maxOccurs="1" minOccurs="1" />
            <xs:element type="xChange:findingsListType" name="findings"
                maxOccurs="1" minOccurs="0" />
            <xs:element type="xChange:documentListType" name="documents"
                maxOccurs="1" minOccurs="0" />
            <xs:element type="xChange:medicationListType" name="medications"
                maxOccurs="1" minOccurs="0" />
            <xs:element type="xChange:riskListType" name="risks"
                maxOccurs="1" minOccurs="0" />
            <xs:element name="meta" type="xChange:metaType" maxOccurs="unbounded"
                minOccurs="0">
            </xs:element>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="riskType">
        <xs:annotation>
            <xs:documentation>
                A risk ist an allergy or a life style risk or a
                genetic
                risk
            </xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:element name="meta" type="xChange:metaType" maxOccurs="unbounded"
                minOccurs="0">
            </xs:element>
        </xs:sequence>
        <xs:attribute use="required" name="confirmedBy" type="xs:IDREF">
        </xs:attribute>
        <xs:attribute use="required" name="firstMentioned" type="xs:date">
        </xs:attribute>
        <xs:attribute use="required" name="substance" type="xs:string">
        </xs:attribute>
        <xs:attribute name="relevance" type="xs:string"></xs:attribute>
    </xs:complexType>
    <xs:complexType name="findingType">
        <xs:annotation>
            <xs:documentation>
                a finding. This might be a lab result or an ecg
                result
                or a microbiological finding.
            </xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:element name="xid" type="xChange:XIDType" maxOccurs="1"
                minOccurs="1">
                <xs:annotation>
                    <xs:documentation>
                        a unique identifier of the code system this item
                        comes from. In the most simple case this is a
                        xid of domain
                        www.xid.ch/labitems/
                        &lt;NameOfLab&gt; with the string that
                        identifies the item within this lab (e.g.
                        "Potassium") as
                        domain_id. Other EMR systems
                        might choose to use
                        www.xid.ch/labitems/LOINC as
                        the codebase and use the LOINC-Code of
                        the item
                        as domain_id.
                    </xs:documentation>
                </xs:annotation>
            </xs:element>
            <xs:element name="meta" type="xChange:metaType" maxOccurs="unbounded"
                minOccurs="0">
                <xs:annotation>
                    <xs:documentation>
                        any additional information the application might
                        want to give
                    </xs:documentation>
                </xs:annotation>
            </xs:element>
        </xs:sequence>
        <xs:attribute name="id" type="xs:ID">
            <xs:annotation>
                <xs:documentation>
                    a globally unique id to identify this findingType
                    unambiguously
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute use="required" name="name" type="xs:string">
            <xs:annotation>
                <xs:documentation>
                    a textual representation of the finding item (the
                    name of the finding, eg hemoglobine or ecg or x-ray
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="normRange" type="xs:string">
            <xs:annotation>
                <xs:documentation>
                    the norm range. shoud be adapted for sex and age
                    of
                    the current patient
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="type">
            <xs:annotation>
                <xs:documentation>
                    the type of results of this finding
                </xs:documentation>
            </xs:annotation>
            <xs:simpleType>
                <xs:restriction base="xs:NMTOKEN">
                    <xs:enumeration value="numeric"></xs:enumeration>
                    <xs:enumeration value="text"></xs:enumeration>
                    <xs:enumeration value="image"></xs:enumeration>
                    <xs:enumeration value="absolute"></xs:enumeration>
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
        <xs:attribute name="unit" type="xs:string">
            <xs:annotation>
                <xs:documentation>units if any</xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="group" type="xs:string">
            <xs:annotation>
                <xs:documentation>
                    a hint where this item should be shown in a result
                    sheet. e.g. Hematology or elektrolytes
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
    </xs:complexType>
    <xs:complexType name="contactRefType">
        <xs:annotation>
            <xs:documentation>
                A relation of a contact. Points to another contact
                inside the same file
            </xs:documentation>
        </xs:annotation>
        <xs:attribute use="required" name="refID" type="xs:IDREF">
            <xs:annotation>
                <xs:documentation>
                    ID of the contact in the contacts section inside
                    the
                    same file
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute use="required" name="description" type="xs:string">
            <xs:annotation>
                <xs:documentation>
                    a description of the relationship of the contact
                    to
                    this identity
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
    </xs:complexType>
    <xs:complexType name="medicationType">
        <xs:sequence>
            <xs:element name="xid" type="xChange:XIDType" maxOccurs="1"
                minOccurs="1">
            </xs:element>
            <xs:element name="meta" type="xChange:metaType" maxOccurs="unbounded"
                minOccurs="0">
            </xs:element>
        </xs:sequence>
        <xs:attribute use="required" name="product" type="xs:string">
        </xs:attribute>
        <xs:attribute use="optional" name="dosage" type="xs:string">
        </xs:attribute>
        <xs:attribute name="dosageUnit" type="xs:string"></xs:attribute>
        <xs:attribute name="frequency" type="xs:string"></xs:attribute>
        <xs:attribute use="optional" name="startDate" type="xs:date">
        </xs:attribute>
        <xs:attribute use="optional" name="stopDate" type="xs:date">
        </xs:attribute>
        <xs:attribute name="substance" type="xs:string"></xs:attribute>
        <xs:attribute name="remark" type="xs:string"></xs:attribute>
    </xs:complexType>
    <xs:complexType name="medicationListType">
        <xs:sequence>
            <xs:element maxOccurs="unbounded" type="xChange:medicationType"
                name="medication" />
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="recordListType">
        <xs:sequence>
            <xs:element name="record" type="xChange:recordType"
                maxOccurs="unbounded" minOccurs="1">
            </xs:element>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="documentListType">
        <xs:annotation>
            <xs:documentation>
                container around the documents section inside a
                medical
                element. contains all patient-related documents
            </xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:element name="document" type="xChange:documentType"
                maxOccurs="unbounded" minOccurs="1">
            </xs:element>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="documentType">
        <xs:annotation>
            <xs:documentation>
                a document of arbitrary type (can be image, text or
                other)
            </xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:element name="xid" type="xChange:XIDType" maxOccurs="1"
                minOccurs="1">
            </xs:element>
            <xs:element name="hint" type="xs:string" maxOccurs="1"
                minOccurs="1">
                <xs:annotation>
                    <xs:documentation>
                        a hint to display to the user if the application
                        can not render the document
                    </xs:documentation>
                </xs:annotation>
            </xs:element>
            <xs:element name="meta" type="xChange:metaType" maxOccurs="unbounded"
                minOccurs="0">
                <xs:annotation>
                    <xs:documentation>
                        any additional informations the application
                        might
                        want to include
                    </xs:documentation>
                </xs:annotation>
            </xs:element>
            <xs:element name="contents" type="xs:string" maxOccurs="1"
                minOccurs="0">
                <xs:annotation>
                    <xs:documentation>
                        if placement was inline: The base64 encoded
                        document. If placement was url: The URL.
                    </xs:documentation>
                </xs:annotation>
            </xs:element>
        </xs:sequence>
        <xs:attribute name="title" type="xs:string" use="required">
            <xs:annotation>
                <xs:documentation>
                    title of the document
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="origin" type="xs:IDREF" use="optional">
            <xs:annotation>
                <xs:documentation>
                    Reference to the xChangeContact where the document
                    originated
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="destination" type="xs:IDREF" use="optional">
            <xs:annotation>
                <xs:documentation>
                    Reference to tthe xChangeContact this document was
                    addressed originally
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="mimetype" type="xs:string" use="required">
            <xs:annotation>
                <xs:documentation>
                    Mimetype of the document
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="subject" type="xs:string" use="optional">
            <xs:annotation>
                <xs:documentation>
                    A short description of the subject of the document
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="placement" type="xChange:placementType"
            use="required">
            <xs:annotation>
                <xs:documentation>
                    Location of the document. Inline: base64 encoded
                    in the body of this element. infile: inside the
                    xChange-file. url: at  the given url
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="date" type="xs:date" use="required">
            <xs:annotation>
                <xs:documentation>
                    date this document was originally created
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="recordref" type="xs:IDREF" use="optional">
            <xs:annotation>
                <xs:documentation>
                    record this document belongs to (if any)
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
    </xs:complexType>
    <xs:simpleType name="placementType">
        <xs:restriction base="xs:string">
            <xs:enumeration value="inline"></xs:enumeration>
            <xs:enumeration value="infile"></xs:enumeration>
            <xs:enumeration value="url"></xs:enumeration>
        </xs:restriction>
    </xs:simpleType>
    <xs:complexType name="contactsListType">
        <xs:annotation>
            <xs:documentation>
                Container around the contacts section of the file
            </xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:element name="contact" type="xChange:xChangeContactType"
                maxOccurs="unbounded" minOccurs="1">
            </xs:element>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="episodeListType">
        <xs:annotation>
            <xs:documentation>
                container around the episodes section of the
                medical
                element. The episodes section contains all
                diagnoses/problems/episodes that are described in this
                medical
            </xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:element name="episode" type="xChange:episodeType"
                maxOccurs="unbounded" minOccurs="1">
            </xs:element>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="episodeType">
        <xs:annotation>
            <xs:documentation>
                An Episode, aka Problem. This is something that
                happened
                to the patient at a given moment - the beginDate and
                continues trough some amount of time, over one or more
                consultations
                or patient records and might eventually
                declared inactive at some
                moment - the endDate
            </xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:element name="diagnosis" type="xChange:diagnosisType">
                <xs:annotation>
                    <xs:documentation>
                        the diagnosis more formally declared as in
                        "name"
                        -> see descrption of diagnosisType
                    </xs:documentation>
                </xs:annotation>
            </xs:element>
            <xs:element name="insurance" type="xChange:insuranceType"
                maxOccurs="unbounded" minOccurs="0">
                <xs:annotation>
                    <xs:documentation>
                        The insurance that is in charge for this episode
                    </xs:documentation>
                </xs:annotation>
            </xs:element>
            <xs:element name="meta" type="xChange:metaType" maxOccurs="unbounded"
                minOccurs="0">
                <xs:annotation>
                    <xs:documentation>
                        any additional informations the application
                        might
                        to give
                    </xs:documentation>
                </xs:annotation>
            </xs:element>
        </xs:sequence>
        <xs:attribute use="required" name="id" type="xs:ID">
            <xs:annotation>
                <xs:documentation>
                    a globalliy unique identifier
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute use="required" name="name" type="xs:string">
            <xs:annotation>
                <xs:documentation>
                    A name this episode has for the physician. This
                    might (but does not need to) duplicate the
                    diagnosis-text. The name
                    might something like
                    "thorax pain" wihle the diagnose states
                    "gastroesophageal reflux".
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="beginDate" type="xs:date" use="optional">
            <xs:annotation>
                <xs:documentation>
                    The date this episode was constated first. (if
                    known).
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="endDate" type="xs:date" use="optional">
            <xs:annotation>
                <xs:documentation>
                    The date, this episode was declared inactive (if
                    ever)
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
    </xs:complexType>
    <xs:complexType name="diagnosisType">
        <xs:annotation>
            <xs:documentation>a systematic diagnosis</xs:documentation>
        </xs:annotation>
        <xs:attribute name="text" type="xs:string">
            <xs:annotation>
                <xs:documentation>
                    textual description of the diagnosis
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="codesystem" type="xs:string">
            <xs:annotation>
                <xs:documentation>
                    codesystem this diagnosis is taken from
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="code" type="xs:string">
            <xs:annotation>
                <xs:documentation>
                    cod einside the diagnosis system
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
    </xs:complexType>
    <xs:complexType name="recordType">
        <xs:sequence>
            <xs:element name="chunk" type="xChange:chunkType"></xs:element>
            <xs:element name="episode" type="xChange:episodeRefType"
                maxOccurs="unbounded" minOccurs="0">
            </xs:element>
            <xs:element name="meta" type="xChange:metaType" maxOccurs="unbounded"
                minOccurs="0">
            </xs:element>
        </xs:sequence>
        <xs:attribute use="required" name="id" type="xs:ID"></xs:attribute>
        <xs:attribute use="required" name="author" type="xs:string"></xs:attribute>
        <xs:attribute use="required" name="date" type="xs:date"></xs:attribute>
        <xs:attribute name="responsible" type="xs:IDREF"></xs:attribute>
    </xs:complexType>
    <xs:complexType name="riskListType">
        <xs:sequence>
            <xs:element name="risk" type="xChange:riskType" maxOccurs="unbounded"
                minOccurs="1">
            </xs:element>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="findingsListType">
        <xs:annotation>
            <xs:documentation>
                container around the findings-section of this
                medical
                element
            </xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:choice maxOccurs="unbounded" minOccurs="0">
                <xs:element name="finding" type="xChange:findingType"></xs:element>
                <xs:element name="result" type="xChange:resultType"></xs:element>
            </xs:choice>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="headerType">
        <xs:annotation>
            <xs:documentation>
                The header of every xChange document
            </xs:documentation>
        </xs:annotation>
        <xs:attribute name="protocolVersion" type="xs:string"
            use="required">
            <xs:annotation>
                <xs:documentation>
                    version of the xChange protocol that created this
                    document, given as maior.minor.rev
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="creatorName" type="xs:string" use="required">
            <xs:annotation>
                <xs:documentation>
                    Name of the software that created this document
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="creatorID" type="xs:string" use="required">
            <xs:annotation>
                <xs:documentation>
                    glibally unique id of the software that created
                    this
                    document
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="creatorVersion" type="xs:string" use="required">
            <xs:annotation>
                <xs:documentation>
                    Version of the software that created this document
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="language" type="xs:string" use="optional">
            <xs:annotation>
                <xs:documentation>
                    language this document is created in
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
    </xs:complexType>
    <xs:complexType name="episodeRefType">
        <xs:attribute name="ref" type="xs:IDREF"></xs:attribute>
    </xs:complexType>
    <xs:complexType name="metaType">
        <xs:annotation>
            <xs:documentation>
                This type is for application specific informations
                within one of the other elements. In most cases this
                infkrmations are
                only useful for other instances of the
                same application that created
                them. No application may
                relay on any meta information to be present.
                Meta
                informations may safely and silently be ignored by
                applications
                that don't recognize them.
            </xs:documentation>
        </xs:annotation>
        <xs:attribute name="name" type="xs:string">
            <xs:annotation>
                <xs:documentation>
                    name of the application specific information
                    element. It is recommended to prefix the name with
                    an application
                    name to make meta names unique.
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="value" type="xs:string">
            <xs:annotation>
                <xs:documentation>
                    value of the element. A Processor must not make
                    any
                    assumptions on the type of any meta tags even if it
                    regognizes
                    the name.
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
    </xs:complexType>
    <xs:complexType name="markupType">
        <xs:annotation>
            <xs:documentation>
                A markup inside the record text. A markup can be
                any  structural information inside the text (e.g. "Subj") or
                a  modification of the appearance of the text (e.g.
                "bold"). The pos-attribute tells the position inside orf
                the text where this  markup will appear. The length
                attribute tells the number of characters (inlcuding
                whitespace and linebreak) will be included by
                this  markup. The length can be omitted ot set to 0, then the
                markup is  solely a positional information or the text
                attibute put at the given  position.
            </xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:element name="meta" type="xChange:metaType" maxOccurs="unbounded"
                minOccurs="0">
                <xs:annotation>
                    <xs:documentation>
                        any additional data the application might want
                        to provide
                    </xs:documentation>
                </xs:annotation>
            </xs:element>
        </xs:sequence>
        <xs:attribute name="pos" type="xs:int" use="required">
            <xs:annotation>
                <xs:documentation>
                    position this markup begins
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="length" type="xs:int" use="optional">
            <xs:annotation>
                <xs:documentation>
                    length in characters this markup consumes
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="type" type="xs:string">
            <xs:annotation>
                <xs:documentation>type of the markup</xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="text" type="xs:string">
            <xs:annotation>
                <xs:documentation>
                    a text that should be inserted at position "pos"
                    before applying the markup
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="hint" type="xs:string">
            <xs:annotation>
                <xs:documentation>
                    a hint what to display for processors that cant't
                    interpret this markup
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
    </xs:complexType>
    <xs:complexType name="resultType">
        <xs:annotation>
            <xs:documentation>a medical result</xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:element name="meta" type="xChange:metaType" maxOccurs="unbounded"
                minOccurs="0">
            </xs:element>
            <xs:element name="textResult" type="xs:string" maxOccurs="1"
                minOccurs="0">
                <xs:annotation>
                    <xs:documentation>
                        if the result is a text or a value, it must be
                        given here. If the result is a document or
                        image, this can be
                        omitted or can contain a
                        textual explanation of the image.
                    </xs:documentation>
                </xs:annotation>
            </xs:element>
            <xs:element name="documentRef" type="xs:IDREF" maxOccurs="1"
                minOccurs="0">
                <xs:annotation>
                    <xs:documentation>
                        indicates that the result is in the
                        documents-section and might be a letter or an
                        image
                    </xs:documentation>
                </xs:annotation>
            </xs:element>
        </xs:sequence>
        <xs:attribute name="id" type="xs:ID" use="required">
            <xs:annotation>
                <xs:documentation>globally unique id</xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="findingRef" type="xs:IDREF" use="required">
            <xs:annotation>
                <xs:documentation>
                    findingType that describes this result
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="timestamp" type="xs:dateTime" use="required">
            <xs:annotation>
                <xs:documentation>
                    date and time this result was found
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="isNormal" type="xs:boolean" use="optional">
            <xs:annotation>
                <xs:documentation>
                    an optional shorthand indicator whether this
                    result
                    is normal or not.
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
    </xs:complexType>
    <xs:group name="ModelGroupDefinition">
        <xs:sequence></xs:sequence>
    </xs:group>
    <xs:complexType name="chunkType">
        <xs:annotation>
            <xs:documentation>
                A Chunk is a part of a record. It has an optional
                title, a text, an optional style information (display hint) and
                optional markups.
            </xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:element name="title" type="xs:string" maxOccurs="1"
                minOccurs="0">
            </xs:element>
            <xs:element name="text" type="xs:string" maxOccurs="1"
                minOccurs="1">
            </xs:element>
            <xs:element name="style" type="xChange:styleType"
                maxOccurs="1" minOccurs="0">
            </xs:element>
            <xs:element name="markup" type="xChange:markupType"
                maxOccurs="unbounded" minOccurs="0">
            </xs:element>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="styleType">
        <xs:sequence>
            <xs:element name="bounds" type="xChange:rectangleType"></xs:element>
        </xs:sequence>
        <xs:attribute name="opacity" type="xs:double"></xs:attribute>
        <xs:attribute name="background" type="xs:string"></xs:attribute>
    </xs:complexType>
    <xs:complexType name="rgbType">
        <xs:attribute name="red" type="xs:int"></xs:attribute>
        <xs:attribute name="green" type="xs:int"></xs:attribute>
        <xs:attribute name="blue" type="xs:int"></xs:attribute>
    </xs:complexType>
    <xs:complexType name="rectangleType">
        <xs:attribute name="x" type="xs:int"></xs:attribute>
        <xs:attribute name="y" type="xs:int"></xs:attribute>
        <xs:attribute name="w" type="xs:int"></xs:attribute>
        <xs:attribute name="h" type="xs:int"></xs:attribute>
        <xs:attribute name="unit" type="xs:string"></xs:attribute>
    </xs:complexType>
    <xs:complexType name="financialType">
        <xs:sequence>
            <xs:element name="servicesRendered" type="xChange:servicesRenderedType"
                maxOccurs="unbounded" minOccurs="0"></xs:element>
        </xs:sequence>
        <xs:attribute name="dateFrom" type="xs:date"></xs:attribute>
        <xs:attribute name="dateUntil" type="xs:date"></xs:attribute>
        <xs:attribute name="billedTotal" type="xs:float"></xs:attribute>
        <xs:attribute name="paidTotal" type="xs:float"></xs:attribute>
        <xs:attribute name="lostTotal" type="xs:float"></xs:attribute>
    </xs:complexType>
    <xs:complexType name="servicesType">
        <xs:sequence>
            <xs:element name="service" type="xChange:serviceType"
                maxOccurs="unbounded" minOccurs="1"></xs:element>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="servicesRenderedType">
        <xs:sequence>
            <xs:element name="service" type="xChange:serviceType"
                maxOccurs="unbounded" minOccurs="1"></xs:element>
        </xs:sequence>
        <xs:attribute name="provider" type="xs:IDREF"></xs:attribute>
        <xs:attribute name="receiver" type="xs:IDREF"></xs:attribute>
        <xs:attribute name="time" type="xs:dateTime"></xs:attribute>
        <xs:attribute name="encounter" type="xs:IDREF"></xs:attribute>
    </xs:complexType>
</xs:schema>

XID.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://informatics.sgam.ch/xChange"
    elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xChange="http://informatics.sgam.ch/xChange">
    <xs:complexType name="XIDType">
        <xs:sequence>
            <xs:element name="identity" maxOccurs="unbounded"
                minOccurs="1" type="xChange:identityType">
            </xs:element>
        </xs:sequence>
        <xs:attribute name="id" type="xs:ID"></xs:attribute>
    </xs:complexType>
    <xs:complexType name="identityType">
        <xs:annotation>
            <xs:documentation>
                an identity within a XID element
            </xs:documentation>
        </xs:annotation>
        <xs:attribute name="domain" type="xs:string">
            <xs:annotation>
                <xs:documentation>
                    domain this identity comes from. must be globally
                    unique
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="domainID" type="xs:string">
            <xs:annotation>
                <xs:documentation>
                    the ID of the denoted object within the given
                    domain. Should be unique within that domain.
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="quality">
            <xs:annotation>
                <xs:documentation>
                    The Quality od this identity. it can be a locally
                    (only in the given sofware) or a regionally (e.g. in
                    a country) or a
                    globally assigned and recognized
                    identification.
                </xs:documentation>
            </xs:annotation>
            <xs:simpleType>
                <xs:restriction base="xs:string">
                    <xs:enumeration value="local"></xs:enumeration>
                    <xs:enumeration value="regional"></xs:enumeration>
                    <xs:enumeration value="global"></xs:enumeration>
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
        <xs:attribute name="isGUID" type="xs:boolean">
            <xs:annotation>
                <xs:documentation>
                    true if this domainID is guaranteed to be
                    globally
                    unique (and not only within the domain).
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
        <xs:attribute name="date" type="xs:date"></xs:attribute>
        <xs:attribute name="usage" type="xs:int">
            <xs:annotation>
                <xs:documentation>Usage count of this identity. Will always be
                    increased by one if this identity was helpful for an identification
                    procecc.
                </xs:documentation>
            </xs:annotation>
        </xs:attribute>
    </xs:complexType>
</xs:schema>

service.xsd

<?xml version="1.0" encoding="UTF-8"?>
<schema targetNamespace="http://informatics.sgam.ch/xChange"
    elementFormDefault="qualified" xmlns="http://www.w3.org/2001/XMLSchema"
    xmlns:xChange="http://informatics.sgam.ch/xChange"
    xmlns:Q1="xChange">
    <include schemaLocation="xid.xsd"></include>
    <complexType name="serviceType">
        <annotation>
            <documentation>
                A Service is defined by a name, a service system that is
                applied by contract (but might also be a custom defines
                service), a price and a cost
            </documentation>
        </annotation>
        <sequence>
            <element name="xid" type="XIDType" maxOccurs="1"
                minOccurs="1">
            </element>
        </sequence>
        <attribute name="name" type="string" use="required">
            <annotation>
                <documentation>name of this service</documentation>
            </annotation>
        </attribute>
        <attribute name="contractName" type="string" use="required"
            default="custom">
            <annotation>
                <documentation>
                    The name of the contractual system this service
                    belongs to (e.g. Tarmed, OKP, Analysenliste) or
                    "custom" to declare a custom service
                </documentation>
            </annotation>
        </attribute>
        <attribute name="contractCode" type="string"></attribute>
        <attribute name="minutes" type="string" use="optional"></attribute>
        <attribute name="cost" type="string" use="optional"></attribute>
        <attribute name="price" type="string" use="optional">
            <annotation>
                <documentation>
                    the price of this service in units of the contryct
                    (e.g. Rp., TP, cents)
                </documentation>
            </annotation>
        </attribute>
    </complexType>
</schema>