| 1 | HDISVM01 ;BPFO/JRP - PARSE XML DOCUMENT USING SAX;12/20/2004 | 
|---|
| 2 | ;;1.0;HEALTH DATA & INFORMATICS;;Feb 22, 2005 | 
|---|
| 3 | ; | 
|---|
| 4 | SAX(XMLARR,PRSARR) ;Parse XML document using SAX interface | 
|---|
| 5 | ; Input: XMLARR - Global array containing XML document (closed root) | 
|---|
| 6 | ;        PRSARR - Array to output parsed XML document (closed root) | 
|---|
| 7 | ;Output: None | 
|---|
| 8 | ;        @PRSARR@("ESUBS",ESN) = Element name | 
|---|
| 9 | ;        @PRSARR@("EINDX",ElementName) = Subscript number (ESN) | 
|---|
| 10 | ;        @PRSARR@("ASUBS",ESN,ASN) = Attribute name | 
|---|
| 11 | ;        @PRSARR@("AINDX",ESN,AttributeName) = Subscript number (ASN) | 
|---|
| 12 | ;        @PRSARR@("DATA",ESN,Repetition,"V") = Value of element | 
|---|
| 13 | ;        @PRSARR@("DATA",ESN,Repetition,"A",ASN) = Value of attribute | 
|---|
| 14 | ;        @PRSARR@("DATA",ESN1,Rep1,ESN2,Rep2,"V") = Value of child | 
|---|
| 15 | ;                                                   element | 
|---|
| 16 | ;        @PRSARR@("DATA",ESN1,Rep1,ESN2,Rep2,"A",ASN) = Value of child | 
|---|
| 17 | ;                                                       attribute | 
|---|
| 18 | ; Notes : XMLARR must be a global array (i.e. no local arrays) | 
|---|
| 19 | ;       : PRSARR is initialized (i.e KILLed) on input | 
|---|
| 20 | Q:$G(XMLARR)="" | 
|---|
| 21 | Q:'$D(@XMLARR) | 
|---|
| 22 | Q:$G(PRSARR)="" | 
|---|
| 23 | N HDICBK,SUBNUM,TAGNAME | 
|---|
| 24 | N ESUBS,EINDX,ASUBS,AINDX,DATA | 
|---|
| 25 | S ESUBS=$NA(@PRSARR@("ESUBS")) | 
|---|
| 26 | S EINDX=$NA(@PRSARR@("EINDX")) | 
|---|
| 27 | S ASUBS=$NA(@PRSARR@("ASUBS")) | 
|---|
| 28 | S AINDX=$NA(@PRSARR@("AINDX")) | 
|---|
| 29 | S DATA=$NA(@PRSARR@("DATA")) | 
|---|
| 30 | ;Set callbacks | 
|---|
| 31 | S HDICBK("STARTDOCUMENT")="STRTDOC^HDISVM01" | 
|---|
| 32 | S HDICBK("ENDDOCUMENT")="ENDDOC^HDISVM01" | 
|---|
| 33 | S HDICBK("DOCTYPE")="DOCTYPE^HDISVM01" | 
|---|
| 34 | S HDICBK("STARTELEMENT")="STRTLMNT^HDISVM01" | 
|---|
| 35 | S HDICBK("ENDELEMENT")="ENDLMNT^HDISVM01" | 
|---|
| 36 | S HDICBK("CHARACTERS")="CHARS^HDISVM01" | 
|---|
| 37 | S HDICBK("PI")="PI^HDISVM01" | 
|---|
| 38 | S HDICBK("EXTERNAL")="EXTERN^HDISVM01" | 
|---|
| 39 | S HDICBK("NOTATION")="NOTATION^HDISVM01" | 
|---|
| 40 | S HDICBK("COMMENT")="COMMENT^HDISVM01" | 
|---|
| 41 | S HDICBK("ERROR")="ERROR^HDISVM01" | 
|---|
| 42 | ;Parse XML document using SAX | 
|---|
| 43 | K @PRSARR | 
|---|
| 44 | D EN^MXMLPRSE(XMLARR,.HDICBK,"") | 
|---|
| 45 | Q | 
|---|
| 46 | ; | 
|---|
| 47 | STRTDOC ;Start document | 
|---|
| 48 | Q | 
|---|
| 49 | ; | 
|---|
| 50 | ENDDOC ;End document | 
|---|
| 51 | Q | 
|---|
| 52 | ; | 
|---|
| 53 | DOCTYPE(ROOT,PUBID,SYSID) ;DOCTYPE declaration | 
|---|
| 54 | Q | 
|---|
| 55 | ; | 
|---|
| 56 | STRTLMNT(NAME,ATTRLIST) ;Start element | 
|---|
| 57 | N ESN,REP,ATTR,ASN,TMPREF | 
|---|
| 58 | ;Determine element subscript number | 
|---|
| 59 | S ESN=+$G(@EINDX@(NAME)) | 
|---|
| 60 | I 'ESN D | 
|---|
| 61 | .S ESN=1+$O(@ESUBS@(""),-1) | 
|---|
| 62 | .S @ESUBS@(ESN)=NAME | 
|---|
| 63 | .S @EINDX@(NAME)=ESN | 
|---|
| 64 | ;Determine repetition number | 
|---|
| 65 | S REP=1+$O(@DATA@(ESN,""),-1) | 
|---|
| 66 | ;Add element subscript number and repetition number to output array | 
|---|
| 67 | S TMPREF=$$OREF^DILF(DATA) | 
|---|
| 68 | S TMPREF=TMPREF_ESN_","_REP_"," | 
|---|
| 69 | S DATA=$$CREF^DILF(TMPREF) | 
|---|
| 70 | ;Store attributes | 
|---|
| 71 | S ATTR="" | 
|---|
| 72 | F  S ATTR=$O(ATTRLIST(ATTR)) Q:ATTR=""  D | 
|---|
| 73 | .;Get attribute subscript number | 
|---|
| 74 | .S ASN=+$G(@AINDX@(ESN,ATTR)) | 
|---|
| 75 | .I 'ASN D | 
|---|
| 76 | ..S ASN=1+$O(@ASUBS@(""),-1) | 
|---|
| 77 | ..S @ASUBS@(ESN,ASN)=ATTR | 
|---|
| 78 | ..S @AINDX@(ESN,ATTR)=ASN | 
|---|
| 79 | .;Store value | 
|---|
| 80 | .S @DATA@("A",ASN)=ATTRLIST(ATTR) | 
|---|
| 81 | Q | 
|---|
| 82 | ; | 
|---|
| 83 | ENDLMNT(NAME) ;End element | 
|---|
| 84 | N TMPREF,SUBCNT,SUBCHK | 
|---|
| 85 | ;Remove element subscript number and repition number from output array | 
|---|
| 86 | S TMPREF=$$OREF^DILF(DATA) | 
|---|
| 87 | S SUBCNT=$L(TMPREF,",") | 
|---|
| 88 | S SUBCHK=SUBCNT-3 | 
|---|
| 89 | I SUBCHK>0 S TMPREF=$P(TMPREF,",",1,SUBCHK)_"," | 
|---|
| 90 | I SUBCHK<1 S TMPREF=$P(TMPREF,"(",1)_"(" | 
|---|
| 91 | S DATA=$$CREF^DILF(TMPREF) | 
|---|
| 92 | Q | 
|---|
| 93 | ; | 
|---|
| 94 | CHARS(TEXT) ;Non-markup content | 
|---|
| 95 | ;Store element value | 
|---|
| 96 | S @DATA@("V")=TEXT | 
|---|
| 97 | Q | 
|---|
| 98 | ; | 
|---|
| 99 | PI(TARGET,TEXT) ;Processing instruction | 
|---|
| 100 | Q | 
|---|
| 101 | ; | 
|---|
| 102 | EXTERN(SYSID,PUBID,GLOBAL) ;External entity reference | 
|---|
| 103 | Q | 
|---|
| 104 | ; | 
|---|
| 105 | NOTATION(NAME,SYSID,PUBID) ;Notation declaration | 
|---|
| 106 | Q | 
|---|
| 107 | ; | 
|---|
| 108 | COMMENT(TEXT) ;Comment | 
|---|
| 109 | Q | 
|---|
| 110 | ; | 
|---|
| 111 | ERROR(ERR) ;Error | 
|---|
| 112 | Q | 
|---|
| 113 | ; | 
|---|
| 114 | UNESC(TEXT) ;Convert escaped characters | 
|---|
| 115 | ;Assumes TEXT is not corrupt | 
|---|
| 116 | N ESCBEG,ESCEND,ESCTXT,ESCCHAR,OUTPUT | 
|---|
| 117 | S TEXT=$G(TEXT) | 
|---|
| 118 | I TEXT="" Q TEXT | 
|---|
| 119 | I TEXT'["&" Q TEXT | 
|---|
| 120 | ;Do conversion | 
|---|
| 121 | S OUTPUT="" | 
|---|
| 122 | F  Q:TEXT'["&"  D | 
|---|
| 123 | .;Find escaped character | 
|---|
| 124 | .S ESCBEG=$F(TEXT,"&") | 
|---|
| 125 | .S ESCEND=$F(TEXT,";",ESCBEG) | 
|---|
| 126 | .S ESCTXT=$E(TEXT,ESCBEG,ESCEND-2) | 
|---|
| 127 | .;Convert escaped character | 
|---|
| 128 | .S ESCCHAR="" | 
|---|
| 129 | .I ESCTXT="amp" S ESCCHAR="&" | 
|---|
| 130 | .I ESCTXT="lt" S ESCCHAR="<" | 
|---|
| 131 | .I ESCTXT="gt" S ESCCHAR=">" | 
|---|
| 132 | .I ESCTXT="apos" S ESCCHAR="'" | 
|---|
| 133 | .I ESCTXT="quot" S ESCCHAR=$C(34) | 
|---|
| 134 | .;Replace escaped character with actual character | 
|---|
| 135 | .S OUTPUT=OUTPUT_$E(TEXT,1,ESCBEG-2)_ESCCHAR | 
|---|
| 136 | .;Continue processing rest of string | 
|---|
| 137 | .S TEXT=$E(TEXT,ESCEND,$L(TEXT)) | 
|---|
| 138 | ;Add on remainder of text | 
|---|
| 139 | S OUTPUT=OUTPUT_TEXT | 
|---|
| 140 | Q OUTPUT | 
|---|