MXMLPRS0 ;SAIC/DKM - XML Parser ;03/09/2005 12:57
;;7.3;TOOLKIT;**58,89,136**;Apr 25, 1995;Build 6
;Per VHA Directive 6402, this routine should not be modified
;=================================================================
; State 0: Prolog
0 N ATTR
S ST=1
D WS()
I '$$NEXT("<?xml") D ERROR(31) Q
D WS(1),ATTRIBS("?xml",.ATTR),WS()
I $$NEXT("?>",3)
D:$G(ATTR("version"))'="1.0" ERROR(10,$G(ATTR("version")))
Q
; State 1: Document type declaration
1 N PUB,SYS
D WS()
Q:$$COMMENT
S ST=2
I '$$NEXT("<!DOCTYPE") D ERROR(32) Q
D WS(1)
S LVL(0)=$$NAME(2),DTD=""
D WS(),SYSPUB(.SYS,.PUB)
I OPTION["V",$L(SYS)!$L(PUB) D
.S DTD=$$EXTRNL(SYS,PUB)
D WS(),CBK("DOCTYPE",LVL(0),PUB,SYS)
I $$NEXT("[") S ST=5
E S:$$NEXT(">",3) ST=6
Q
; State 2: Non-markup text
2 N TXT,CHR
D:'LVL WS()
S TXT=""
F S CHR=$E(XML,CPOS) Q:"<"[CHR!EOD D
.I $$NEXT("&") S TXT=TXT_$$ENTITY
.E S TXT=TXT_CHR,CPOS=CPOS+1
.D:(LLEN-CPOS)<50 READ ;P136
S:CHR="<" ST=3
I $L(TXT) D
.I 'LVL D ERROR(6) Q
.I '$$ISCHILD(LVL(LVL),"#PCDATA",1) D:$L($TR(TXT,WS)) ERROR(27) Q
.D CBK("CHARACTERS",TXT)
Q
; State 3: Markup text
3 N END,ENAME,ATTR
S ST=2
Q:$$COMMENT
Q:$$CDATA
Q:$$PI
Q:'$$NEXT("<",3)
S END=$$NEXT("/"),ENAME=$$NAME(2)
Q:'$L(ENAME)
I 'END D
.S:LVL LVL(LVL,"N")=$$ISCHILD(LVL(LVL),ENAME,LVL(LVL,"N"))
.D:'LVL(LVL,"N") ERROR(24,ENAME)
.D ATTRIBS(ENAME,.ATTR),CBK("STARTELEMENT",ENAME,.ATTR),WS()
.D READ ;*89 Check for more data
.S END=$$NEXT("/"),LVL=LVL+1
.M LVL(LVL)=ERR
.S LVL(LVL)=ENAME,LVL(LVL,"N")=1
.I LVL=1 D
..I $D(LVL(0))#2,LVL(0)'=ENAME D ERROR(15,ENAME) Q
..I '$D(LVL(-1)) S LVL(-1)=""
..E D ERROR(45,ENAME)
I END D
.I LVL>0,$G(LVL(LVL))=ENAME D
..D:'$$ISCHILD(ENAME,"*",LVL(LVL,"N")) ERROR(25)
..D CBK("ENDELEMENT",ENAME)
..K LVL(LVL)
..S LVL=LVL-1
.E D ERROR(5,ENAME)
I $$NEXT(">",3)
Q
; State 5: Internal or external DTD
5 N X,Y
D DOPARAM
Q:$$COMMENT
I CS,$$NEXT("]]>") S CS=CS-1 Q
I $$NEXT("]") D Q
.S ST=6
.D WS()
.I $$NEXT(">",3)
Q:'$$NEXT("<!",3)
S X=$S($$NEXT("["):"[",1:$$NAME(2))
Q:'$L(X)
I $G(DTD(X)) S ST=$$WS(X'="["),ST=DTD(X)
E D ERROR(16,X)
Q
; State 6: Check for external DTD
6 S ST=2
Q:OPTION'["V"
I $G(DTD)'="" D Q
.D OPNDOC(DTD,,"]>"),0
.S ST=5,DTD=""
D:CS ERROR(42)
Q
; State 8: End of DTD declaration
8 D WS()
I $$NEXT(">",3)
S ST=5
Q
; State 20: DTD ENTITY declaration
20 N SYS,PUB,ENAME,TYP,DUP,Z
I $$NEXT("%"),$$WS(1) S TYP=2
E S TYP=1
S ENAME=$$NAME(2)
Q:'$L(ENAME)
S ST=8,ENAME=$S(TYP=2:"%",1:"")_ENAME,DUP=$D(^TMP(ID,$J,"ENT",ENAME))
D NOFWD("UNP",ENAME),ERROR(18,ENAME):DUP,WS(1)
I $$SYSPUB(.SYS,.PUB) D
.D WS()
.I TYP=1,$$NEXT("NDATA") D
..D WS(1)
..S Z=$$NAME(2)
..Q:'$L(Z)
..D FWD("NOT",Z)
..S:'DUP ^TMP(ID,$J,"ENT",ENAME)="",^TMP(ID,$J,"UNP",ENAME)=Z
.E D:'DUP
..S Z=$$EXTRNL(SYS,PUB)
..S:$L(Z) ^TMP(ID,$J,"ENT",ENAME)=Z
E D
.S Z=$$VALUE(1,TYP)
.D:'DUP SETENT(ENAME,Z)
Q
; State 30: DTD ELEMENT declaration
; Builds a parse tree for child elements
30 N STK,ELEMENT,CHILD,START,END,MIXED,X,Z
D DOPARAM
S ELEMENT=$$NAME(2),ST=8
Q:'$L(ELEMENT)
Q:'$$WS(1)
I $D(^TMP(ID,$J,"ELE",ELEMENT)) D ERROR(20,ELEMENT) Q
D NOFWD("ELE",ELEMENT)
S Z=$S($$NEXT("EMPTY"):1,$$NEXT("ANY"):2,1:0),^TMP(ID,$J,"ELE",ELEMENT)=Z
Q:Z
S STK=0,MIXED=0,START=1,END=2
; Check for opening parenthesis
LPAREN D DOPARAM
I MIXED<2 D
.F D WS() Q:'$$NEXT("(",$S(STK:0,1:3)) S STK(STK)=START,STK=STK+1
; Element name, parameter entity, or #PCDATA
D DOPARAM
I 'MIXED,$$NEXT("#PCDATA") S CHILD="#PCDATA",MIXED=2
E S CHILD=$$NAME(2),MIXED=$S('MIXED:1,MIXED=2:3,1:MIXED) Q:'$L(CHILD) D FWD("ELE",CHILD)
I $D(STK(-1,CHILD)) D ERROR(23,CHILD) Q
S STK(-1,CHILD)="",^TMP(ID,$J,"ELE",ELEMENT,START,CHILD)=END
S:CHILD="#PCDATA" ^(END)=""
G:MIXED>1 SEQOPR
; Check for repetition modifier
REPMOD S X=$S($$NEXT("*",$S(MIXED=3:3,1:0)):2,MIXED>1:0,$$NEXT("+"):1,$$NEXT("?"):3,1:0)
S:X=1 ^TMP(ID,$J,"ELE",ELEMENT,END,START)=""
S:X=2 ^TMP(ID,$J,"ELE",ELEMENT,END,START)="",^TMP(ID,$J,"ELE",ELEMENT,START,END)=""
S:X=3 ^TMP(ID,$J,"ELE",ELEMENT,START,END)=""
; Check for sequence operator
SEQOPR D WS()
S X=$S($$NEXT("|"):2,MIXED=2:0,$$NEXT(","):1,1:0)
I X D G LPAREN
.S:'$D(STK(STK,0)) STK(STK,0)=X
.D:STK(STK,0)'=X ERROR(22,$E(",|",X))
.S:X=1 START=END,END=END+1
D WS()
I '$$NEXT(")",$S(STK:3,1:0)) D Q
.S ^TMP(ID,$J,"ELE",ELEMENT,END,"*")=-1
I 'STK D ERROR(21) Q
K STK(STK)
S STK=STK-1,START=STK(STK)
G REPMOD
; State 40: DTD ATTLIST declaration
40 N ELEMENT,ATTRIB,TYPE,DFLT,DUP,X,Y
D DOPARAM
S ELEMENT=$$NAME(2)
Q:'$L(ELEMENT)
Q:'$$WS(1)
D FWD("ELE",ELEMENT)
; Attribute name
ATTNAME D DOPARAM
S ATTRIB=$$NAME(2)
Q:'$L(ATTRIB)
S DUP=$D(^TMP(ID,$J,"ATT",ELEMENT,ATTRIB))
D ERROR(4,ATTRIB):DUP,WS(1)
; Attribute type
S TYPE=$$FNDTKN("TYP")
I 'TYPE D ERROR(33) Q
S:'DUP ^TMP(ID,$J,"ATT",ELEMENT,ATTRIB)=TYPE
D WS(TYPE'=1),NOTN:TYPE=8,ENUM:TYPE=1,WS()
; Default modifier
S DFLT=$$FNDTKN("MOD")
S:'DUP $P(^TMP(ID,$J,"ATT",ELEMENT,ATTRIB),"^",2)=DFLT,Y=$G(^("#ID"))
I TYPE=5 D ; If ID type
.D:DFLT=3 ERROR(34)
.I '$L(Y) S:'DUP ^TMP(ID,$J,"ATT",ELEMENT,"#ID")=ATTRIB
.E D ERROR(35,Y)
; Default value
I DFLT=3!'DFLT D
.D:DFLT WS(1)
.S X=$$VALUE(1)
.Q:DUP
.S $P(^TMP(ID,$J,"ATT",ELEMENT,ATTRIB),"^",3)=X
.D CHKVAL(ELEMENT,ATTRIB,X)
; Next attribute or end of declaration
D WS()
G:'$$NEXT(">") ATTNAME
S ST=5
Q
; Search for a token of the specified group
; GRP=Group id
; Returns token id within group or 0 if none found
FNDTKN(GRP) ;
N TKN
S TKN=""
F S TKN=$O(^TMP(ID,$J,GRP,TKN),-1) Q:$$NEXT(TKN)
Q $S($L(TKN):^TMP(ID,$J,GRP,TKN),1:0)
; Enumerated attribute type
ENUM F D WS() S X=$$NAMETKN(3) Q:'$L(X) D Q:'$$NEXT("|")
.D:TYPE=8 FWD("NOT",X)
.S ^TMP(ID,$J,"ATT",ELEMENT,ATTRIB,X)=""
.D WS()
I $$NEXT(")",3)
Q
; NOTATION attribute type
NOTN D ENUM:$$NEXT("(",3)
Q
; State 50: DTD NOTATION declaration
50 N NAME,SYS,PUB,DUP
S NAME=$$NAME(3),ST=8
Q:'$L(NAME)
Q:'$$WS(1)
S DUP=$D(^TMP(ID,$J,"NOT",NAME))
D NOFWD("NOT",NAME),ERROR(48,NAME):DUP
I '$$SYSPUB(.SYS,.PUB,1) D ERROR(39) Q
Q:DUP
S ^TMP(ID,$J,"NOT",NAME,1)=SYS,^(2)=PUB
D CBK("NOTATION",NAME,SYS,PUB)
Q
; State 60: Conditional sections
60 N CSTYPE,CSCNT,DLM
D DOPARAM
S CSTYPE=$S($$NEXT("INCLUDE"):1,$$NEXT("IGNORE"):2,1:0),ST=5
I 'CSTYPE D ERROR(41) Q
I DOCSTK=1 D ERROR(44) Q
D WS()
Q:'$$NEXT("[",3)
I CSTYPE=1 S CS=CS+1 Q
S CSCNT=1,DLM=""
F D Q:'CSCNT!EOD
.I $L(DLM),$$NEXT(DLM) S DLM=""
.E I $L(DLM) S CPOS=CPOS+1
.E I $$NEXT(QT) S DLM=QT
.E I $$NEXT("'") S DLM="'"
.E I $$NEXT("<![") S CSCNT=CSCNT+1
.E I $$NEXT("]]>") S CSCNT=CSCNT-1
.E S CPOS=CPOS+1
.D:CPOS>LLEN READ
D:CSCNT ERROR(42)
Q
;Local Functions moved from MXMLPRSE
; Execute event callback (if defined)
; EVT=Event name
; Pn=Parameters
CBK(EVT,P1,P2,P3,P4) ;
Q:EOD<0
N EN,PNUM
S EN=$G(CBK(EVT))
Q:EN=""
S PNUM=^TMP(ID,$J,"CBK",EVT)
D @(EN_$P("(.P1,.P2,.P3,.P4",",",1,PNUM)_$S('PNUM:"",1:")"))
Q
; Save current document location for error reporting
; See EPOS^MXMLPRSE
EPOS S ERR("XML")=XML,ERR("POS")=CPOS,ERR("LIN")=LPOS
Q
; Check next characters
; SEQ=character sequence
; ERN=Error to signal if not found (optional)
NEXT(SEQ,ERN) ;
I SEQ=$E(XML,CPOS,CPOS+$L(SEQ)-1) S CPOS=CPOS+$L(SEQ) Q 1
D:$G(ERN) EPOS^MXMLPRSE,ERROR(ERN,SEQ)
Q 0
; Skip whitespace
; ERN=Error to signal if not found (optional)
; Optional return value =1 if whitespace found, 0 if not.
WS(ERN) N CHR,FND
D EPOS^MXMLPRSE
S FND=0
F D:CPOS>LLEN READ S CHR=$E(XML,CPOS) Q:WS'[CHR!EOD D
.S ERN=0,CPOS=CPOS+1,FND=1
D:$G(ERN) ERROR(ERN)
Q:$Q FND
Q
; Shortcuts to functions/procedures defined elsewhere
ATTRIBS(X,Y) D ATTRIBS^MXMLPRSE(.X,.Y) Q
CDATA() Q $$CDATA^MXMLPRSE
CHKVAL(X,Y,Z) D CHKVAL^MXMLPRS1(.X,.Y,.Z) Q
DOPARAM G DOPARAM^MXMLPRSE
ENTITY(X) Q $$ENTITY^MXMLPRSE(.X)
ERROR(X,Y) D ERROR^MXMLPRSE(.X,.Y) Q
EXTRNL(X,Y,Z) Q $$EXTRNL^MXMLPRSE(.X,.Y,.Z)
FWD(X,Y) D FWD^MXMLPRS1(.X,.Y) Q
ISCHILD(X,Y,Z) Q $$ISCHILD^MXMLPRS1(.X,.Y,.Z)
NAME(X) Q $$NAME^MXMLPRSE(.X)
NAMETKN(X) Q $$NAMETKN^MXMLPRSE(.X)
NOFWD(X,Y) D NOFWD^MXMLPRS1(.X,.Y) Q
OPNDOC(X,Y,Z) D OPNDOC^MXMLPRSE(.X,.Y,.Z) Q
PI() Q $$PI^MXMLPRSE
SETENT(X,Y) D SETENT^MXMLPRSE(.X,.Y) Q
SYSPUB(X,Y,Z) Q:$Q $$SYSPUB^MXMLPRSE(.X,.Y,.Z)
D SYSPUB^MXMLPRSE(.X,.Y) Q
READ G READ^MXMLPRSE
VALUE(X,Y) Q $$VALUE^MXMLPRSE(.X,.Y)
MXMLPRS0 ;SAIC/DKM - XML Parser ;03/09/2005 12:57
+1 ;;7.3;TOOLKIT;**58,89,136**;Apr 25, 1995;Build 6
+2 ;Per VHA Directive 6402, this routine should not be modified
+3 ;=================================================================
+4 ; State 0: Prolog
0 NEW ATTR
+1 SET ST=1
+2 DO WS()
+3 IF '$$NEXT("<?xml")
DO ERROR(31)
QUIT
+4 DO WS(1)
DO ATTRIBS("?xml",.ATTR)
DO WS()
+5 IF $$NEXT("?>",3)
+6 IF $GET(ATTR("version"))'="1.0"
DO ERROR(10,$GET(ATTR("version")))
+7 QUIT
+8 ; State 1: Document type declaration
1 NEW PUB,SYS
+1 DO WS()
+2 IF $$COMMENT
QUIT
+3 SET ST=2
+4 IF '$$NEXT("<!DOCTYPE")
DO ERROR(32)
QUIT
+5 DO WS(1)
+6 SET LVL(0)=$$NAME(2)
SET DTD=""
+7 DO WS()
DO SYSPUB(.SYS,.PUB)
+8 IF OPTION["V"
IF $LENGTH(SYS)!$LENGTH(PUB)
Begin DoDot:1
+9 SET DTD=$$EXTRNL(SYS,PUB)
End DoDot:1
+10 DO WS()
DO CBK("DOCTYPE",LVL(0),PUB,SYS)
+11 IF $$NEXT("[")
SET ST=5
+12 IF '$TEST
IF $$NEXT(">",3)
SET ST=6
+13 QUIT
+14 ; State 2: Non-markup text
2 NEW TXT,CHR
+1 IF 'LVL
DO WS()
+2 SET TXT=""
+3 FOR
SET CHR=$EXTRACT(XML,CPOS)
IF "<"[CHR!EOD
QUIT
Begin DoDot:1
+4 IF $$NEXT("&")
SET TXT=TXT_$$ENTITY
+5 IF '$TEST
SET TXT=TXT_CHR
SET CPOS=CPOS+1
+6 ;P136
IF (LLEN-CPOS)<50
DO READ
End DoDot:1
+7 IF CHR="<"
SET ST=3
+8 IF $LENGTH(TXT)
Begin DoDot:1
+9 IF 'LVL
DO ERROR(6)
QUIT
+10 IF '$$ISCHILD(LVL(LVL),"#PCDATA",1)
IF $LENGTH($TRANSLATE(TXT,WS))
DO ERROR(27)
QUIT
+11 DO CBK("CHARACTERS",TXT)
End DoDot:1
+12 QUIT
+13 ; State 3: Markup text
3 NEW END,ENAME,ATTR
+1 SET ST=2
+2 IF $$COMMENT
QUIT
+3 IF $$CDATA
QUIT
+4 IF $$PI
QUIT
+5 IF '$$NEXT("<",3)
QUIT
+6 SET END=$$NEXT("/")
SET ENAME=$$NAME(2)
+7 IF '$LENGTH(ENAME)
QUIT
+8 IF 'END
Begin DoDot:1
+9 IF LVL
SET LVL(LVL,"N")=$$ISCHILD(LVL(LVL),ENAME,LVL(LVL,"N"))
+10 IF 'LVL(LVL,"N")
DO ERROR(24,ENAME)
+11 DO ATTRIBS(ENAME,.ATTR)
DO CBK("STARTELEMENT",ENAME,.ATTR)
DO WS()
+12 ;*89 Check for more data
DO READ
+13 SET END=$$NEXT("/")
SET LVL=LVL+1
+14 MERGE LVL(LVL)=ERR
+15 SET LVL(LVL)=ENAME
SET LVL(LVL,"N")=1
+16 IF LVL=1
Begin DoDot:2
+17 IF $DATA(LVL(0))#2
IF LVL(0)'=ENAME
DO ERROR(15,ENAME)
QUIT
+18 IF '$DATA(LVL(-1))
SET LVL(-1)=""
+19 IF '$TEST
DO ERROR(45,ENAME)
End DoDot:2
End DoDot:1
+20 IF END
Begin DoDot:1
+21 IF LVL>0
IF $GET(LVL(LVL))=ENAME
Begin DoDot:2
+22 IF '$$ISCHILD(ENAME,"*",LVL(LVL,"N"))
DO ERROR(25)
+23 DO CBK("ENDELEMENT",ENAME)
+24 KILL LVL(LVL)
+25 SET LVL=LVL-1
End DoDot:2
+26 IF '$TEST
DO ERROR(5,ENAME)
End DoDot:1
+27 IF $$NEXT(">",3)
+28 QUIT
+29 ; State 5: Internal or external DTD
5 NEW X,Y
+1 DO DOPARAM
+2 IF $$COMMENT
QUIT
+3 IF CS
IF $$NEXT("]]>")
SET CS=CS-1
QUIT
+4 IF $$NEXT("]")
Begin DoDot:1
+5 SET ST=6
+6 DO WS()
+7 IF $$NEXT(">",3)
End DoDot:1
QUIT
+8 IF '$$NEXT("<!",3)
QUIT
+9 SET X=$SELECT($$NEXT("["):"[",1:$$NAME(2))
+10 IF '$LENGTH(X)
QUIT
+11 IF $GET(DTD(X))
SET ST=$$WS(X'="[")
SET ST=DTD(X)
+12 IF '$TEST
DO ERROR(16,X)
+13 QUIT
+14 ; State 6: Check for external DTD
6 SET ST=2
+1 IF OPTION'["V"
QUIT
+2 IF $GET(DTD)'=""
Begin DoDot:1
+3 DO OPNDOC(DTD,,"]>")
DO 0
+4 SET ST=5
SET DTD=""
End DoDot:1
QUIT
+5 IF CS
DO ERROR(42)
+6 QUIT
+7 ; State 8: End of DTD declaration
8 DO WS()
+1 IF $$NEXT(">",3)
+2 SET ST=5
+3 QUIT
+4 ; State 20: DTD ENTITY declaration
20 NEW SYS,PUB,ENAME,TYP,DUP,Z
+1 IF $$NEXT("%")
IF $$WS(1)
SET TYP=2
+2 IF '$TEST
SET TYP=1
+3 SET ENAME=$$NAME(2)
+4 IF '$LENGTH(ENAME)
QUIT
+5 SET ST=8
SET ENAME=$SELECT(TYP=2:"%",1:"")_ENAME
SET DUP=$DATA(^TMP(ID,$JOB,"ENT",ENAME))
+6 DO NOFWD("UNP",ENAME)
IF DUP
DO ERROR(18,ENAME)
DO WS(1)
+7 IF $$SYSPUB(.SYS,.PUB)
Begin DoDot:1
+8 DO WS()
+9 IF TYP=1
IF $$NEXT("NDATA")
Begin DoDot:2
+10 DO WS(1)
+11 SET Z=$$NAME(2)
+12 IF '$LENGTH(Z)
QUIT
+13 DO FWD("NOT",Z)
+14 IF 'DUP
SET ^TMP(ID,$JOB,"ENT",ENAME)=""
SET ^TMP(ID,$JOB,"UNP",ENAME)=Z
End DoDot:2
+15 IF '$TEST
IF 'DUP
Begin DoDot:2
+16 SET Z=$$EXTRNL(SYS,PUB)
+17 IF $LENGTH(Z)
SET ^TMP(ID,$JOB,"ENT",ENAME)=Z
End DoDot:2
End DoDot:1
+18 IF '$TEST
Begin DoDot:1
+19 SET Z=$$VALUE(1,TYP)
+20 IF 'DUP
DO SETENT(ENAME,Z)
End DoDot:1
+21 QUIT
+22 ; State 30: DTD ELEMENT declaration
+23 ; Builds a parse tree for child elements
30 NEW STK,ELEMENT,CHILD,START,END,MIXED,X,Z
+1 DO DOPARAM
+2 SET ELEMENT=$$NAME(2)
SET ST=8
+3 IF '$LENGTH(ELEMENT)
QUIT
+4 IF '$$WS(1)
QUIT
+5 IF $DATA(^TMP(ID,$JOB,"ELE",ELEMENT))
DO ERROR(20,ELEMENT)
QUIT
+6 DO NOFWD("ELE",ELEMENT)
+7 SET Z=$SELECT($$NEXT("EMPTY"):1,$$NEXT("ANY"):2,1:0)
SET ^TMP(ID,$JOB,"ELE",ELEMENT)=Z
+8 IF Z
QUIT
+9 SET STK=0
SET MIXED=0
SET START=1
SET END=2
+10 ; Check for opening parenthesis
LPAREN DO DOPARAM
+1 IF MIXED<2
Begin DoDot:1
+2 FOR
DO WS()
IF '$$NEXT("(",$SELECT(STK
QUIT
SET STK(STK)=START
SET STK=STK+1
End DoDot:1
+3 ; Element name, parameter entity, or #PCDATA
+4 DO DOPARAM
+5 IF 'MIXED
IF $$NEXT("#PCDATA")
SET CHILD="#PCDATA"
SET MIXED=2
+6 IF '$TEST
SET CHILD=$$NAME(2)
SET MIXED=$SELECT('MIXED:1,MIXED=2:3,1:MIXED)
IF '$LENGTH(CHILD)
QUIT
DO FWD("ELE",CHILD)
+7 IF $DATA(STK(-1,CHILD))
DO ERROR(23,CHILD)
QUIT
+8 SET STK(-1,CHILD)=""
SET ^TMP(ID,$JOB,"ELE",ELEMENT,START,CHILD)=END
+9 IF CHILD="#PCDATA"
SET ^(END)=""
+10 IF MIXED>1
GOTO SEQOPR
+11 ; Check for repetition modifier
REPMOD SET X=$SELECT($$NEXT("*",$SELECT(MIXED=3:3,1:0)):2,MIXED>1:0,$$NEXT("+"):1,$$NEXT("?"):3,1:0)
+1 IF X=1
SET ^TMP(ID,$JOB,"ELE",ELEMENT,END,START)=""
+2 IF X=2
SET ^TMP(ID,$JOB,"ELE",ELEMENT,END,START)=""
SET ^TMP(ID,$JOB,"ELE",ELEMENT,START,END)=""
+3 IF X=3
SET ^TMP(ID,$JOB,"ELE",ELEMENT,START,END)=""
+4 ; Check for sequence operator
SEQOPR DO WS()
+1 SET X=$SELECT($$NEXT("|"):2,MIXED=2:0,$$NEXT(","):1,1:0)
+2 IF X
Begin DoDot:1
+3 IF '$DATA(STK(STK,0))
SET STK(STK,0)=X
+4 IF STK(STK,0)'=X
DO ERROR(22,$EXTRACT(",|",X))
+5 IF X=1
SET START=END
SET END=END+1
End DoDot:1
GOTO LPAREN
+6 DO WS()
+7 IF '$$NEXT(")",$SELECT(STK:3,1:0))
Begin DoDot:1
+8 SET ^TMP(ID,$JOB,"ELE",ELEMENT,END,"*")=-1
End DoDot:1
QUIT
+9 IF 'STK
DO ERROR(21)
QUIT
+10 KILL STK(STK)
+11 SET STK=STK-1
SET START=STK(STK)
+12 GOTO REPMOD
+13 ; State 40: DTD ATTLIST declaration
40 NEW ELEMENT,ATTRIB,TYPE,DFLT,DUP,X,Y
+1 DO DOPARAM
+2 SET ELEMENT=$$NAME(2)
+3 IF '$LENGTH(ELEMENT)
QUIT
+4 IF '$$WS(1)
QUIT
+5 DO FWD("ELE",ELEMENT)
+6 ; Attribute name
ATTNAME DO DOPARAM
+1 SET ATTRIB=$$NAME(2)
+2 IF '$LENGTH(ATTRIB)
QUIT
+3 SET DUP=$DATA(^TMP(ID,$JOB,"ATT",ELEMENT,ATTRIB))
+4 IF DUP
DO ERROR(4,ATTRIB)
DO WS(1)
+5 ; Attribute type
+6 SET TYPE=$$FNDTKN("TYP")
+7 IF 'TYPE
DO ERROR(33)
QUIT
+8 IF 'DUP
SET ^TMP(ID,$JOB,"ATT",ELEMENT,ATTRIB)=TYPE
+9 DO WS(TYPE'=1)
IF TYPE=8
DO NOTN
IF TYPE=1
DO ENUM
DO WS()
+10 ; Default modifier
+11 SET DFLT=$$FNDTKN("MOD")
+12 IF 'DUP
SET $PIECE(^TMP(ID,$JOB,"ATT",ELEMENT,ATTRIB),"^",2)=DFLT
SET Y=$GET(^("#ID"))
+13 ; If ID type
IF TYPE=5
Begin DoDot:1
+14 IF DFLT=3
DO ERROR(34)
+15 IF '$LENGTH(Y)
IF 'DUP
SET ^TMP(ID,$JOB,"ATT",ELEMENT,"#ID")=ATTRIB
+16 IF '$TEST
DO ERROR(35,Y)
End DoDot:1
+17 ; Default value
+18 IF DFLT=3!'DFLT
Begin DoDot:1
+19 IF DFLT
DO WS(1)
+20 SET X=$$VALUE(1)
+21 IF DUP
QUIT
+22 SET $PIECE(^TMP(ID,$JOB,"ATT",ELEMENT,ATTRIB),"^",3)=X
+23 DO CHKVAL(ELEMENT,ATTRIB,X)
End DoDot:1
+24 ; Next attribute or end of declaration
+25 DO WS()
+26 IF '$$NEXT(">")
GOTO ATTNAME
+27 SET ST=5
+28 QUIT
+29 ; Search for a token of the specified group
+30 ; GRP=Group id
+31 ; Returns token id within group or 0 if none found
FNDTKN(GRP) ;
+1 NEW TKN
+2 SET TKN=""
+3 FOR
SET TKN=$ORDER(^TMP(ID,$JOB,GRP,TKN),-1)
IF $$NEXT(TKN)
QUIT
+4 QUIT $SELECT($LENGTH(TKN):^TMP(ID,$JOB,GRP,TKN),1:0)
+5 ; Enumerated attribute type
ENUM FOR
DO WS()
SET X=$$NAMETKN(3)
IF '$LENGTH(X)
QUIT
Begin DoDot:1
+1 IF TYPE=8
DO FWD("NOT",X)
+2 SET ^TMP(ID,$JOB,"ATT",ELEMENT,ATTRIB,X)=""
+3 DO WS()
End DoDot:1
IF '$$NEXT("|")
QUIT
+4 IF $$NEXT(")",3)
+5 QUIT
+6 ; NOTATION attribute type
NOTN IF $$NEXT("(",3)
DO ENUM
+1 QUIT
+2 ; State 50: DTD NOTATION declaration
50 NEW NAME,SYS,PUB,DUP
+1 SET NAME=$$NAME(3)
SET ST=8
+2 IF '$LENGTH(NAME)
QUIT
+3 IF '$$WS(1)
QUIT
+4 SET DUP=$DATA(^TMP(ID,$JOB,"NOT",NAME))
+5 DO NOFWD("NOT",NAME)
IF DUP
DO ERROR(48,NAME)
+6 IF '$$SYSPUB(.SYS,.PUB,1)
DO ERROR(39)
QUIT
+7 IF DUP
QUIT
+8 SET ^TMP(ID,$JOB,"NOT",NAME,1)=SYS
SET ^(2)=PUB
+9 DO CBK("NOTATION",NAME,SYS,PUB)
+10 QUIT
+11 ; State 60: Conditional sections
60 NEW CSTYPE,CSCNT,DLM
+1 DO DOPARAM
+2 SET CSTYPE=$SELECT($$NEXT("INCLUDE"):1,$$NEXT("IGNORE"):2,1:0)
SET ST=5
+3 IF 'CSTYPE
DO ERROR(41)
QUIT
+4 IF DOCSTK=1
DO ERROR(44)
QUIT
+5 DO WS()
+6 IF '$$NEXT("[",3)
QUIT
+7 IF CSTYPE=1
SET CS=CS+1
QUIT
+8 SET CSCNT=1
SET DLM=""
+9 FOR
Begin DoDot:1
+10 IF $LENGTH(DLM)
IF $$NEXT(DLM)
SET DLM=""
+11 IF '$TEST
IF $LENGTH(DLM)
SET CPOS=CPOS+1
+12 IF '$TEST
IF $$NEXT(QT)
SET DLM=QT
+13 IF '$TEST
IF $$NEXT("'")
SET DLM="'"
+14 IF '$TEST
IF $$NEXT("<![")
SET CSCNT=CSCNT+1
+15 IF '$TEST
IF $$NEXT("]]>")
SET CSCNT=CSCNT-1
+16 IF '$TEST
SET CPOS=CPOS+1
+17 IF CPOS>LLEN
DO READ
End DoDot:1
IF 'CSCNT!EOD
QUIT
+18 IF CSCNT
DO ERROR(42)
+19 QUIT
+20 ;Local Functions moved from MXMLPRSE
+21 ; Execute event callback (if defined)
+22 ; EVT=Event name
+23 ; Pn=Parameters
CBK(EVT,P1,P2,P3,P4) ;
+1 IF EOD<0
QUIT
+2 NEW EN,PNUM
+3 SET EN=$GET(CBK(EVT))
+4 IF EN=""
QUIT
+5 SET PNUM=^TMP(ID,$JOB,"CBK",EVT)
+6 DO @(EN_$PIECE("(.P1,.P2,.P3,.P4",",",1,PNUM)_$SELECT('PNUM:"",1:")"))
+7 QUIT
+8 ; Save current document location for error reporting
+9 ; See EPOS^MXMLPRSE
EPOS SET ERR("XML")=XML
SET ERR("POS")=CPOS
SET ERR("LIN")=LPOS
+1 QUIT
+2 ; Check next characters
+3 ; SEQ=character sequence
+4 ; ERN=Error to signal if not found (optional)
NEXT(SEQ,ERN) ;
+1 IF SEQ=$EXTRACT(XML,CPOS,CPOS+$LENGTH(SEQ)-1)
SET CPOS=CPOS+$LENGTH(SEQ)
QUIT 1
+2 IF $GET(ERN)
DO EPOS^MXMLPRSE
DO ERROR(ERN,SEQ)
+3 QUIT 0
+4 ; Skip whitespace
+5 ; ERN=Error to signal if not found (optional)
+6 ; Optional return value =1 if whitespace found, 0 if not.
WS(ERN) NEW CHR,FND
+1 DO EPOS^MXMLPRSE
+2 SET FND=0
+3 FOR
IF CPOS>LLEN
DO READ
SET CHR=$EXTRACT(XML,CPOS)
IF WS'[CHR!EOD
QUIT
Begin DoDot:1
+4 SET ERN=0
SET CPOS=CPOS+1
SET FND=1
End DoDot:1
+5 IF $GET(ERN)
DO ERROR(ERN)
+6 IF $QUIT
QUIT FND
+7 QUIT
+8 ; Shortcuts to functions/procedures defined elsewhere
ATTRIBS(X,Y) DO ATTRIBS^MXMLPRSE(.X,.Y)
QUIT
CDATA() QUIT $$CDATA^MXMLPRSE
CHKVAL(X,Y,Z) DO CHKVAL^MXMLPRS1(.X,.Y,.Z)
QUIT
DOPARAM GOTO DOPARAM^MXMLPRSE
ENTITY(X) QUIT $$ENTITY^MXMLPRSE(.X)
ERROR(X,Y) DO ERROR^MXMLPRSE(.X,.Y)
QUIT
EXTRNL(X,Y,Z) QUIT $$EXTRNL^MXMLPRSE(.X,.Y,.Z)
FWD(X,Y) DO FWD^MXMLPRS1(.X,.Y)
QUIT
ISCHILD(X,Y,Z) QUIT $$ISCHILD^MXMLPRS1(.X,.Y,.Z)
NAME(X) QUIT $$NAME^MXMLPRSE(.X)
NAMETKN(X) QUIT $$NAMETKN^MXMLPRSE(.X)
NOFWD(X,Y) DO NOFWD^MXMLPRS1(.X,.Y)
QUIT
OPNDOC(X,Y,Z) DO OPNDOC^MXMLPRSE(.X,.Y,.Z)
QUIT
PI() QUIT $$PI^MXMLPRSE
SETENT(X,Y) DO SETENT^MXMLPRSE(.X,.Y)
QUIT
SYSPUB(X,Y,Z) IF $QUIT
QUIT $$SYSPUB^MXMLPRSE(.X,.Y,.Z)
+1 DO SYSPUB^MXMLPRSE(.X,.Y)
QUIT
READ GOTO READ^MXMLPRSE
VALUE(X,Y) QUIT $$VALUE^MXMLPRSE(.X,.Y)