diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 11047f7982..b57eab752a 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -3190,13 +3190,15 @@ ExplainSeparatePlans(ExplainState *es) * Optionally, OR in X_NOWHITESPACE to suppress the whitespace we'd normally * add. * - * XML tag names can't contain white space, so we replace any spaces in - * "tagname" with dashes. + * XML restricts tag names more than our other output formats, eg they can't + * contain white space or slashes. Replace invalid characters with dashes, + * so that for example "I/O Read Time" becomes "I-O-Read-Time". */ static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es) { const char *s; + const char *valid = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_."; if ((flags & X_NOWHITESPACE) == 0) appendStringInfoSpaces(es->str, 2 * es->indent); @@ -3204,7 +3206,7 @@ ExplainXMLTag(const char *tagname, int flags, ExplainState *es) if ((flags & X_CLOSING) != 0) appendStringInfoCharMacro(es->str, '/'); for (s = tagname; *s; s++) - appendStringInfoCharMacro(es->str, (*s == ' ') ? '-' : *s); + appendStringInfoChar(es->str, strchr(valid, *s) ? *s : '-'); if ((flags & X_CLOSE_IMMEDIATE) != 0) appendStringInfoString(es->str, " /"); appendStringInfoCharMacro(es->str, '>');