protected String getXMLifiedLogMsg(String type, String resourceId, Throwable t, String... attrs) {

        ContentHandler toXML = new ToXMLContentHandler();
        SafeContentHandler handler = new SafeContentHandler(toXML);
        AttributesImpl attributes = new AttributesImpl();
        attributes.addAttribute("", "resourceId", "resourceId", "", resourceId);
        for (int i = 0; i < attrs.length - 1; i++) {
            attributes.addAttribute("", attrs[i], attrs[i], "", attrs[i + 1]);
        }
        try {
            handler.startDocument();
            handler.startElement("", type, type, attributes);
            if (t != null) {
                StringWriter stackWriter = new StringWriter();
                PrintWriter printWriter = new PrintWriter(stackWriter);
                t.printStackTrace(printWriter);
                printWriter.flush();
                stackWriter.flush();
                char[] chars = stackWriter
                        .toString()
                        .toCharArray();
                handler.characters(chars, 0, chars.length);
            }
            handler.endElement("", type, type);
            handler.endDocument();
        } catch (SAXException e) {
            LOG.warn("error writing xml stream for: {}", resourceId, t);
        }
        return handler.toString();
    }
Use this for structured output that captures resourceId and other attributes.

@param type       entity name for exception
@param resourceId resourceId string
@param t          throwable can be null
@param attrs      (array of key0, value0, key1, value1, etc.)
tika-batch/src/main/java/org/apache/tika/batch/FileResourceConsumer.java