everest
everest copied to clipboard
Multiple Race Codes in CDA
I'm having a difficult time getting this to work. I've reviewed the following pages: https://everest.codeplex.com/discussions/653908 http://te.marc-hi.ca/forums/default.aspx?g=posts&t=58
In my source XML I have the following:
<raceCode code="2106-3" displayName="White" codeSystem="2.16.840.1.113883.6.238" codeSystemName="Race & Ethnicity - CDC"/>
<sdtc:raceCode code="2108-9" displayName="White European" codeSystem="2.16.840.1.113883.6.238" codeSystemName="Race & Ethnicity - CDC"/>
Which fails to parse with the this error: System.Xml.XmlException: Can't parse 'raceCode' in namespace 'urn:hl7-org:sdtc'. The data does not appear to be an HL7v3 instance
This is my test that is blowing up:
[TestMethod]
public void ParseCcd()
{
var formatter = new XmlIts1Formatter();
formatter.ValidateConformance = false;
formatter.GraphAides.Add(new ClinicalDocumentDatatypeFormatter());
formatter.RegisterXSITypeName("POCD_MT000040UV.Patient", typeof(MyPatientMultipleRaceCodes));
formatter.Settings |= SettingsType.SuppressNullEnforcement | SettingsType.AlwaysCheckForOverrides;
formatter.ValidateConformance = false;
ClinicalDocument cda;
using (var xr = new XmlStateReader(XmlReader.Create(@"C:\CDA_Tests\170.315_b1_toc_amb_ccd_r21_sample1_v8.xml")))
{
var result = formatter.Parse(xr, typeof(ClinicalDocument));
cda = result.Structure as ClinicalDocument;
}
}
When I am rendering XML I have a different problem in that only one of the race codes is being assigned to the sdtc schema:
<sdtc:raceCode code="2106-3" codeSystem="2.16.840.1.113883.6.238" displayName="White" />
<raceCode code="2106-3" codeSystem="2.16.840.1.113883.6.238" displayName="White" />
<raceCode code="2108-9" codeSystem="2.16.840.1.113883.6.238" displayName="White European" />
Generated from this method:
private MemoryStream RenderCda(ClinicalDocument cda)
{
XmlIts1Formatter fmtr = new XmlIts1Formatter();
fmtr.RegisterXSITypeName("POCD_MT000040UV.Patient", typeof(MyPatientMultipleRaceCodes));
fmtr.Settings |= SettingsType.SuppressNullEnforcement | SettingsType.AlwaysCheckForOverrides;
fmtr.GraphAides.Add(new DatatypeFormatter());
fmtr.ValidateConformance = false;
// Prepare the output
var stream = new MemoryStream();
XmlStateWriter xsw = new XmlStateWriter(XmlWriter.Create(stream, new XmlWriterSettings() { Indent = true }));
xsw.WriteStartElement("ClinicalDocument", "urn:hl7-org:v3");
xsw.WriteAttributeString("xmlns", "sdtc", null, "urn:hl7-org:sdtc");
fmtr.Graph(xsw, cda);
xsw.WriteEndElement();
xsw.Flush();
stream.Position = 0;
return stream;
}
I've been banging my head against this for quite awhile now. Any help would be welcomed.
I was able to get the parse to work with a custom build of Everest. I added the and clause on line 12 (code is from XmlIts1Formatter.cs):
public IFormatterParseResult Parse(XmlReader r, Type t)
{
if (!(r is XmlStateReader))
r = new XmlStateReader(r);
// Initial state
if (r.ReadState == ReadState.Initial)
while (r.NodeType != XmlNodeType.Element)
r.Read();
// Detect if we can parse this...
if (r.NamespaceURI != "urn:hl7-org:v3" && r.NamespaceURI != "urn:hl7-org:sdtc")
throw new XmlException(string.Format("Can't parse '{0}' in namespace '{1}'. The data does not appear to be an HL7v3 instance", r.LocalName, r.NamespaceURI), null);
var resultContext = new XmlIts1FormatterParseResult(ResultCode.Accepted, null);
resultContext.Structure = ParseObject(r, t, null, resultContext);
return resultContext;
}
I think the render issue is a bug where SET<T> only applies the NamespaceUri from the property attribute on the first item in the collection:
[Property(Name = "raceCode", PropertyType = PropertyAttribute.AttributeAttributeType.NonStructural, NamespaceUri = "urn:hl7-org:sdtc")]
public new SET<CE<string>> RaceCode { get; set; }
So, I was able to get this to work with a custom formatter:
public class DlEverestFormatter : XmlIts1Formatter
{
protected override void GraphObject(XmlWriter s, IGraphable o, Type useType, IGraphable context, XmlIts1FormatterGraphResult resultContext)
{
var writer = (XmlStateWriter)s;
if (writer.CurrentElement.Name == "raceCode" && useType.GetGenericTypeDefinition().FullName.Contains(".SET"))
{
var raceCodes = (SET<CE<string>>)o;
var raceCodeCount = 0;
foreach (var raceCode in raceCodes)
{
if (raceCodeCount > 0)
{
s.WriteStartElement("raceCode", "urn:hl7-org:sdtc");
}
s.WriteAttributeString("code", raceCode.Code);
s.WriteAttributeString("codeSystem", raceCode.CodeSystem);
s.WriteAttributeString("displayName", raceCode.DisplayName);
raceCodeCount = raceCodeCount + 1;
if (raceCodeCount < raceCodes.Count)
{
s.WriteEndElement();
}
}
return;
}
base.GraphObject(s, o, useType, context, resultContext);
}
}
I also removed the NamespaceUri from my Patient class override RaceCode property. The override GraphObject takes care of setting the correct namespace for any raceCode past the first one. I will be doing the same for ethnicity which also has multiple in MU2015.