static bool isValidIdentifierChar(const QChar &character)
{
    return character.isLetterOrNumber()
        || character == QLatin1Char('_')
        || character.isHighSurrogate()
        || character.isLowSurrogate();
}
QString KdbxXmlWriter::stripInvalidXml10Chars(QString str)
{
    for (int i = str.size() - 1; i >= 0; i--) {
        const QChar ch = str.at(i);
        const ushort uc = ch.unicode();

        if (ch.isLowSurrogate() && i != 0 && str.at(i - 1).isHighSurrogate()) {
            // keep valid surrogate pair
            i--;
        } else if ((uc < 0x20 && uc != 0x09 && uc != 0x0A && uc != 0x0D) // control characters
                   || (uc >= 0x7F && uc <= 0x84) // control characters, valid but discouraged by XML
                   || (uc >= 0x86 && uc <= 0x9F) // control characters, valid but discouraged by XML
                   || (uc > 0xFFFD) // noncharacter
                   || ch.isLowSurrogate() // single low surrogate
                   || ch.isHighSurrogate()) // single high surrogate
        {
            qWarning("Stripping invalid XML 1.0 codepoint %x", uc);
            str.remove(i, 1);
        }
    }

    return str;
}
bool isValidFirstIdentifierChar(const QChar &ch)
{
    return ch.isLetter() || ch == QLatin1Char('_') || ch.isHighSurrogate() || ch.isLowSurrogate();
}