anchor.diff:        .or(ref('comment'))
         .or(ref('cdata'))
         .star());
  -    def('doctype', string('<!DOCTYPE')
  +    def('doctype', string(OPEN_DOCTYPE)
         .seq(ref('whitespace'))
         .seq(ref('nameToken')
           .or(ref('attributeValue'))
  
positive.code:         .separatedBy(ref('whitespace'))
          .flatten())
        .seq(ref('whitespace').optional())
        .seq(char('>'))
        .pick(2));
      def('document', ref('processing').optional()
        .seq(ref('misc'))
  
negative.code:  */
  class XmlGrammar extends CompositeParser {
  
    static const NAME_START_CHARS = ':A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF'
        '\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001\uD7FF'
        '\uF900-\uFDCF\uFDF0-\uFFFD';
    static const NAME_CHARS = '-.0-9\u00B7\u0300-\u036F\u203F-\u2040$NAME_START_CHARS';
  
    static const DOUBLE_QUOTE = '"';
    static const SINGLE_QUOTE = "'";
    static const OPEN_COMMENT = '<!--';
    static const CLOSE_COMMENT = '-->';
    static const OPEN_CDATA = '<![CDATA[';
    static const CLOSE_CDATA = ']]>';
    static const OPEN_DOCTYPE = '<!DOCTYPE';
    static const CLOSE_DOCTYPE = '>';
    static const OPEN_PROCESSING = '<?';
    static const CLOSE_PROCESSING = '?>';
  
    @override
    void initialize() {
  