root      ::= document
document ::= (prolog) ws? (doctype ws) element
doctype        ::= "<!DOCTYPE" ws name (ws externalid)? ws "[" ws fullIntSubset ws "]" ws ">"
fullIntSubset  ::= elementdecl attlistdecl GEDecl PEDecl notationdecl PEReference comment ( ws markupdecl )*
baseName ::= name
middleName ::= name
finalName ::= name
entityrefContent ::= (entityref | [^%&"])* 
markupdecl     ::= elementdecl | attlistdecl | entitydecl | notationdecl | PEReference | comment | pi 
PEReference    ::= "%" name ";" ws
elementdecl    ::= "<!ELEMENT" ws name ws contentspec ws ">" ws
attlistdecl    ::= "<!ATTLIST" ws name ws attdef+ ws ">" ws
entitydecl     ::= GEDecl | PEDecl
GEDecl         ::= "<!ENTITY" ws name ws entityDef ws ">" ws
PEDecl         ::= "<!ENTITY" ws "%" ws name ws entityDef ws ">" ws
entityDef      ::= string | externalid ( ws NDataDecl )?
NDataDecl      ::= "NDATA" ws name
notationdecl   ::= "<!NOTATION" ws name ws externalid ws ">" ws
contentspec ::= name | "EMPTY" | "ANY" | Mixed | children
Mixed       ::= "(" ws "#PCDATA" ( ws "|" ws name )* ws ")" ws
choice      ::= "(" ws cp ( ws "|" ws cp )+ ws ")" occurrence? ws
seq ::= "(" ws cp ( ws "," ws cp )* ws ")" occurrence? ws
children    ::= choice | seq
cp          ::= name occurrence? ws
occurrence  ::= "?" | "*" | "+" ws
attdef         ::= name ws attType ws defaultDecl ws
attType        ::= StringType | TokenizedType | EnumeratedType
StringType     ::= "CDATA" ws
TokenizedType  ::= "ID" ws | "IDREF" ws | "IDREFS" ws | "ENTITY" ws | "ENTITIES" ws | "NMTOKEN" ws | "NMTOKENS" ws | "NOTATION" ws "(" ws name ( ws "|" ws name )* ws ")" ws
EnumeratedType ::= "(" ws name ( ws "|" ws name )* ws ")" ws
defaultDecl    ::= "#REQUIRED" | "#IMPLIED" | ("#FIXED" ws string) | string
externalid ::= "SYSTEM" ws string | "PUBLIC" ws string ws string
prolog         ::= xmldecl ( ws comment | ws pi )*
xmldecl        ::= "<?xml" VersionInfo EncodingDecl? StandaloneDecl? ws? "?>"
Digit          ::= [0-9]
Digits         ::= Digit+
VersionInfo    ::= ws "version" eq ("\"" VersionNum "\"" | "'" VersionNum "'") ws
VersionNum     ::= "1." Digits
EncodingName   ::= [A-Za-z] [A-Za-z0-9._-]+
EncodingValue  ::= "\"" EncodingName "\"" ws
EncodingDecl   ::= ws "encoding" eq EncodingValue ws
StandaloneDecl ::= ws "standalone" eq (("\"" ("yes" | "no") "\"") | ("'" ("yes" | "no") "'")) 
eq ::= ws? "=" ws?
element   ::= emptyelement | openclose
emptyelement ::= "<" name ws attr* "/>" ws
openclose ::= opentag content closetag
opentag   ::= "<" name ws attr* ">" ws
closetag  ::= "</" name ">" ws
attr      ::= namespaceDecl | name eq string ws
namespaceDecl ::= "xmlns" ( ":" name )? eq string ws
entityref ::= "&" name ";" ws
charref   ::= "&#" Digits ";" ws | "&#x" [0-9A-Fa-f]+ ";" ws
content   ::= (chardata | entityref | element | comment | pi | cdata)*
name      ::= QName ws
prefix    ::= [A-Za-z][A-Za-z0-9.-]* 
localPart ::= [A-Za-z][A-Za-z0-9.-]* 
QName     ::= prefix ":" localPart | localPart
chardata  ::= [^<&]+ ws
cdata            ::= "<![CDATA[" [^\]]* "]]>" ws
comment   ::= "<!--" [^-]* "-->" ws 
pi       ::= "<?" pitarget (ws (char* - (char* "?>" char)))? "?>"
piname ::= ":" | [A-Z] | "_" | [a-z]
pitarget      ::= NonXStart | XNonM | XMNonL
NonXStart     ::= [A-WY-Za-wy-z_] NameChar*
XNonM         ::= ("X" | "x") NameCharExceptM NameChar*
XMNonL        ::= ("X" | "x") ("M" | "m") NameCharExceptL NameChar*
NameCharExceptM ::= [A-LN-Za-ln-z0-9._-]
NameCharExceptL ::= [A-KM-Za-km-z0-9._-]
NameChar        ::= [A-Za-z0-9._-]
string    ::= "\"" ( [^"&] | entityref | charref ) "\"" ws | "'" ( [^'&] | entityref | charref )* "'" ws
ws        ::= ([ \t\n\r] ws)?
char    ::= [a-z0-9 ]
