CCDA – USCDI Data Elements – Sexual Orientation
One of the another important Data Point that is required by the Edge testing tool to validate a CCDA Documents under USCDI-V3 is the availability of Sexual Orientation value of the patient.
Sexual Orientation CCDA
Although from the outside the Sexual Orientation makes more sense to be available inside the Patient Demographics section. It is as a matter of fact, present inside the patient demographics screen in the UI on most of the EHR applications that I’ve seen Eg: In EPIC – It’s in the demographics tab on the patient chart, Similarly in Athena EHR – its inside the Gender Identity and Sexual Orientation.
But for the CCDA documentation, this data is available under Social History section for some reason – How is sexual orientation belonging to a social history section in a CCDA document?.
HL7 and ONC (Office of the National Coordinator for Health IT) treat sexual orientation and gender identity as part of the patient’s lived experience, similar to alcohol use, tobacco use, or occupation. These are not strictly demographic values but are fluid, personal, and can change over time. The Social History section in C-CDA is meant to capture non-medical but clinically relevant factors. Because of the sensitive nature of SOGI (Sexual orientation, Gender Identity) data, placing it in a non-demographic section like Social History allows for more controlled access, rather than embedding it in the core patient identity (which may be broadly shared).
Let’s look at the values that can appear on this section.
- Heterosexual – 20430005
- Female Homosexual – 89217008
- Male Homosexual – 76102007
- Bisexual – 42035005
- Sexually attracted to neither gender – 472985009
- Other – OTH
- Unknown – UNK
- Asked but no answer – ASKU
- Not Applicable – NA
The C-CDA would also expect the SNOMED CT Codes to come along with these values. But, unfortunately by the time of writing this blog I don’t find a way to get a proper online source to get these values.The above mentioned values are extracted from multiple certified EHR systems and consolidated here for your reference – so thank me later or feel free to buy me a coffee from this website here.
C-CDA <entry> section
<entry typeCode="DRIV"> <observation classCode="OBS" moodCode="EVN"> <!-- ** Sexual Orientation ** --> <templateId root="2.16.840.1.113883.10.20.22.4.38"/> <templateId root="2.16.840.1.113883.10.20.22.4.501" extension="2022-06-01"/> <id root="45efb604-7049-4a2e-ad33-d38557c7636c"/> <code code="76690-7" codeSystem="2.16.840.1.113883.6.1" codeSystemName="LOINC" displayName="Sexual Orientation"/> <statusCode code="completed"/> <effectiveTime nullFlavor="NI"> </effectiveTime> <value xsi:type="CD" nullFlavor="UNK"/> </observation> </entry>
Develop the code in Mirth
Function to create sexualOrientation XML
function sexualOrientationXmlStructure(sexual_orientation) {
var val;
switch (sexual_orientation) {
case "Heterosexual":
//This term can also be mapped to "Heterosexual or Straight"
val = new XML('<value type="CD" code="20430005" codeSystem="2.16.840.1.113883.6.96" codeSystemName="SNOMED CT" displayName="Heterosexual"/>');
break;
case "Female Homosexual":
//This can also be mapped to "Gay or Lesbian"
val = new XML('<value type="CD" code="89217008" codeSystem="2.16.840.1.113883.6.96" codeSystemName="SNOMED CT" displayName="Female Homosexual"/>');
break;
case "Male Homosexual":
//This can also be mapped to "Gay or Lesbian"
val = new XML('<value type="CD" code="76102007" codeSystem="2.16.840.1.113883.6.96" codeSystemName="SNOMED CT" displayName="Male Homosexual"/>');
break;
case "Bisexual":
val = new XML('<value type="CD" code="42035005" codeSystem="2.16.840.1.113883.6.96" codeSystemName="SNOMED CT" displayName="Bisexual"/>');
break;
case "Sexually attracted to neither gender":
//This can be mapped to "Other sexual orientation not listed"
val = new XML('<value type="CD" code="472985009" codeSystem="2.16.840.1.113883.6.96" codeSystemName="SNOMED CT" displayName="Sexually attracted to neither gender"/>');
break;
case "Other":
val = new XML('<value type="CD" nullFlavor="OTH"/>');
break;
case "Unknown":
val = new XML('<value type="CD" nullFlavor="UNK"/>');
break;
case "Asked but no answer":
val = new XML('<value type="CD" nullFlavor="ASKU"/>');
break;
case "Not Applicable":
val = new XML('<value type="CD" nullFlavor="NA"/>');
break;
default:
val = new XML('<value type="CD" nullFlavor="UNK"/>');
}
return val;
}
Generating XML of the C-CDA
Below is the code for creating the <entry> section with in the social History Component section of a CCDA.
var entry = new XML('<entry typeCode="DRIV"></entry>');
var obs = new XML('<observation classCode="OBS" moodCode="EVN"></observation>');
obs.appendChild(new XML('<templateId root="2.16.840.1.113883.10.20.22.4.38"/>'));
obs.appendChild(new XML('<templateId root="2.16.840.1.113883.10.20.34.3.45" extension="2022-06-01" />'));
obs.appendChild(new XML('<id root="' + UUIDGenerator.getUUID() + '"/>'));
obs.appendChild(new XML('<code code="76691-5" codeSystem="2.16.840.1.113883.6.1" codeSystemName="LOINC" displayName="Gender Identity"/>'));
obs.appendChild(new XML('<statusCode code="completed"/>'));
obs.appendChild(new XML('<effectiveTime nullFlavor="NI"></effectiveTime>'));
var val = genderIdentityXmlStructure(gender_identity);
obs.appendChild(val);
entry.appendChild(obs);
Social History Section with Sexual Orientation
Imagine your building Social History CCDA section from scratch in Mirth then you need to use the code like below.
Parameters for function
Assuming there is a JSON data that comes to you from your EHR application as “msg” parameter. This msg parameter can have multiple values that corresponds to social history not just gender_identity.
But, generally gender_identity, sexual_orientation parameters are the stand-alone parameter covered in the demographics of a patient.
You can use these parameters as separate value in a function. Here is how I would generate a Social History Section in CCDA using Mirth’s E4XJS
function createSocialHistorySectionCCDA(msg,gender_identity,sexual_orientation,gender) {
var parsed = JSON.parse(msg);
var newSocialHistoryData = new XML("<component></component>");
var sectionData = new XML("<section></section>");
// Template ID for Social History Section
sectionData.appendChild(new XML("<templateId root='2.16.840.1.113883.10.20.22.2.17'/>"));
sectionData.appendChild(new XML("<templateId root='2.16.840.1.113883.10.20.22.2.17' extension='2015-08-01'/>"));
// Section code
sectionData.appendChild(new XML("<code code='29762-2' codeSystem='2.16.840.1.113883.6.1' displayName='Social History'/>"));
sectionData.appendChild(new XML("<title>Social History</title>"));
// Create <text> and <table>
var text = new XML("<text></text>");
var table = new XML("<table border='1' width='100%'><thead><tr><th>Aspect</th><th>Value</th></tr></thead><tbody></tbody></table>");
var tbody = table.elements("tbody")[0];
if (sexual_orientation) {
tbody.appendChild(new XML("<tr><td>Sexual Orientation</td><td>"+sexual_orientation+"</td></tr>"));
var entry = new XML('<entry typeCode="DRIV"></entry>');
var obs = new XML('<observation classCode="OBS" moodCode="EVN"></observation>');
obs.appendChild(new XML('<templateId root="2.16.840.1.113883.10.20.22.4.38"/>'));
obs.appendChild(new XML('<templateId root="2.16.840.1.113883.10.20.22.4.501" extension="2022-06-01" />'));
obs.appendChild(new XML('<id root="' + UUIDGenerator.getUUID() + '"/>'));
obs.appendChild(new XML('<code code="76690-7" codeSystem="2.16.840.1.113883.6.1" codeSystemName="LOINC" displayName="Sexual Orientation"/>'));
obs.appendChild(new XML('<statusCode code="completed"/>'));
obs.appendChild(new XML('<effectiveTime nullFlavor="NI"></effectiveTime>'));
var val = sexualOrientationXmlStructure(sexual_orientation);
obs.appendChild(val);
entry.appendChild(obs);
sectionData.appendChild(entry);
}
// Append table into <text>, and <text> before <entry>s
text.appendChild(table);
sectionData.insertChildBefore(sectionData.children()[4], text); // ⬅ insert <text> as first child
newSocialHistoryData.appendChild(sectionData);
return newSocialHistoryData;
}