* Emit opening or closing XML tag. * * "flags" must contain X_OPENING, X_CLOSING, or X_CLOSE_IMMEDIATE. * Optionally, OR in X_NOWHITESPACE to suppress the whitespace we'd normally * add. * * 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-R
| 5979 | * so that for example "I/O Read Time" becomes "I-O-Read-Time". |
| 5980 | */ |
| 5981 | static void |
| 5982 | ExplainXMLTag(const char *tagname, int flags, ExplainState *es) |
| 5983 | { |
| 5984 | const char *s; |
| 5985 | const char *valid = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_."; |
| 5986 | |
| 5987 | if ((flags & X_NOWHITESPACE) == 0) |
| 5988 | appendStringInfoSpaces(es->str, 2 * es->indent); |
| 5989 | appendStringInfoCharMacro(es->str, '<'); |
| 5990 | if ((flags & X_CLOSING) != 0) |
| 5991 | appendStringInfoCharMacro(es->str, '/'); |
| 5992 | for (s = tagname; *s; s++) |
| 5993 | appendStringInfoChar(es->str, strchr(valid, *s) ? *s : '-'); |
| 5994 | if ((flags & X_CLOSE_IMMEDIATE) != 0) |
| 5995 | appendStringInfoString(es->str, " /"); |
| 5996 | appendStringInfoCharMacro(es->str, '>'); |
| 5997 | if ((flags & X_NOWHITESPACE) == 0) |
| 5998 | appendStringInfoCharMacro(es->str, '\n'); |
| 5999 | } |
| 6000 | |
| 6001 | /* |
| 6002 | * Indent a text-format line. |
no test coverage detected