/// <summary>parse message according to our HL7 XML handler, and dump the data found /// to props. /// </summary> /// <summary>returns true if we parsed ok, which means well-formed XML, and /// that's about it. We just barely check against HL7 structure, and ignore any /// elements / text that is unexpected (that is, impossible in any HL7 message: /// independant of any message / segment definitions). /// "message" should be an XML document with one top-level element -- that being /// the message. (<ACK> or whatever). We're only expecting one message to be in /// "message". /// props can be null if you don't want the data (we still parse). The message /// data found in message (that passes msgMask) will be added to props as key / /// value pairs with the key a toString() of the appropriate DatumPath for the /// location where the data is found (i.e. in the ZYX[a]-b[c]-d-e style), and /// the value the corresponding text. So, after calling parseMessage /// successfully, if you wanted to retrieve the message data from props you /// might call something like /// props.getProperty((new DatumPath()).add("MSH").add(1).toString()) /// and that would return a String with "|", probably. /// Note that this package facilitates the extraction of message data in a way /// independent of message version (i.e. components and whatever getting added): /// With a message of "<FOO><ZYX><ZYX.42>fieldy-field-field</ZYX.42></ZYX></FOO>", /// "ZYX[0]-1[0]-1-1" will be the key that ends up in props (see notes at /// DatumPath.toString()) /// So if you, coding for a future version of the FOO message but /// recieving old-version message data, tried /// props.getProperty((new DatumPath()).add("ZYX").add(0).add(42).add(0).add(1).toString()) /// with the message above (that is, trying to extract a repetition and /// component that aren't there), you would get "ZYX[0]-42[0]-1-1" mapping to /// "fieldy-field-field" in the resulting props. /// If the message was /// "<FOO><ZYX><ZYX.42><ARG.1>component data</ARG.1></ZYX.42></ZYX></FOO>" /// and you, coding for an old version of this FOO message but recieving /// new-version FOO message data, tried /// props.getProperty((new DatumPath()).add("ZYX").add(0).add(42).toString()) /// you would get "ZYX[0]-42[0]-1-1" mapping to "component data" in the resulting /// props. /// msgMask lets you specify which parts of the message you want dumped to props. /// Passing in null gets you everything. Otherwise, msgMask's elements should /// all be DatumPaths (! => ClassCastException), and a particular part of the /// message will be dumped to props only if it's location, as represented by a /// DatumPath, startsWith (as in DatumPath.startsWith()) at least one element of /// msgMask. So if one element of msgMask was a (new DatumPath()).add(new /// String("ZYX")), then everything in all ZYX segment would get dumped to props. /// A (new DatumPath()).add(new String("ZYX")).add(1) would get only the first /// repetitions of same (if there is one) dumped to props. etc. etc. Note that /// a DatumPath of size() == 0 in msgMask will get you everything, no matter what /// the other elements of msgMask are, because all DatumPaths startsWith the /// zero-length DatumPath. /// Segment group elements (eg. ADT_A01.PROCEDURE) are handled fine, but they /// aren't addressed in msgMask or in the output in props -- basically any /// element tags at the level immediately inside the message element, and having /// a name that starts with the message element name + '.', is ignored (meaning /// it's contents are dealt with the same as if the start and end tags' just /// wasn't there.) /// </summary> public static bool parseMessage(System.Collections.Specialized.NameValueCollection props, System.String message, System.Collections.ICollection msgMask) { bool ret = false; try { XmlSAXDocumentManager factory = XmlSAXDocumentManager.NewInstance(); XmlSAXDocumentManager parser = XmlSAXDocumentManager.CloneInstance(factory); XmlSourceSupport inSrc = new XmlSourceSupport(new System.IO.MemoryStream(new System.Text.ASCIIEncoding().GetBytes(message))); HL7MessageHandler handler = new HL7MessageHandler(); handler.m_props = (props != null?props:new System.Collections.Specialized.NameValueCollection()); // it's expecting a props. if (msgMask != null) { handler.m_msgMask = msgMask; } else { handler.m_msgMask = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10)); SupportClass.ICollectionSupport.Add(handler.m_msgMask, new NuGenDatumPath()); } parser.parse(inSrc, handler); ret = true; } catch (System.IO.IOException e) { throw new NuGenHL7Exception(e); } catch (StopParsingException e) { throw new NuGenHL7Exception(e); } catch (System.Xml.XmlException e) { throw new NuGenHL7Exception(e); } return(ret); }
/// <summary>parse message according to our HL7 XML handler, and dump the data found /// to props. /// </summary> /// <summary>returns true if we parsed ok, which means well-formed XML, and /// that's about it. We just barely check against HL7 structure, and ignore any /// elements / text that is unexpected (that is, impossible in any HL7 message: /// independant of any message / segment definitions). /// "message" should be an XML document with one top-level element -- that being /// the message. (<ACK> or whatever). We're only expecting one message to be in /// "message". /// props can be null if you don't want the data (we still parse). The message /// data found in message (that passes msgMask) will be added to props as key / /// value pairs with the key a toString() of the appropriate DatumPath for the /// location where the data is found (i.e. in the ZYX[a]-b[c]-d-e style), and /// the value the corresponding text. So, after calling parseMessage /// successfully, if you wanted to retrieve the message data from props you /// might call something like /// props.getProperty((new DatumPath()).add("MSH").add(1).toString()) /// and that would return a String with "|", probably. /// Note that this package facilitates the extraction of message data in a way /// independent of message version (i.e. components and whatever getting added): /// With a message of "<FOO><ZYX><ZYX.42>fieldy-field-field</ZYX.42></ZYX></FOO>", /// "ZYX[0]-1[0]-1-1" will be the key that ends up in props (see notes at /// DatumPath.toString()) /// So if you, coding for a future version of the FOO message but /// recieving old-version message data, tried /// props.getProperty((new DatumPath()).add("ZYX").add(0).add(42).add(0).add(1).toString()) /// with the message above (that is, trying to extract a repetition and /// component that aren't there), you would get "ZYX[0]-42[0]-1-1" mapping to /// "fieldy-field-field" in the resulting props. /// If the message was /// "<FOO><ZYX><ZYX.42><ARG.1>component data</ARG.1></ZYX.42></ZYX></FOO>" /// and you, coding for an old version of this FOO message but recieving /// new-version FOO message data, tried /// props.getProperty((new DatumPath()).add("ZYX").add(0).add(42).toString()) /// you would get "ZYX[0]-42[0]-1-1" mapping to "component data" in the resulting /// props. /// msgMask lets you specify which parts of the message you want dumped to props. /// Passing in null gets you everything. Otherwise, msgMask's elements should /// all be DatumPaths (! => ClassCastException), and a particular part of the /// message will be dumped to props only if it's location, as represented by a /// DatumPath, startsWith (as in DatumPath.startsWith()) at least one element of /// msgMask. So if one element of msgMask was a (new DatumPath()).add(new /// String("ZYX")), then everything in all ZYX segment would get dumped to props. /// A (new DatumPath()).add(new String("ZYX")).add(1) would get only the first /// repetitions of same (if there is one) dumped to props. etc. etc. Note that /// a DatumPath of size() == 0 in msgMask will get you everything, no matter what /// the other elements of msgMask are, because all DatumPaths startsWith the /// zero-length DatumPath. /// Segment group elements (eg. ADT_A01.PROCEDURE) are handled fine, but they /// aren't addressed in msgMask or in the output in props -- basically any /// element tags at the level immediately inside the message element, and having /// a name that starts with the message element name + '.', is ignored (meaning /// it's contents are dealt with the same as if the start and end tags' just /// wasn't there.) /// </summary> public static bool parseMessage(System.Collections.Specialized.NameValueCollection props, System.String message, System.Collections.ICollection msgMask) { bool ret = false; try { XmlSAXDocumentManager factory = XmlSAXDocumentManager.NewInstance(); XmlSAXDocumentManager parser = XmlSAXDocumentManager.CloneInstance(factory); XmlSourceSupport inSrc = new XmlSourceSupport(new System.IO.MemoryStream(new System.Text.ASCIIEncoding().GetBytes(message))); HL7MessageHandler handler = new HL7MessageHandler(); handler.m_props = (props != null?props:new System.Collections.Specialized.NameValueCollection()); // it's expecting a props. if (msgMask != null) handler.m_msgMask = msgMask; else { handler.m_msgMask = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10)); SupportClass.ICollectionSupport.Add(handler.m_msgMask, new NuGenDatumPath()); } parser.parse(inSrc, handler); ret = true; } catch (System.IO.IOException e) { throw new NuGenHL7Exception(e); } catch (StopParsingException e) { throw new NuGenHL7Exception(e); } catch (System.Xml.XmlException e) { throw new NuGenHL7Exception(e); } return ret; }