
Wenn Sie eine Anwendung erstellen, die aktiv mit Diensten und Systemen von Drittanbietern interagiert, ist es häufig erforderlich, einen Informationsaustausch mit ihnen in eine Richtung oder in beide Richtungen bereitzustellen
Häufig bietet ein Drittanbieter-Service jedoch ein einziges Format und eine einzige Datenstruktur für eine solche Interaktion.
Eines dieser Formate der elektronischen Dokumentenverwaltung ist
EDI ANSI ASC X12 , dessen Beschreibung hier ziemlich detailliert ist.
KDPV wurde von
dieser Seite genommenUnter der Katze befindet sich ein einfacher X12-Parser-Algorithmus und Clojure-Code, der den Parser implementiert, sowie ein Beispiel für die Verarbeitung analysierter Daten.
Ein bisschen über das Format
Zitieren des obigen Links:
Der Standard für den elektronischen Dokumentenaustausch ANSI ASC X12 (Akkreditiertes Standardkomitee X12 des American National Standards Institute) wurde in den 70er Jahren entwickelt, als die geringe Größe des elektronischen Dokuments wichtig war (für Modems mit einer Geschwindigkeit von 300 bis 1200 Bit pro Sekunde) und jedes Byte übertragen werden musste maximale Information. Damit wurde die „Lesbarkeit“ des elektronischen Dokuments zugunsten der „Informationsdichte“ aufgegeben.
Daher werden darin keine für Menschen lesbaren Schönheiten wie in XML angezeigt. Und obwohl der Standard es Ihnen ermöglicht, Dokumente mit einer ziemlich komplexen hierarchischen Struktur zu erstellen, wobei Blöcke und sogenannte Schleifen vorhanden sind, werden nicht einmal schließende Tags für alle Blöcke (außer ISA / GS / ST) bereitgestellt. Durch den Link zu Kata können sich diejenigen, die dies wünschen, detailliert mit der Struktur und Beschreibung des Formats vertraut machen, dann werden wir nur die notwendigen Dinge ansprechen.
Jeder Dokumenttyp verfügt über eine eigene Vorlagenstruktur, die die Bedeutung und den Zweck einzelner Felder und Segmente, ihre Typen und möglichen Werte sowie eine Liste der erforderlichen und optionalen Segmente und Blöcke angibt. Die Versionierung von Vorlagen wird unterstützt, Informationen zu Typ und Versionsnummer werden in den entsprechenden Feldern des Dokuments übertragen. Es wird davon ausgegangen, dass es unter Verwendung einer Vorlage eines bestimmten Dokumenttyps analysiert und validiert werden sollte.
Unten finden Sie ein Beispiel für ein Dokument, das mehrere Transaktionen vom Typ 835 enthält (ein Dokument vom Typ Claim Response), das das Parsen und die anschließende Datenverarbeitung demonstriert.
Beispiel X12ISA*00* *00* *ZZ*EMEDNYBAT *ZZ*ETIN *140305*0929*^*00501*111111123*0*P*:~ GS*HP*EMED*ETIN*20140301*09304100*111111123*X*005010X221A1~ ST*835*35681~ BPR*I*810.8*C*CHK************20140331~ TRN*1*12345*1512345678~ REF*EV*XYZ CLEARINGHOUSE~ N1*PR*DENTAL OF ABC~ N3*225 MAIN STREET~ N4*CENTERVILLE*PA*17111~ PER*BL*JANE DOE*TE*9005555555~ N1*PE*BAN DDS LLC*FI*999994703~ LX*1~ CLP*7722337*1*226*132**12*119932404007801~ NM1*QC*1*DOE*SANDY****MI*SJD11112~ NM1*82*1*BAN*ERIN****XX*1811901945~ AMT*AU*132~ SVC*AD:D0120*46*25~ DTM*472*20140324~ CAS*CO*131*21~ AMT*B6*25~ SVC*AD:D0220*25*14~ DTM*472*20140324~ CAS*CO*131*11~ AMT*B6*14~ SVC*AD:D0230*22*10~ DTM*472*20140324~ CAS*CO*131*12~ AMT*B6*10~ SVC*AD:D0274*60*34~ DTM*472*20140324~ CAS*CO*131*26~ AMT*B6*34~ SVC*AD:D1110*73*49~ DTM*472*20140324~ CAS*CO*131*24~ AMT*B6*49~ LX*2~ CLP*7722337*1*119*74**12*119932404007801~ NM1*QC*1*DOE*SALLY****MI*SJD11111~ NM1*IL*1*DOE*JOHN****MI*123456~ NM1*82*1*BAN*ERIN****XX*1811901945~ AMT*AU*74~ SVC*AD:D0120*46*25~ DTM*472*20140324~ CAS*CO*131*21~ AMT*B6*25~ SVC*AD:D1110*73*49~ DTM*472*20140324~ CAS*CO*131*24~ AMT*B6*49~ LX*3~ CLP*7722337*1*226*108*24*12*119932404007801~ NM1*QC*1*SMITH*SALLY****MI*SJD11113~ NM1*82*1*BAN*ERIN****XX*1811901945~ AMT*AU*132~ SVC*AD:D0120*46*25~ DTM*472*20140324~ CAS*CO*131*21~ AMT*B6*25~ SVC*AD:D0220*25*0~ DTM*472*20140324~ CAS*PR*3*14~ CAS*CO*131*11~ AMT*B6*14~ SVC*AD:D0230*22*0~ DTM*472*20140324~ CAS*PR*3*10~ CAS*CO*131*12~ AMT*B6*10~ SVC*AD:D0274*60*34~ DTM*472*20140324~ CAS*CO*131*26~ AMT*B6*34~ SVC*AD:D1110*73*49~ DTM*472*20140324~ CAS*CO*131*24~ AMT*B6*49~ LX*4~ CLP*7722337*1*1145*14*902*12*119932404007801~ NM1*QC*1*SMITH*SAM****MI*SJD11116~ NM1*82*1*BAN*ERIN****XX*1811901945~ AMT*AU*14~ SVC*AD:D0220*25*14~ DTM*472*20140324~ CAS*CO*131*11~ AMT*B6*14~ SVC*AD:D2790*940*0~ DTM*472*20140324~ CAS*PR*3*756~ CAS*CO*131*184~ SVC*AD:D2950*180*0~ DTM*472*20140324~ CAS*PR*3*146~ CAS*CO*131*34~ LX*5~ CLP*7722337*1*348*16.8*44.2*12*119932404007801~ NM1*QC*1*JONES*SAM****MI*SJD11122~ NM1*82*1*BAN*ERIN****XX*1811901945~ AMT*AU*28~ SVC*AD:D4342*125*0~ DTM*472*20140313~ CAS*CO*131*125~ SVC*AD:D4381*43*0~ DTM*472*20140313~ CAS*PR*3*33~ CAS*CO*131*10~ SVC*AD:D2950*180*16.8~ DTM*472*20140313~ CAS*PR*3*11.2~ CAS*CO*131*152~ AMT*B6*28~ LX*6~ CLP*7722337*1*226*132**12*119932404007801~ NM1*QC*1*JONES*SALLY****MI*SJD11133~ NM1*82*1*BAN*ERIN****XX*1811901945~ AMT*AU*132~ SVC*AD:D0120*46*25~ DTM*472*20140321~ CAS*CO*131*21~ AMT*B6*25~ SVC*AD:D0220*25*14~ DTM*472*20140321~ CAS*CO*131*11~ AMT*B6*14~ SVC*AD:D0230*22*10~ DTM*472*20140321~ CAS*CO*131*12~ AMT*B6*10~ SVC*AD:D0274*60*34~ DTM*472*20140321~ CAS*CO*131*26~ AMT*B6*34~ SVC*AD:D1110*73*49~ DTM*472*20140321~ CAS*CO*131*24~ AMT*B6*49~ LX*7~ CLP*7722337*1*179*108**12*119932404007801~ NM1*QC*1*DOE*SAM****MI*SJD99999~ NM1*82*1*BAN*ERIN****XX*1811901945~ AMT*AU*108~ SVC*AD:D0120*46*25~ DTM*472*20140324~ CAS*CO*131*21~ AMT*B6*25~ SVC*AD:D0274*60*34~ DTM*472*20140324~ CAS*CO*131*26~ AMT*B6*34~ SVC*AD:D1110*73*49~ DTM*472*20140324~ CAS*CO*131*24~ AMT*B6*49~ LX*8~ CLP*7722337*1*129*82**12*119932404007801~ NM1*QC*1*DOE*SUE****MI*SJD88888~ NM1*82*1*BAN*ERIN****XX*1811901945~ AMT*AU*82~ SVC*AD:D0120*46*25~ DTM*472*20140324~ CAS*CO*131*21~ AMT*B6*25~ SVC*AD:D1120*54*37~ DTM*472*20140324~ CAS*CO*131*17~ AMT*B6*37~ SVC*AD:D1208*29*20~ DTM*472*20140324~ CAS*CO*131*9~ AMT*B6*20~ LX*9~ CLP*7722337*1*221*144**12*119932404007801~ NM1*QC*1*DOE*DONNA****MI*SJD77777~ NM1*82*1*BAN*ERIN****XX*1811901945~ AMT*AU*144~ SVC*AD:D0120*46*25~ DTM*472*20140324~ CAS*CO*131*21~ AMT*B6*25~ SVC*AD:D0330*92*62~ DTM*472*20140324~ CAS*CO*131*30~ AMT*B6*62~ SVC*AD:D1120*54*37~ DTM*472*20140324~ CAS*CO*131*17~ AMT*B6*37~ SVC*AD:D1208*29*20~ DTM*472*20140324~ CAS*CO*131*9~ AMT*B6*20~ SE*190*35681~ GE*1*111111123~ IEA*1*111111123~
Eine detaillierte Beschreibung des Zwecks jedes Blocks und Segments findet sich in der Analyse der allgemeinen Struktur 12 und der Struktur der Vorlage für diesen Dokumenttyp. Das Grundkonzept ist jedoch allen Typen gemeinsam - der Inhalt des Pakets besteht aus Segmenten, die durch das Symbol
~ getrennt sind (im Beispieltext wird jedes Segment zur besseren Lesbarkeit in einer neuen Zeile angezeigt). Jedes Segment kann wiederum eine beliebige Anzahl von Feldern enthalten, die durch
* getrennt sind.
Solche Vereinbarungen ermöglichen es uns, leicht eine lineare Struktur des Dokuments als Liste von Segmenten mit einer Liste ihrer Felder zu erhalten. Dies reicht jedoch nicht aus, um die hierarchische Struktur von Dokumentblöcken wiederherzustellen. Wie bereits erwähnt, soll hierfür ein Schema verwendet werden, das für die meisten Dokumenttypen eine ziemlich große Datei ist. Da wir uns jedoch nicht mit der Aufgabe der Dokumentvalidierung befassen, sondern uns nur auf das Parsen beschränken, ist der folgende Algorithmus für unsere Zwecke durchaus geeignet: Für jedes Segment, das bei der sequentiellen Analyse der linearen Liste von Dokumentsegmenten auftritt, müssen wir eine Antwort auf die einzige Frage erhalten: Formt sich dieses Segment? Ein neuer verschachtelter Block, unabhängig davon, ob es sich um das Ende des aktuellen Blocks (und gleichzeitig um den Beginn des nächsten) oder (in anderen Fällen) um das innere Segment des aktuellen Blocks handelt.
Parser
Unten sehen Sie den Clojure-Code, der eine lineare Segmentstruktur in eine hierarchische Blockstruktur analysiert. Um die Hierarchiestruktur zu definieren, wird ein deklarativer Ansatz verwendet - die einfachste Schleifen-Datenstruktur, in der Listen von Segmenten, die verschachtelte Blöcke bilden und den aktuellen Block beenden, für die aufgelisteten Segmente separat angegeben werden. Natürlich hängt diese Struktur von der Art des Dokuments ab, sie definiert tatsächlich seine Hierarchie. Die folgende Analysefunktion ist jedoch universell und funktioniert natürlich für alle Strukturvorlagen, die auf diese Weise korrekt eingestellt sind, vorausgesetzt, der Typ des analysierten Dokuments stimmt mit der ausgewählten Vorlage überein.
;; Parse 835 x12 string to hierarchical structure (def loops {"835" {:nested #{"ISA"}} "ISA" {:nested #{"GS"}} "GS" {:nested #{"ST"} :end #{"IEA"}} "ST" {:nested #{"N1" "LX"} :end #{"GE" "ST"}} "N1" {:end #{"SE" "LX" "N1"}} "LX" {:nested #{"CLP"} :end #{"SE" "LX"}} "CLP" {:nested #{"SVC"} :end #{"SE" "LX" "CLP"}} "SVC" {:end #{"SE" "LX" "CLP" "SVC"}}}) (defn parser-core [id ss acc] (let [seg-id (first (first ss)) {:keys [nested end]} (loops id)] (if (or (empty? ss) (and (contains? end seg-id) (not (empty? acc)))) [acc ss] (let [[v ss-] (if (contains? nested seg-id) (parser-core seg-id ss []) [(first ss) (rest ss)])] (recur id ss- (conj acc v)))))) (defn segments [s] (str/split (str/trim s) #"~")) (defn elements [s] (str/split (str/trim s) #"\*")) (defn x12 [s] (first (parser-core "835" (mapv elements (segments (or s ""))) [])))
Unter dem Spoiler vorgestellt
Analyseergebnis [[["ISA" "00" " " "00" " " "ZZ" "EMEDNYBAT " "ZZ" "ETIN " "140305" "0929" "^" "00501" "111111123" "0" "P" ":"] [["GS" "HP" "EMED" "ETIN" "20140301" "09304100" "111111123" "X" "005010X221A1"] [["ST" "835" "35681"] ["BPR" "I" "810.8" "C" "CHK" "" "" "" "" "" "" "" "" "" "" "" "20140331"] ["TRN" "1" "12345" "1512345678"] ["REF" "EV" "XYZ CLEARINGHOUSE"] [["N1" "PR" "DENTAL OF ABC"] ["N3" "225 MAIN STREET"] ["N4" "CENTERVILLE" "PA" "17111"] ["PER" "BL" "JANE DOE" "TE" "9005555555"]] [["N1" "PE" "BAN DDS LLC" "FI" "999994703"]] [["LX" "1"] [["CLP" "7722337" "1" "226" "132" "" "12" "119932404007801"] ["NM1" "QC" "1" "DOE" "SANDY" "" "" "" "MI" "SJD11112"] ["NM1" "82" "1" "BAN" "ERIN" "" "" "" "XX" "1811901945"] ["AMT" "AU" "132"] [["SVC" "AD:D0120" "46" "25"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "21"] ["AMT" "B6" "25"]] [["SVC" "AD:D0220" "25" "14"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "11"] ["AMT" "B6" "14"]] [["SVC" "AD:D0230" "22" "10"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "12"] ["AMT" "B6" "10"]] [["SVC" "AD:D0274" "60" "34"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "26"] ["AMT" "B6" "34"]] [["SVC" "AD:D1110" "73" "49"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "24"] ["AMT" "B6" "49"]]]] [["LX" "2"] [["CLP" "7722337" "1" "119" "74" "" "12" "119932404007801"] ["NM1" "QC" "1" "DOE" "SALLY" "" "" "" "MI" "SJD11111"] ["NM1" "IL" "1" "DOE" "JOHN" "" "" "" "MI" "123456"] ["NM1" "82" "1" "BAN" "ERIN" "" "" "" "XX" "1811901945"] ["AMT" "AU" "74"] [["SVC" "AD:D0120" "46" "25"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "21"] ["AMT" "B6" "25"]] [["SVC" "AD:D1110" "73" "49"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "24"] ["AMT" "B6" "49"]]]] [["LX" "3"] [["CLP" "7722337" "1" "226" "108" "24" "12" "119932404007801"] ["NM1" "QC" "1" "SMITH" "SALLY" "" "" "" "MI" "SJD11113"] ["NM1" "82" "1" "BAN" "ERIN" "" "" "" "XX" "1811901945"] ["AMT" "AU" "132"] [["SVC" "AD:D0120" "46" "25"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "21"] ["AMT" "B6" "25"]] [["SVC" "AD:D0220" "25" "0"] ["DTM" "472" "20140324"] ["CAS" "PR" "3" "14"] ["CAS" "CO" "131" "11"] ["AMT" "B6" "14"]] [["SVC" "AD:D0230" "22" "0"] ["DTM" "472" "20140324"] ["CAS" "PR" "3" "10"] ["CAS" "CO" "131" "12"] ["AMT" "B6" "10"]] [["SVC" "AD:D0274" "60" "34"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "26"] ["AMT" "B6" "34"]] [["SVC" "AD:D1110" "73" "49"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "24"] ["AMT" "B6" "49"]]]] [["LX" "4"] [["CLP" "7722337" "1" "1145" "14" "902" "12" "119932404007801"] ["NM1" "QC" "1" "SMITH" "SAM" "" "" "" "MI" "SJD11116"] ["NM1" "82" "1" "BAN" "ERIN" "" "" "" "XX" "1811901945"] ["AMT" "AU" "14"] [["SVC" "AD:D0220" "25" "14"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "11"] ["AMT" "B6" "14"]] [["SVC" "AD:D2790" "940" "0"] ["DTM" "472" "20140324"] ["CAS" "PR" "3" "756"] ["CAS" "CO" "131" "184"]] [["SVC" "AD:D2950" "180" "0"] ["DTM" "472" "20140324"] ["CAS" "PR" "3" "146"] ["CAS" "CO" "131" "34"]]]] [["LX" "5"] [["CLP" "7722337" "1" "348" "16.8" "44.2" "12" "119932404007801"] ["NM1" "QC" "1" "JONES" "SAM" "" "" "" "MI" "SJD11122"] ["NM1" "82" "1" "BAN" "ERIN" "" "" "" "XX" "1811901945"] ["AMT" "AU" "28"] [["SVC" "AD:D4342" "125" "0"] ["DTM" "472" "20140313"] ["CAS" "CO" "131" "125"]] [["SVC" "AD:D4381" "43" "0"] ["DTM" "472" "20140313"] ["CAS" "PR" "3" "33"] ["CAS" "CO" "131" "10"]] [["SVC" "AD:D2950" "180" "16.8"] ["DTM" "472" "20140313"] ["CAS" "PR" "3" "11.2"] ["CAS" "CO" "131" "152"] ["AMT" "B6" "28"]]]] [["LX" "6"] [["CLP" "7722337" "1" "226" "132" "" "12" "119932404007801"] ["NM1" "QC" "1" "JONES" "SALLY" "" "" "" "MI" "SJD11133"] ["NM1" "82" "1" "BAN" "ERIN" "" "" "" "XX" "1811901945"] ["AMT" "AU" "132"] [["SVC" "AD:D0120" "46" "25"] ["DTM" "472" "20140321"] ["CAS" "CO" "131" "21"] ["AMT" "B6" "25"]] [["SVC" "AD:D0220" "25" "14"] ["DTM" "472" "20140321"] ["CAS" "CO" "131" "11"] ["AMT" "B6" "14"]] [["SVC" "AD:D0230" "22" "10"] ["DTM" "472" "20140321"] ["CAS" "CO" "131" "12"] ["AMT" "B6" "10"]] [["SVC" "AD:D0274" "60" "34"] ["DTM" "472" "20140321"] ["CAS" "CO" "131" "26"] ["AMT" "B6" "34"]] [["SVC" "AD:D1110" "73" "49"] ["DTM" "472" "20140321"] ["CAS" "CO" "131" "24"] ["AMT" "B6" "49"]]]] [["LX" "7"] [["CLP" "7722337" "1" "179" "108" "" "12" "119932404007801"] ["NM1" "QC" "1" "DOE" "SAM" "" "" "" "MI" "SJD99999"] ["NM1" "82" "1" "BAN" "ERIN" "" "" "" "XX" "1811901945"] ["AMT" "AU" "108"] [["SVC" "AD:D0120" "46" "25"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "21"] ["AMT" "B6" "25"]] [["SVC" "AD:D0274" "60" "34"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "26"] ["AMT" "B6" "34"]] [["SVC" "AD:D1110" "73" "49"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "24"] ["AMT" "B6" "49"]]]] [["LX" "8"] [["CLP" "7722337" "1" "129" "82" "" "12" "119932404007801"] ["NM1" "QC" "1" "DOE" "SUE" "" "" "" "MI" "SJD88888"] ["NM1" "82" "1" "BAN" "ERIN" "" "" "" "XX" "1811901945"] ["AMT" "AU" "82"] [["SVC" "AD:D0120" "46" "25"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "21"] ["AMT" "B6" "25"]] [["SVC" "AD:D1120" "54" "37"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "17"] ["AMT" "B6" "37"]] [["SVC" "AD:D1208" "29" "20"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "9"] ["AMT" "B6" "20"]]]] [["LX" "9"] [["CLP" "7722337" "1" "221" "144" "" "12" "119932404007801"] ["NM1" "QC" "1" "DOE" "DONNA" "" "" "" "MI" "SJD77777"] ["NM1" "82" "1" "BAN" "ERIN" "" "" "" "XX" "1811901945"] ["AMT" "AU" "144"] [["SVC" "AD:D0120" "46" "25"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "21"] ["AMT" "B6" "25"]] [["SVC" "AD:D0330" "92" "62"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "30"] ["AMT" "B6" "62"]] [["SVC" "AD:D1120" "54" "37"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "17"] ["AMT" "B6" "37"]] [["SVC" "AD:D1208" "29" "20"] ["DTM" "472" "20140324"] ["CAS" "CO" "131" "9"] ["AMT" "B6" "20"]]]] ["SE" "190" "35681"]] ["GE" "1" "111111123"]] ["IEA" "1" "111111123"]]]
Unser erstes Beispiel ist die hierarchische Struktur von Segmenten.
Tatsächlich kann diese Aufgabe bereits als gelöst betrachtet werden. Ein Dutzend Zeilen Clojure-Code bieten uns einen voll funktionsfähigen Parser für alle X12-Dokumente in einem hierarchischen AST. Um das Bild zu vervollständigen, können Sie ein Beispiel für die Umgehung dieses AST zeigen, um eine nützliche Aufgabe auszuführen - beispielsweise das Erstellen von Strukturen im erforderlichen Format und das Schreiben dieser Informationen in die Datenbank. Unten finden Sie ein Beispiel für Code, der die analysierte Struktur umgeht und eine Liste von darauf basierenden Objekten erstellt. Ein Paar universeller Hilfsfunktionen für den bequemen Zugriff auf Daten, wie sie in AST dargestellt werden, und ein Tree Walker, der ein Objekt bildet und auf jeder Hierarchieebene auf die Originaldaten zugreifen kann.
;; util helpers for extracting information (defn v-prefix? [vp] (and (vector? v) (= p (if (vector? p) (subvec v 0 (min (count v) (count p))) (get v 0))))) (defn items [vp & path] (filter #(v-prefix? (get-in % (vec path)) p) v)) (defn item [vp & path] (first (apply items vp path))) ;; test function for extracting human-readable structure (defn tst [x12-string] (for [isa (items (x12 x12-string) "ISA" 0) gs (items isa "GS" 0) st (items gs "ST" 0) lx (items st "LX" 0) clp (items lx "CLP" 0)] (let [bpr (item st "BPR")] {:message {:received (get-in isa [0 9]) :created (get-in gs [0 4])} :transaction {:check (get (item st "TRN") 2) :payed (get bpr 16) :total (read-string (get bpr 2))} :insurer (get-in (item st ["N1" "PR"] 0) [0 2]) :organization (get-in (item st ["N1" "PE"] 0) [0 2]) :claim {:patient (if-let [x (item clp ["NM1" "QC"])] (str (get x 3) " " (get x 4))) :total (read-string (get-in clp [0 4]))} :services (mapv (fn [svc] {:code (get-in svc [0 1]) :amount (read-string (get-in svc [0 3])) :date (get (item svc ["DTM" "472"]) 2)}) (items clp "SVC" 0))})))
Unter dem Spoiler vorgestellt
Funktionsergebnis ({:message {:received "140305", :created "20140301"}, :transaction {:check "12345", :payed "20140331", :total 810.8}, :insurer "DENTAL OF ABC", :organization "BAN DDS LLC", :claim {:patient "DOE SANDY", :total 132}, :services [{:code "AD:D0120", :amount 25, :date "20140324"} {:code "AD:D0220", :amount 14, :date "20140324"} {:code "AD:D0230", :amount 10, :date "20140324"} {:code "AD:D0274", :amount 34, :date "20140324"} {:code "AD:D1110", :amount 49, :date "20140324"}]} {:message {:received "140305", :created "20140301"}, :transaction {:check "12345", :payed "20140331", :total 810.8}, :insurer "DENTAL OF ABC", :organization "BAN DDS LLC", :claim {:patient "DOE SALLY", :total 74}, :services [{:code "AD:D0120", :amount 25, :date "20140324"} {:code "AD:D1110", :amount 49, :date "20140324"}]} {:message {:received "140305", :created "20140301"}, :transaction {:check "12345", :payed "20140331", :total 810.8}, :insurer "DENTAL OF ABC", :organization "BAN DDS LLC", :claim {:patient "SMITH SALLY", :total 108}, :services [{:code "AD:D0120", :amount 25, :date "20140324"} {:code "AD:D0220", :amount 0, :date "20140324"} {:code "AD:D0230", :amount 0, :date "20140324"} {:code "AD:D0274", :amount 34, :date "20140324"} {:code "AD:D1110", :amount 49, :date "20140324"}]} {:message {:received "140305", :created "20140301"}, :transaction {:check "12345", :payed "20140331", :total 810.8}, :insurer "DENTAL OF ABC", :organization "BAN DDS LLC", :claim {:patient "SMITH SAM", :total 14}, :services [{:code "AD:D0220", :amount 14, :date "20140324"} {:code "AD:D2790", :amount 0, :date "20140324"} {:code "AD:D2950", :amount 0, :date "20140324"}]} {:message {:received "140305", :created "20140301"}, :transaction {:check "12345", :payed "20140331", :total 810.8}, :insurer "DENTAL OF ABC", :organization "BAN DDS LLC", :claim {:patient "JONES SAM", :total 16.8}, :services [{:code "AD:D4342", :amount 0, :date "20140313"} {:code "AD:D4381", :amount 0, :date "20140313"} {:code "AD:D2950", :amount 16.8, :date "20140313"}]} {:message {:received "140305", :created "20140301"}, :transaction {:check "12345", :payed "20140331", :total 810.8}, :insurer "DENTAL OF ABC", :organization "BAN DDS LLC", :claim {:patient "JONES SALLY", :total 132}, :services [{:code "AD:D0120", :amount 25, :date "20140321"} {:code "AD:D0220", :amount 14, :date "20140321"} {:code "AD:D0230", :amount 10, :date "20140321"} {:code "AD:D0274", :amount 34, :date "20140321"} {:code "AD:D1110", :amount 49, :date "20140321"}]} {:message {:received "140305", :created "20140301"}, :transaction {:check "12345", :payed "20140331", :total 810.8}, :insurer "DENTAL OF ABC", :organization "BAN DDS LLC", :claim {:patient "DOE SAM", :total 108}, :services [{:code "AD:D0120", :amount 25, :date "20140324"} {:code "AD:D0274", :amount 34, :date "20140324"} {:code "AD:D1110", :amount 49, :date "20140324"}]} {:message {:received "140305", :created "20140301"}, :transaction {:check "12345", :payed "20140331", :total 810.8}, :insurer "DENTAL OF ABC", :organization "BAN DDS LLC", :claim {:patient "DOE SUE", :total 82}, :services [{:code "AD:D0120", :amount 25, :date "20140324"} {:code "AD:D1120", :amount 37, :date "20140324"} {:code "AD:D1208", :amount 20, :date "20140324"}]} {:message {:received "140305", :created "20140301"}, :transaction {:check "12345", :payed "20140331", :total 810.8}, :insurer "DENTAL OF ABC", :organization "BAN DDS LLC", :claim {:patient "DOE DONNA", :total 144}, :services [{:code "AD:D0120", :amount 25, :date "20140324"} {:code "AD:D0330", :amount 62, :date "20140324"} {:code "AD:D1120", :amount 37, :date "20140324"} {:code "AD:D1208", :amount 20, :date "20140324"}]})
- Sie können
der Tabelle dienen , um in die Datenbank zu schreiben, auf der Benutzeroberfläche zu visualisieren oder auf andere Weise zu verwenden
In meinem Arbeitsprojekt wird ähnlicher Code und ein Algorithmus zum Parsen von X12-Dokumenten verwendet - natürlich mit einer Reihe zusätzlicher Funktionen. Die Codebeispiele in diesem Artikel sind ein minimal funktionierender Prototyp, um den Algorithmus und den Ansatz zu demonstrieren. Entschuldigung, dass es ohne abstrakte Fabriken, kombinatorische Parser, rekursive Grammatiken und andere ernste Dinge nur 3 Dutzend Codezeilen gibt.
Wer möchte, kann mit diesem Parser in jeder Online-Wiedergabe spielen, die Clojure unterstützt - ideone / replit / etc. Von den Abhängigkeiten müssen Sie nur den Namespace
clojure.string verbinden, also vielleicht
clojure.pprint, um einen schönen Ausdruck der Ergebnisse zu erhalten. Sie können versuchen, den Code der Testfunktion zum Erstellen des Objekts, Abrufen anderer Felder aus der analysierten Struktur usw. zu ändern. Beispiele für X12-Dokumente vom Typ 835 (Anspruchsantwort) finden Sie im Internet.