Aqui uma gramática "livre de contexto" para reconhecer XMLs em geral (sem entrar na especificidade dos XSDs).
A tag de identificação por hora tá sendo ignorada, a que tem a forma <?xml ... ?>, mas seria só adicionar ela.
Para facilitar a escrita da gramática livre de contexto, estou usando aqui uma estratégia de "passagem de parâmetro".
Isso facilita a indicação, por exemplo, de tags que se fecham: <p></p>, por exemplo, é derivado de TREE_NODE("p").
Para os casos de passagem de parâmetro, o "tipo" tá indicado. Por exemplo, a produção de TREE_NODE(TAG_NAME ::= IDENTIFICADOR_TAG)
indica que o parâmetro TAG_NAME é feito como a produção IDENTIFICADOR_TAG.