Thursday 26 June 2008

c# with XmlDocument and xpaths

Im almost embarrassed to admit it but I have spend almost a day playing around with the XmlDocument .NET class and xpaths. My problem was that I have the XML shown below(only a snipped of it is pasted below)

And wanted to get hold of the "id" tag inside patient. To do this I found that the fast way was to use the method SelectSingleNode to and a xpath expression like the following:

"/ClinicalDocument/recordTarget/patientRole/id".

In the following way:

XmlDocument xml = new XmlDocument();
xml.LoadXml(cda.Xmlcda);
XmlNode node = xml.SelectSingleNode("/ClinicalDocument/recordTarget/patientRole/id");

But no element was found. I tried quite a lot of different stuff. But nothing worked.

Until finally I found this article: (link) (which I only skimmed(to be completely honest))which described the funny thing that even if the elements is not prefixed in the XML the base namespace is used anyway. So to enable me to Xpath my way to the patient Id tag I needed a XmlNameSpaceManager to handle the namespaces.


The working code looks like this:
XmlDocument xml = new XmlDocument();
xml.LoadXml(cda.Xmlcda);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable);
nsmgr.AddNamespace("cda", "urn:hl7-org:v3");
XmlNode node = xml.SelectSingleNode("/ClinicalDocument/recordTarget/patientRole/id", nsmgr);



The XML:

<!-- ?xml-stylesheet type="text/xsl" href="CDA.xsl"? -->
<!-- Readers should be aware of the evolving "Using SNOMED CT in HL7 Version 3" implementation guide, currently in a draft state. The guide, co-developed by HL7 and the College of American Pathologists, will be balloted by HL7 as an Informative Document. Recommendations in the final published guide should usurp patterns of SNOMED CT usage found in this sample instance. -->
<clinicaldocument xmlns="urn:hl7-org:v3" voc="urn:hl7-org:v3/voc"
xsi="http://www.w3.org/2001/XMLSchema-instance"
schemalocation="urn:hl7-org:v3 CDA.xsd">
<!-- ******************************************************** CDA Header ******************************************************** -->
<typeid root="2.16.840.1.113883.1.3" extension="POCD_HD000040">
<templateid root="2.16.840.1.113883.3.27.1776">
<id extension="c266" root="2.16.840.1.113883.19.4">
<code code="11488-4" codesystem="2.16.840.1.113883.6.1" codesystemname="LOINC" displayname="Consultation note">
<title>Good Health Clinic Consultation Note</title>
<effectivetime value="20000407">
<confidentialitycode code="N" codesystem="2.16.840.1.113883.5.25">
<languagecode code="en-US">
<setid extension="BB35" root="2.16.840.1.113883.19.7">
<versionnumber value="2">
<recordtarget>
<patientrole>
<id extension="12345" root="2.16.840.1.113883.19.5">
<patient>
<name>
</name></patient></id></patientrole></recordtarget></versionnumber></setid></languagecode></confidentialitycode></effectivetime></code>

Tuesday 10 June 2008

"?" - Question mark in c# code (Nullable value types)

In a piece of auto generated code, I found the following property


public DateTime? EffettiveTime
{
get { return m_effettiveTime; }
set { this.m_effettiveTime = value; }
}


This was the first time I seen the question mark in the c# code (at least in this context) The problem arose when I wanted to do the following:


someInstance.date = EffettiveTime.ToString("yyyy-mm-dd");


It returned an error saying that the ToString method does not have any overload methods, which takes a string. I looked up DateTime and found the overloaded method, so why couldn't I use it.

After some googling I found the wikipedia site for c-sharp (link) where I found the following:


Nullable value types (denoted by a question mark, e.g. int? i = null;) which add null to the set of allowed values for any value type. This provides improved interaction with SQL databases, which can have nullable columns of types corresponding to C# primitive types: an SQL INTEGER NULL column type directly translates to the C# int?.


But then there is just the problem that this new type (DateTime?) did not implement the method that I needed, so I had to cast it to DateTime before continuing, on. This seemed to work:

DateTime eTime = (DateTime) EffettiveTime;
someInstance.date = eTime.ToString("yyyy-mm-dd");





The "?" question mark is also used for short if statements. The following can be written much shorter:


SomeClasse someInstance = null;
if(<someBoolean>)
{
someInstance= <doSomething>;
}
else
{
someInstance = <doSomethingElse>;
}



This could be written like this instead

SomeClasse someInstance = <someBoolean> ? <doSomething> : <doSomethingElse>;