class XMLAnalyzer extends TextAnalyzer {

    /**
     * Creates a new instance of XMLAnalyzer.
     * @param factory factory to be used
     */
    protected XMLAnalyzer(AnalyzerFactory factory) {
        super(factory);
    }

    /**
     * @return {@code "XML"}
     */
    @Override
    public String getCtagsLang() {
        return "XML";
    }

    /**
     * Gets a version number to be used to tag processed documents so that
     * re-analysis can be re-done later if a stored version number is different
     * from the current implementation.
     * @return 20180112_00
     */
    @Override
    protected int getSpecializedVersionNo() {
        return 20180112_00; // Edit comment above too!
    }

    @Override
    public void analyze(Document doc, StreamSource src, Writer xrefOut) throws IOException, InterruptedException {<FILL_FUNCTION_BODY>}

    /**
     * Creates a wrapped {@link XMLXref} instance.
     * @param reader the data to produce xref for
     * @return xref instance
     */
    @Override
    protected JFlexXref newXref(Reader reader) {
        return new JFlexXref(new XMLXref(reader));
    }
}

        doc.add(new OGKTextField(QueryBuilder.FULL, getReader(src.getStream())));

        if (xrefOut != null) {
            try (Reader in = getReader(src.getStream())) {
                WriteXrefArgs args = new WriteXrefArgs(in, xrefOut);
                args.setProject(project);
                XrefWork xrefWork = new XrefWork(args, this);
                Xrefer xref = xrefWork.getXrefer();

                if (xref != null) {
                    String path = doc.get(QueryBuilder.PATH);
                    addNumLinesLOC(doc, new NumLinesLOC(path, xref.getLineNumber(), xref.getLOC()));
                }
            } catch (ExecutionException e) {
                throw new InterruptedException("failed to generate xref :" + e);
            }
        }
    
<methods>public org.opengrok.indexer.analysis.Xrefer writeXref(org.opengrok.indexer.analysis.WriteXrefArgs) throws java.io.IOException<variables>