pulling certain section of xml

Homepage Clovertech Forums Read Only Archives Cloverleaf Tcl Library pulling certain section of xml

  • Creator
  • #55633
    Kevin Crist

    need help with the following. i need search through a ccd document and if there is follow up info i then need to email the whole patient discharge instructions section to provider office. How can I pull off just the Patient Discharge section and not the rest of the ccd info? below is an example section of what it looks like but has other info before and after this section that is not wanted.

    This is just a straight raw route so i’m just using tcl.

    Patient Discharge Instructions    

    ===Follow-Up Appointment====


    Thanks for any insight.

Viewing 5 reply threads
  • Author
    • #85974
      Rob Lindsey

      Oh the XML woes.

      I fight with this type of stuff on and off.

      There are a number of different ways to do this and none are really great.  You can use  regexp to pull information.  Depending on how big the CCD is, that may not be what you want.  You could write a program to split up the Tagname and put them into a keyed list and then pull out the information from there.  You could write a loop to find the beginning and ending of but this would fail if your data has more than one section of .

      Dealers choice.


    • #85975
      Peter Heggie

      Same here. I use simple, crude text parsing to pick my way through the Discharge Instructions. I’l bet each EMR formats them differently.


      # get Discharge Instructions text from CCDA
                 set textDI [parseString “2.16.840.1.113883.” “” “” 1 “$xml”]
                 # get first followup to start the loop
                 set start 0
                 set followup [get_next_follow_up_visit $debug “$textDI” $start]
                 lassign [split “$followup” “|”] code provider address msi start
                 if {$code > 4} {set dispList [return_error $debug $module $mh “$provider”] ; return $dispList}

                 # looping through referrals – if and while there are more referrals, process each one
                 while {$code 4} {set dispList [return_error $debug $module $mh “$provider”] ; return $dispList}

      Where the –

      – textDI is a code used to indicate the Discharge Instructions

      – provider is the doctor name that will be used to do a table lookup to get the Direct email address

      – address is a physical address, just to provide a second data element to use in the provider lookup, to make sure we have a unique doctor

      – msi is our internal doctor ID number – eventually all referrals to ‘known’ doctors will also include this unique doctor number so the lookup will be easier

      – start is the starting position in the text block to start searching from, which is incremented with each loop, to march through the text block

      Obviously I’m doing other things, like using the called routine ‘parseString’, which just searches a large block of text (last parameter – the entire CCDA xml) for the first occurrence of a string (first parameter), and then use the next two parameters as start and end identifiers of strings, and then return everything between those start and end blocks. That is something I wrote because I used that logic so often.

      And proc ‘CCDA_gen_msg’ which will will use msgcopy to generate a new message and return that $mh. The new message is empty, but I put several data elements in the msgmetadata USERDATA, like the provider name, msi number, etc., and then send the message downstream for further processing. If I tried to do it all in one big TCL proc I’d go crazy.

      I can also post the code for get_next_followup_visit, but I know this is based on our own EMR’s DI formatting and layout. Unless you have Cerner Soarian, you will have to make up your own parsing routine.

      Here is a sample section of Discharge Instructions:


      Hospital Discharge Instructions

      Detailed Instructions from 2/27/2018 10:26 AM:

      Follow-Up Appointments

      Follow-Up With : Marshall, Cindy NP (844530) – NP Family Medicine

      Follow Up Address Telephone 1 : 164 BROAD ST, HAMILTON 13346 (315)8244600

      This is probably the worst example of XML I’ve seen. Not very hierarchical or intuitive. I have to ‘find my way’ to this section, then find ‘Follow-Up With’, then find the next text string having six numbers within parenthesis (in the example it is 844530), which is the MSI number, and then pick the provider name from that (Marshall, Cindy) and return the name, address and msi number (and the current position within the text, so the main loop can continue looking forward from the new current position).

      Its daunting!

      Peter Heggie

    • #85976
      Jim Kosloskey

      If I were faced with doing XML work via Tcl think I would approach it this way:

      1. Make sure I have a valid schema for the input and the output.

      2. Use the GRM functions to navigate, etc.

      I think I recall even seeing a recommendation in the Cloverleaf docs to use the GRM functions when dealing with XML.

      Unfortunately I do not have any experiences to share vis-a-vis XML, GRM, Tcl as I would not use Tcl inside Cloverleaf to transform XML.

      email: jim.kosloskey@jim-kosloskey.com

    • #85977

      Take a look at the tcl tdom package and xpath searching. It’s very helpful for searching XML including CCD/A’s.


      # https://wiki.tcl-lang.org/1948

      package require tdom
      set fh [open test.ccd r]; fconfigure $fh -translation binary; set xml [read $fh]; close $fh
      set doc [dom parse -simple -keepEmpties -baseurl urn:hl7-org:v3 $xml]
      set root [$doc documentElement]
      set ns {ns urn:hl7-org:v3}
      $doc selectNodesNamespaces $ns

      set node [$root selectNodes {ns:id}]
      if {$node eq “”} {echo node is empty; return 0}
      set id_root [$node getAttribute root]
      set id_extension [$node getAttribute extension]
      echo id_root: $id_root
      echo id_extension: $id_extension

      set node [$root selectNodes {ns:code[1]}]
      if {$node eq ""} {echo node is empty; return 0}
      set code_codeSystem [$node getAttribute codeSystem]
      set code_displayName [$node getAttribute displayName]
      echo code_codeSystem: $code_codeSystem
      echo code_displayName: $code_displayName

      # 17 Daws Rd.
      set node [$root selectNodes {/ns:ClinicalDocument/ns:recordTarget/ns:patientRole/ns:addr[1]/ns:streetAddressLine/text()}]
      if {$node eq ""} {echo node is empty; return 0}
      #puts [$node data]
      puts [$node nodeValue]

      # data
      # For a processing instruction node the data part is returned. For a text node, comment node or cdata section node the value is returned. Otherwise an error is generated.

      # nodeValue ?newValue?
      # Returns the value of that node object. This is the the text or the data for element nodes of type
      # If the node is a TEXT_NODE, COMMENT_NODE or PROCESSING_INSTRUCTION_NODE and the optional argument newValue is given, the node is set to that value.

      #regsub -all {/} $xpath {/ns:} newxpath
      #string map {/ /ns:} newxpath

      -- Max Drown (Infor)

    • #85978
      Charlie Bursell

      I have not used it in a long time so it may have changed but in the past I have found the Tcl DOM package to very slow plus you must supply a schema.

      I have always had good luck using regular expressions to parse XML messages as long as I have a priory information about the layout.  Even large files can be parsed quickly.  Sometimes, if looking for a loop within a loop you may have to grab the main look and then parse it.

      As an example here is a Tcl proc I used to provide with level 3 classes

    • #85979

      The latest version of tdom is fast.

      -- Max Drown (Infor)

Viewing 5 reply threads
  • The forum ‘Tcl Library’ is closed to new topics and replies.

Forum Statistics

Registered Users
Topic Tags